From 6a16d40efa557bf3e5589e87236e39c6d302dd34 Mon Sep 17 00:00:00 2001 From: Chris Houston Date: Wed, 21 Jan 2026 08:54:07 -0500 Subject: [PATCH 1/2] Umbraco.Core: add XML documentation to all public members Add comprehensive XML documentation comments to all public classes, interfaces, methods, properties, constructors, and enums in Umbraco.Core to resolve SA1600 StyleCop warnings. - Document ~2,500+ files across all folders (Services, Models, Notifications, Configuration, Cache, etc.) - Use , , , tags as appropriate - Apply for interface implementations - Use for type references - Preserve all existing comments This eliminates approximately 15,500 SA1600 warnings from the project. --- .../Actions/ActionDocumentPropertyRead.cs | 8 +- .../Actions/ActionDocumentPropertyWrite.cs | 8 +- .../Blocks/IPartialViewBlockEngine.cs | 10 +- src/Umbraco.Core/Cache/AppCacheExtensions.cs | 70 ++- src/Umbraco.Core/Cache/AppCaches.cs | 10 + .../Cache/AppPolicedCacheDictionary.cs | 5 + src/Umbraco.Core/Cache/CacheKeys.cs | 45 +- .../Cache/DataTypeConfigurationCache.cs | 17 +- .../DataTypeConfigurationCacheRefresher.cs | 12 + src/Umbraco.Core/Cache/DeepCloneAppCache.cs | 5 + src/Umbraco.Core/Cache/DictionaryAppCache.cs | 12 +- .../Cache/DistributedCacheExtensions.cs | 230 +++++++++- .../Cache/FastDictionaryAppCache.cs | 6 + .../Cache/FastDictionaryAppCacheBase.cs | 43 +- .../Cache/IRepositoryCachePolicy.cs | 10 + src/Umbraco.Core/Cache/IRequestCache.cs | 23 +- src/Umbraco.Core/Cache/IValueEditorCache.cs | 17 + src/Umbraco.Core/Cache/NoAppCache.cs | 13 + .../Cache/NoCacheRepositoryCachePolicy.cs | 23 + src/Umbraco.Core/Cache/ObjectCacheAppCache.cs | 5 + .../Cache/Refreshers/CacheRefresherBase.cs | 3 + .../Refreshers/CacheRefresherCollection.cs | 15 + .../CacheRefresherCollectionBuilder.cs | 7 + .../CacheRefresherNotificationFactory.cs | 4 + .../Cache/Refreshers/ICacheRefresher.cs | 45 +- .../Implement/ApplicationCacheRefresher.cs | 17 + .../Implement/ContentTypeCacheRefresher.cs | 46 ++ .../Implement/DataTypeCacheRefresher.cs | 60 +++ .../Implement/DictionaryCacheRefresher.cs | 16 + .../Implement/DomainCacheRefresher.cs | 36 ++ .../Implement/LanguageCacheRefresher.cs | 43 ++ .../Implement/MediaCacheRefresher.cs | 50 ++ .../Implement/MemberCacheRefresher.cs | 54 ++- .../Implement/MemberGroupCacheRefresher.cs | 32 ++ .../Implement/PublicAccessCacheRefresher.cs | 18 + .../Implement/RelationTypeCacheRefresher.cs | 19 +- .../Implement/TemplateCacheRefresher.cs | 18 + .../Implement/UserCacheRefresher.cs | 26 ++ .../Implement/UserGroupCacheRefresher.cs | 14 + .../Implement/ValueEditorCacheRefresher.cs | 22 + .../Refreshers/JsonCacheRefresherBase.cs | 8 + .../Refreshers/PayloadCacheRefresherBase.cs | 5 + .../Cache/RepositoryCacheVersionService.cs | 14 +- src/Umbraco.Core/Cache/SafeLazy.cs | 36 +- src/Umbraco.Core/Cache/ValueEditorCache.cs | 12 + src/Umbraco.Core/CacheSyncService.cs | 9 + .../UmbracoObjectTypeAttribute.cs | 17 +- .../UmbracoUdiTypeAttribute.cs | 13 + .../Collections/CompositeIntStringKey.cs | 15 + .../Collections/CompositeNStringNStringKey.cs | 15 + .../Collections/CompositeStringStringKey.cs | 15 + .../Collections/CompositeTypeTypeKey.cs | 12 + .../Collections/ConcurrentHashSet.cs | 22 + .../Collections/DeepCloneableList.cs | 23 +- .../EventClearingObservableCollection.cs | 15 + .../Collections/ListCloneBehavior.cs | 3 + .../Collections/ObservableDictionary.cs | 32 +- .../Collections/OrderedHashSet.cs | 9 + src/Umbraco.Core/Collections/StackQueue.cs | 30 ++ src/Umbraco.Core/Collections/TopoGraph.cs | 63 +++ .../Composing/CollectionBuilderBase.cs | 7 + .../Composing/ComponentCollection.cs | 18 + .../Composing/ComponentCollectionBuilder.cs | 3 + src/Umbraco.Core/Composing/ComposerGraph.cs | 28 ++ .../DefaultUmbracoAssemblyProvider.cs | 9 + .../Composing/DisableAttribute.cs | 5 + .../FindAssembliesWithReferencesTo.cs | 4 + .../Composing/HideFromTypeFinderAttribute.cs | 5 +- .../Composing/IAssemblyProvider.cs | 5 +- src/Umbraco.Core/Composing/IDiscoverable.cs | 8 + src/Umbraco.Core/Composing/IRuntimeHash.cs | 10 +- src/Umbraco.Core/Composing/ITypeFinder.cs | 7 +- .../Composing/LazyCollectionBuilderBase.cs | 4 + .../Composing/LazyReadOnlyCollection.cs | 18 + src/Umbraco.Core/Composing/LazyResolve.cs | 12 + .../Composing/OrderedCollectionBuilderBase.cs | 3 + .../Composing/ReferenceResolver.cs | 30 +- src/Umbraco.Core/Composing/RuntimeHash.cs | 6 + .../Composing/RuntimeHashPaths.cs | 18 + .../Composing/SetCollectionBuilderBase.cs | 3 + .../Composing/TypeCollectionBuilderBase.cs | 42 +- src/Umbraco.Core/Composing/TypeFinder.cs | 44 +- .../Composing/TypeFinderConfig.cs | 5 + .../Composing/TypeFinderExtensions.cs | 3 + src/Umbraco.Core/Composing/TypeHelper.cs | 14 + .../Composing/VaryingRuntimeHash.cs | 8 + .../WeightedCollectionBuilderBase.cs | 12 + .../ContentSettingsExtensions.cs | 3 + .../Configuration/EntryAssemblyMetadata.cs | 8 + .../Configuration/IConfigManipulator.cs | 3 + .../Configuration/IUmbracoVersion.cs | 3 + .../Configuration/LocalTempStorage.cs | 14 + .../MemberPasswordConfiguration.cs | 6 +- .../Attributes/UmbracoOptionsAttribute.cs | 16 + .../Configuration/Models/BasicAuthSettings.cs | 18 + .../Configuration/Models/CharItem.cs | 7 +- .../Configuration/Models/ContentErrorPage.cs | 4 + .../Models/ContentNotificationSettings.cs | 3 + .../Configuration/Models/ContentSettings.cs | 60 +++ .../Configuration/Models/CoreDebugSettings.cs | 7 + .../Models/DataTypeChangeMode.cs | 16 +- .../Configuration/Models/DataTypesSettings.cs | 8 +- .../Models/DatabaseServerMessengerSettings.cs | 15 + .../Models/DatabaseServerRegistrarSettings.cs | 7 + .../Models/DeliveryApiSettings.cs | 8 +- .../Models/DistributedJobSettings.cs | 13 +- .../Models/ExceptionFilterSettings.cs | 3 + .../Configuration/Models/GlobalSettings.cs | 75 ++- .../HealthChecksNotificationMethodSettings.cs | 11 + .../HealthChecksNotificationSettings.cs | 7 + .../Configuration/Models/HelpPageSettings.cs | 3 + .../Configuration/Models/HostingSettings.cs | 7 + .../Models/ImagingCacheSettings.cs | 19 + .../Models/ImagingResizeSettings.cs | 7 + .../Configuration/Models/LoggingSettings.cs | 15 + .../Models/LuceneDirectoryFactory.cs | 3 + .../MemberPasswordConfigurationSettings.cs | 23 + .../Models/ModelsBuilderSettings.cs | 24 + .../Configuration/Models/NuCacheSettings.cs | 14 + .../Models/RequestHandlerSettings.cs | 18 + .../Configuration/Models/SecuritySettings.cs | 76 ++++ .../Configuration/Models/SmtpSettings.cs | 7 + .../TinyMceToTiptapMigrationSettings.cs | 6 + .../UserPasswordConfigurationSettings.cs | 27 ++ .../DeliveryApiSettingsValidator.cs | 4 + .../Validation/SecuritySettingsValidator.cs | 6 +- .../Models/Validation/ValidatableEntryBase.cs | 4 + .../Models/WebRoutingSettings.cs | 39 ++ .../Configuration/Models/WebhookSettings.cs | 8 + .../ModelsBuilderConfigExtensions.cs | 18 +- .../Configuration/PasswordConfiguration.cs | 15 + .../CharacterReplacementEqualityComparer.cs | 5 + .../Configuration/UmbracoSettings/IChar.cs | 9 + .../IImagingAutoFillUploadField.cs | 20 +- .../IPasswordConfigurationSection.cs | 27 ++ .../UmbracoSettings/ITypeFinderConfig.cs | 6 + .../Configuration/UmbracoVersion.cs | 3 + .../UserPasswordConfiguration.cs | 6 +- src/Umbraco.Core/Constants-Applications.cs | 33 ++ src/Umbraco.Core/Constants-Audit.cs | 14 + src/Umbraco.Core/Constants-Cache.cs | 13 + src/Umbraco.Core/Constants-Composing.cs | 3 + src/Umbraco.Core/Constants-Configuration.cs | 245 ++++++++++ src/Umbraco.Core/Constants-Conventions.cs | 71 +++ src/Umbraco.Core/Constants-DataTypes.cs | 106 +++++ src/Umbraco.Core/Constants-DeploySelector.cs | 23 + src/Umbraco.Core/Constants-Headers.cs | 3 + src/Umbraco.Core/Constants-HealthChecks.cs | 90 +++- src/Umbraco.Core/Constants-HttpClients.cs | 3 + .../Constants-HttpContextItemsKeys.cs | 3 + src/Umbraco.Core/Constants-Icons.cs | 3 + src/Umbraco.Core/Constants-Indexes.cs | 18 + .../Constants-JsonOptionsNames.cs | 9 +- src/Umbraco.Core/Constants-Marketplace.cs | 3 + .../Constants-ModelStateErrorKeys.cs | 8 +- src/Umbraco.Core/Constants-ModelsBuilder.cs | 15 + src/Umbraco.Core/Constants-OAuthClaims.cs | 3 + src/Umbraco.Core/Constants-OAuthClientIds.cs | 5 +- src/Umbraco.Core/Constants-ObjectTypes.cs | 163 +++++++ src/Umbraco.Core/Constants-PropertyEditors.cs | 59 +++ src/Umbraco.Core/Constants-ProviderNames.cs | 9 + src/Umbraco.Core/Constants-ReferenceTypes.cs | 23 + src/Umbraco.Core/Constants-Security.cs | 95 ++++ src/Umbraco.Core/Constants-ServerEvents.cs | 91 ++++ src/Umbraco.Core/Constants-Sql.cs | 3 + src/Umbraco.Core/Constants-SqlTemplates.cs | 89 ++++ src/Umbraco.Core/Constants-System.cs | 3 + .../Constants-SystemDirectories.cs | 34 ++ src/Umbraco.Core/Constants-Telemetry.cs | 139 ++++++ src/Umbraco.Core/Constants-UdiEntityType.cs | 132 ++++++ src/Umbraco.Core/Constants-UrlProviders.cs | 9 + src/Umbraco.Core/Constants-Validation.cs | 20 +- src/Umbraco.Core/Constants-Web.cs | 103 +++++ src/Umbraco.Core/Constants-WebhookEvents.cs | 12 + src/Umbraco.Core/Constants-Webhooks.cs | 3 + src/Umbraco.Core/ConventionsHelper.cs | 8 + .../CustomBooleanTypeConverter.cs | 2 + .../DefaultEventMessagesFactory.cs | 10 + src/Umbraco.Core/DelegateEqualityComparer.cs | 11 + .../NoopOutputExpansionStrategyAccessor.cs | 6 +- .../NoopRequestStartItemProviderAccessor.cs | 6 +- .../DeliveryApi/ApiContentBuilder.cs | 11 + .../DeliveryApi/ApiContentBuilderBase.cs | 32 +- .../DeliveryApi/ApiContentNameProvider.cs | 4 + .../DeliveryApi/ApiContentPathProvider.cs | 12 +- .../DeliveryApi/ApiContentPathResolver.cs | 13 +- .../DeliveryApi/ApiContentResponseBuilder.cs | 16 + .../DeliveryApi/ApiContentRouteBuilder.cs | 18 +- .../DeliveryApi/ApiDocumentUrlService.cs | 10 +- .../DeliveryApi/ApiElementBuilder.cs | 8 + .../DeliveryApi/ApiMediaBuilder.cs | 13 +- .../DeliveryApi/ApiMediaUrlProvider.cs | 10 +- .../DeliveryApi/ApiPropertyRenderer.cs | 10 +- .../DeliveryApi/ApiPublishedContentCache.cs | 17 + .../ContentIndexHandlerCollection.cs | 9 +- .../ContentIndexHandlerCollectionBuilder.cs | 6 +- .../DeliveryApiCompositeIdHandler.cs | 7 +- .../DeliveryApiIndexCompositeIdModel.cs | 11 +- src/Umbraco.Core/DeliveryApi/FieldType.cs | 24 +- .../DeliveryApi/FilterHandlerCollection.cs | 7 + .../FilterHandlerCollectionBuilder.cs | 4 + .../DeliveryApi/FilterOperation.cs | 36 +- src/Umbraco.Core/DeliveryApi/FilterOption.cs | 12 + .../DeliveryApi/IApiAccessService.cs | 5 +- .../DeliveryApi/IApiContentBuilder.cs | 8 + .../DeliveryApi/IApiContentNameProvider.cs | 8 + .../DeliveryApi/IApiContentPathProvider.cs | 9 + .../DeliveryApi/IApiContentPathResolver.cs | 8 + .../DeliveryApi/IApiContentResponseBuilder.cs | 10 +- .../DeliveryApi/IApiContentRouteBuilder.cs | 11 +- .../DeliveryApi/IApiDocumentUrlService.cs | 12 +- .../DeliveryApi/IApiElementBuilder.cs | 8 + .../DeliveryApi/IApiMediaBuilder.cs | 10 +- .../DeliveryApi/IApiMediaUrlProvider.cs | 10 +- .../DeliveryApi/IApiPropertyRenderer.cs | 11 +- .../DeliveryApi/IApiPublishedContentCache.cs | 37 +- .../DeliveryApi/IApiRichTextElementParser.cs | 9 + .../DeliveryApi/IApiRichTextMarkupParser.cs | 10 +- .../ICurrentMemberClaimsProvider.cs | 5 +- .../IDeliveryApiCompositeIdHandler.cs | 16 +- .../DeliveryApi/IOutputExpansionStrategy.cs | 21 +- .../IOutputExpansionStrategyAccessor.cs | 10 +- src/Umbraco.Core/DeliveryApi/IQueryHandler.cs | 3 + .../DeliveryApi/IRequestCultureService.cs | 5 +- .../IRequestMemberAccessService.cs | 12 + .../DeliveryApi/IRequestPreviewService.cs | 5 +- .../DeliveryApi/IRequestRedirectService.cs | 3 + .../DeliveryApi/IRequestRoutingService.cs | 5 +- .../DeliveryApi/IRequestSegmentService.cs | 9 + .../DeliveryApi/IRequestStartItemProvider.cs | 3 + .../IRequestStartItemProviderAccessor.cs | 10 +- .../IncludeInApiVersionAttribute.cs | 9 + src/Umbraco.Core/DeliveryApi/IndexField.cs | 14 +- .../DeliveryApi/IndexFieldValue.cs | 11 +- .../DeliveryApi/NoopApiAccessService.cs | 5 +- .../DeliveryApi/NoopApiContentQueryService.cs | 3 + .../DeliveryApi/NoopApiMediaQueryService.cs | 5 +- .../NoopCurrentMemberClaimsProvider.cs | 6 +- .../NoopOutputExpansionStrategy.cs | 8 +- .../DeliveryApi/NoopRequestCultureService.cs | 10 +- .../NoopRequestMemberAccessService.cs | 5 + .../DeliveryApi/NoopRequestPreviewService.cs | 5 +- .../DeliveryApi/NoopRequestRedirectService.cs | 3 + .../DeliveryApi/NoopRequestRoutingService.cs | 5 +- .../NoopRequestStartItemProvider.cs | 5 +- .../DeliveryApi/SelectorHandlerCollection.cs | 7 + .../SelectorHandlerCollectionBuilder.cs | 4 + .../DeliveryApi/SelectorOption.cs | 9 + .../DeliveryApi/SortHandlerCollection.cs | 7 + .../SortHandlerCollectionBuilder.cs | 4 + src/Umbraco.Core/DeliveryApi/SortOption.cs | 9 + .../DependencyInjection/IUmbracoBuilder.cs | 26 ++ .../ServiceCollectionExtensions.cs | 11 + .../ServiceProviderExtensions.cs | 5 + .../UmbracoBuilder.Collections.cs | 39 +- .../UmbracoBuilder.Configuration.cs | 8 + .../UmbracoBuilder.Events.cs | 14 + .../DependencyInjection/UmbracoBuilder.cs | 12 + src/Umbraco.Core/Diagnostics/MiniDump.cs | 144 +++++- src/Umbraco.Core/Diagnostics/NoopMarchal.cs | 7 + .../Dictionary/DefaultCultureDictionary.cs | 5 + .../DefaultCultureDictionaryFactory.cs | 7 + .../Dictionary/ICultureDictionaryFactory.cs | 19 +- src/Umbraco.Core/Direction.cs | 10 + .../IDistributedLockingMechanismFactory.cs | 3 + .../DynamicRoot/DynamicRootContext.cs | 9 + .../DynamicRoot/DynamicRootNodeQuery.cs | 12 + .../DynamicRoot/DynamicRootService.cs | 23 +- .../DynamicRoot/IDynamicRootService.cs | 5 + .../Origin/ByKeyDynamicRootOriginFinder.cs | 12 + .../ContentRootDynamicRootOriginFinder.cs | 8 + .../Origin/CurrentDynamicRootOriginFinder.cs | 10 + .../DynamicRootOriginFinderCollection.cs | 7 + ...ynamicRootOriginFinderCollectionBuilder.cs | 4 + .../Origin/IDynamicRootOriginFinder.cs | 5 + .../Origin/ParentDynamicRootOriginFinder.cs | 10 + .../Origin/RootDynamicRootOriginFinder.cs | 17 + .../Origin/SiteDynamicRootOriginFinder.cs | 12 + .../QuerySteps/DynamicRootQueryStep.cs | 6 + .../DynamicRootQueryStepCollection.cs | 7 + .../DynamicRootQueryStepCollectionBuilder.cs | 4 + ...thestAncestorOrSelfDynamicRootQueryStep.cs | 11 + ...estDescendantOrSelfDynamicRootQueryStep.cs | 11 + .../QuerySteps/IDynamicRootQueryStep.cs | 16 + .../QuerySteps/IDynamicRootRepository.cs | 27 ++ ...arestAncestorOrSelfDynamicRootQueryStep.cs | 11 + ...estDescendantOrSelfDynamicRootQueryStep.cs | 11 + .../Editors/BackOfficePreviewModel.cs | 17 + .../Editors/EditorValidatorCollection.cs | 10 + .../EditorValidatorCollectionBuilder.cs | 7 + .../Editors/EditorValidator{T}.cs | 9 +- .../Editors/UserEditorAuthorizationHelper.cs | 26 +- src/Umbraco.Core/Enum.cs | 55 +++ ...rningsWhenPublishingNotificationHandler.cs | 17 + ...rningsWhenPublishingNotificationHandler.cs | 22 +- .../CancellableEnumerableObjectEventArgs.cs | 30 ++ .../Events/CancellableEventArgs.cs | 37 ++ .../Events/CancellableObjectEventArgs.cs | 27 ++ ...ancellableObjectEventArgs{TEventObject}.cs | 42 ++ .../Events/ContentCacheEventArgs.cs | 3 + src/Umbraco.Core/Events/CopyEventArgs.cs | 43 ++ src/Umbraco.Core/Events/DeleteEventArgs.cs | 52 +++ .../Events/EventAggregator.Notifications.cs | 81 ++++ src/Umbraco.Core/Events/EventDefinition.cs | 36 ++ .../Events/EventDefinitionBase.cs | 30 ++ src/Umbraco.Core/Events/EventMessage.cs | 9 + src/Umbraco.Core/Events/EventMessageType.cs | 19 + src/Umbraco.Core/Events/EventMessages.cs | 12 + src/Umbraco.Core/Events/EventNameExtractor.cs | 7 + .../Events/EventNameExtractorError.cs | 10 + .../Events/EventNameExtractorResult.cs | 17 + .../Events/ExportedMemberEventArgs.cs | 14 + .../Events/IDeletingMediaFilesEventArgs.cs | 6 + src/Umbraco.Core/Events/IEventDefinition.cs | 15 + .../Events/IEventMessagesAccessor.cs | 6 + .../Events/IEventMessagesFactory.cs | 8 + .../Events/IScopedNotificationPublisher.cs | 3 + src/Umbraco.Core/Events/MoveEventArgs.cs | 19 + src/Umbraco.Core/Events/MoveEventInfo.cs | 42 ++ src/Umbraco.Core/Events/MoveEventInfoBase.cs | 20 +- .../Events/MoveToRecycleBinEventInfo.cs | 11 +- src/Umbraco.Core/Events/NewEventArgs.cs | 75 +++ .../Events/PassThroughEventDispatcher.cs | 8 + src/Umbraco.Core/Events/PublishEventArgs.cs | 19 + .../Events/QueuingEventDispatcher.cs | 5 + .../Events/QueuingEventDispatcherBase.cs | 46 +- .../Events/RecycleBinEventArgs.cs | 27 ++ .../Events/RelateOnCopyNotificationHandler.cs | 15 + src/Umbraco.Core/Events/RolesEventArgs.cs | 14 + src/Umbraco.Core/Events/RollbackEventArgs.cs | 13 + src/Umbraco.Core/Events/SaveEventArgs.cs | 4 + .../Events/ScopedNotificationPublisher.cs | 37 ++ src/Umbraco.Core/Events/SendEmailEventArgs.cs | 10 + .../Events/SendToPublishEventArgs.cs | 13 + .../Events/SupersedeEventAttribute.cs | 7 + .../Events/TransientEventMessagesFactory.cs | 2 + src/Umbraco.Core/Events/TypedEventHandler.cs | 7 + src/Umbraco.Core/Events/UserGroupWithUsers.cs | 18 + .../Events/UserNotificationsHandler.cs | 31 ++ src/Umbraco.Core/ExpressionHelper.cs | 20 + .../Extensions/AssemblyExtensions.cs | 3 + .../Extensions/ClaimsIdentityExtensions.cs | 15 + .../Extensions/ConfigurationExtensions.cs | 5 + .../Extensions/ContentExtensions.cs | 27 ++ .../Extensions/CoreCacheHelperExtensions.cs | 3 + .../DeliveryApiSettingsExtensions.cs | 18 + .../Extensions/DictionaryExtensions.cs | 10 + .../Extensions/EnumerableExtensions.cs | 75 ++- src/Umbraco.Core/Extensions/GuidExtensions.cs | 22 +- .../Extensions/HtmlEncodedStringExtensions.cs | 3 + src/Umbraco.Core/Extensions/IntExtensions.cs | 3 + .../Extensions/LineEndingsExtensions.cs | 5 +- .../Extensions/MediaTypeExtensions.cs | 8 + .../Extensions/MemberTypeExtensions.cs | 15 +- .../PasswordConfigurationExtensions.cs | 8 + .../Extensions/PublishedElementExtensions.cs | 19 +- .../Extensions/PublishedPropertyExtension.cs | 21 + .../Extensions/RuntimeStateExtensions.cs | 3 + .../Extensions/SemVersionExtensions.cs | 13 + .../TemporaryFileServiceExtensions.cs | 10 + .../Extensions/TreeEntityExtensions.cs | 10 +- src/Umbraco.Core/Extensions/TypeExtensions.cs | 153 ++++++- .../Extensions/TypeLoaderExtensions.cs | 3 + .../Extensions/UmbracoBuilderExtensions.cs | 3 + .../UmbracoContextAccessorExtensions.cs | 10 + .../Extensions/UmbracoContextExtensions.cs | 3 + .../Extensions/UserServiceExtensions.cs | 12 +- .../Extensions/VersionExtensions.cs | 20 + .../Extensions/WaitHandleExtensions.cs | 17 +- src/Umbraco.Core/Extensions/XmlExtensions.cs | 71 ++- .../Factories/IInstallSettingsFactory.cs | 7 + .../Factories/IUpgradeSettingsFactory.cs | 9 +- .../Factories/IUserSettingsFactory.cs | 7 + .../Factories/InstallSettingsFactory.cs | 9 + .../Factories/MachineInfoFactory.cs | 9 +- .../Factories/UpgradeSettingsFactory.cs | 12 +- .../Factories/UserSettingsFactory.cs | 23 + src/Umbraco.Core/FireAndForgetRunner.cs | 14 +- src/Umbraco.Core/GuidUdi.cs | 7 + .../Handlers/AuditNotificationsHandler.cs | 102 +++++ .../Handlers/PublicAccessHandler.cs | 38 ++ ...entTypeElementSwitchNotificationHandler.cs | 44 +- src/Umbraco.Core/HashCodeCombiner.cs | 36 ++ src/Umbraco.Core/HashCodeHelper.cs | 42 ++ .../HealthChecks/AcceptableConfiguration.cs | 9 + .../Checks/Data/DatabaseIntegrityCheck.cs | 4 +- .../FolderAndFilePermissionsCheck.cs | 8 +- .../Checks/ProvidedValueValidation.cs | 14 + .../Checks/Security/BaseHttpHeaderCheck.cs | 25 +- .../Checks/Security/ExcessiveHeadersCheck.cs | 8 +- .../HealthChecks/Checks/Security/HstsCheck.cs | 4 +- .../Checks/Security/HttpsCheck.cs | 3 + .../Security/UmbracoApplicationUrlCheck.cs | 16 +- .../HealthChecks/Checks/Services/SmtpCheck.cs | 8 +- .../ConfigurationServiceResult.cs | 9 + src/Umbraco.Core/HealthChecks/HealthCheck.cs | 34 +- .../HealthChecks/HealthCheckAction.cs | 6 + .../HealthChecks/HealthCheckAttribute.cs | 19 +- .../HealthChecks/HealthCheckCollection.cs | 7 + .../HealthCheckCollectionBuilder.cs | 5 + .../HealthChecks/HealthCheckGroup.cs | 9 + .../HealthCheckNotificationMethodAttribute.cs | 9 +- ...HealthCheckNotificationMethodCollection.cs | 7 + ...heckNotificationMethodCollectionBuilder.cs | 4 + .../HealthCheckNotificationVerbosity.cs | 10 + .../HealthChecks/HealthCheckResults.cs | 37 ++ .../HealthChecks/HealthCheckStatus.cs | 8 +- .../EmailNotificationMethod.cs | 16 + .../IHealthCheckNotificationMethod.cs | 11 + .../IMarkdownToHtmlConverter.cs | 9 + .../NotificationMethodBase.cs | 23 + .../HealthChecks/StatusResultType.cs | 18 + .../HealthChecks/ValueComparisonType.cs | 10 + .../Hosting/IApplicationShutdownRegistry.cs | 15 + .../Hosting/IHostingEnvironment.cs | 16 + .../Hosting/IUmbracoApplicationLifetime.cs | 3 + .../NoopApplicationShutdownRegistry.cs | 9 + src/Umbraco.Core/HybridAccessorBase.cs | 11 + .../HybridEventMessagesAccessor.cs | 8 + src/Umbraco.Core/IBackOfficeInfo.cs | 3 + src/Umbraco.Core/ICompletable.cs | 10 + src/Umbraco.Core/IFireAndForgetRunner.cs | 12 +- src/Umbraco.Core/IO/CleanFolderResult.cs | 39 ++ .../IO/CleanFolderResultStatus.cs | 14 + .../IO/DefaultViewContentProvider.cs | 4 + src/Umbraco.Core/IO/FileSystemExtensions.cs | 31 ++ src/Umbraco.Core/IO/FileSystems.cs | 59 ++- .../IO/IDefaultViewContentProvider.cs | 11 + src/Umbraco.Core/IO/IIOHelper.cs | 24 + src/Umbraco.Core/IO/IOHelper.cs | 14 +- src/Umbraco.Core/IO/IOHelperExtensions.cs | 8 + src/Umbraco.Core/IO/IOHelperLinux.cs | 8 + src/Umbraco.Core/IO/IOHelperOSX.cs | 8 + src/Umbraco.Core/IO/IOHelperWindows.cs | 8 + src/Umbraco.Core/IO/IViewHelper.cs | 30 ++ src/Umbraco.Core/IO/MediaFileManager.cs | 26 ++ src/Umbraco.Core/IO/ShadowFileSystem.cs | 104 ++++- src/Umbraco.Core/IO/ShadowFileSystems.cs | 29 +- src/Umbraco.Core/IO/ShadowWrapper.cs | 60 +++ src/Umbraco.Core/IO/ViewHelper.cs | 26 +- src/Umbraco.Core/IRegisteredObject.cs | 10 + .../Install/FilePermissionTest.cs | 18 + .../Install/Models/DatabaseModel.cs | 39 ++ src/Umbraco.Core/InstallLog.cs | 50 ++ .../Installer/NewInstallStepCollection.cs | 9 +- .../NewInstallStepCollectionBuilder.cs | 7 +- src/Umbraco.Core/Installer/StepBase.cs | 14 +- .../Installer/Steps/FilePermissionsStep.cs | 22 +- .../Installer/Steps/RestartRuntimeStep.cs | 21 +- .../Steps/TelemetryIdentifierStep.cs | 22 +- .../Installer/UpgradeStepCollection.cs | 9 +- .../Installer/UpgradeStepCollectionBuilder.cs | 7 +- src/Umbraco.Core/LambdaExpressionCacheKey.cs | 10 + src/Umbraco.Core/Logging/DisposableTimer.cs | 18 +- .../Logging/ILoggingConfiguration.cs | 3 + src/Umbraco.Core/Logging/IMessageTemplates.cs | 6 + src/Umbraco.Core/Logging/IProfilingLogger.cs | 46 +- src/Umbraco.Core/Logging/LogHttpRequest.cs | 3 + src/Umbraco.Core/Logging/LogLevel.cs | 23 + src/Umbraco.Core/Logging/LogProfiler.cs | 13 +- .../Logging/LoggingTaskExtension.cs | 14 + src/Umbraco.Core/Logging/NoopProfiler.cs | 14 + .../Logging/ProfilerExtensions.cs | 3 + src/Umbraco.Core/Logging/ProfilingLogger.cs | 59 +++ src/Umbraco.Core/Logging/Viewer/ILogEntry.cs | 3 + src/Umbraco.Core/Logging/Viewer/LogEntry.cs | 3 + .../Logging/Viewer/LogLevelCounts.cs | 18 + .../Logging/Viewer/LogTemplate.cs | 9 + .../Logging/Viewer/LogTimePeriod.cs | 14 + src/Umbraco.Core/Mail/ISmsSender.cs | 12 +- .../Mail/NotImplementedEmailSender.cs | 11 + .../Mail/NotImplementedSmsSender.cs | 7 +- src/Umbraco.Core/Manifest/BundleOptions.cs | 3 + .../Manifest/IPackageManifestService.cs | 21 +- src/Umbraco.Core/Manifest/PackageManifest.cs | 27 ++ .../Manifest/PackageManifestImportmap.cs | 11 +- src/Umbraco.Core/Mapping/IUmbracoMapper.cs | 7 + .../Mapping/MapDefinitionCollection.cs | 7 + .../Mapping/MapDefinitionCollectionBuilder.cs | 8 + .../Media/EmbedProviders/DailyMotion.cs | 8 + .../Media/EmbedProviders/EmbedProviderBase.cs | 7 + .../EmbedProvidersCollection.cs | 7 + .../EmbedProvidersCollectionBuilder.cs | 4 + .../Media/EmbedProviders/Flickr.cs | 8 + .../Media/EmbedProviders/GettyImages.cs | 9 + .../Media/EmbedProviders/Giphy.cs | 8 + src/Umbraco.Core/Media/EmbedProviders/Hulu.cs | 8 + .../Media/EmbedProviders/Issuu.cs | 8 + .../Media/EmbedProviders/Kickstarter.cs | 8 + .../Media/EmbedProviders/LottieFiles.cs | 8 + .../EmbedProviders/OEmbedProviderBase.cs | 67 +++ .../Media/EmbedProviders/OEmbedResponse.cs | 14 +- .../EmbedProviders/OEmbedResponseBase.cs | 42 ++ .../Media/EmbedProviders/Slideshare.cs | 8 + .../Media/EmbedProviders/SoundCloud.cs | 8 + src/Umbraco.Core/Media/EmbedProviders/Ted.cs | 8 + .../Media/EmbedProviders/Vimeo.cs | 8 + src/Umbraco.Core/Media/EmbedProviders/X.cs | 8 + .../Media/EmbedProviders/Youtube.cs | 8 + src/Umbraco.Core/Media/IEmbedProvider.cs | 11 + .../ImageDimensionExtractorExtensions.cs | 3 + .../Media/ImageUrlGeneratorExtensions.cs | 3 + .../Media/NoopImageDimensionExtractor.cs | 5 + .../Media/NoopImageUrlGenerator.cs | 5 + .../Media/TypeDetector/JpegDetector.cs | 8 + .../TypeDetector/RasterizedTypeDetector.cs | 8 + .../Media/TypeDetector/SvgDetector.cs | 8 + .../Media/TypeDetector/TIFFDetector.cs | 13 + .../Media/UploadAutoFillProperties.cs | 6 + src/Umbraco.Core/Models/AuditItem.cs | 3 + .../Models/Blocks/BlockEditorData.cs | 35 +- .../Models/Blocks/BlockEditorDataConverter.cs | 26 +- .../Models/Blocks/BlockGridArea.cs | 26 +- .../Blocks/BlockGridEditorDataConverter.cs | 7 +- .../Models/Blocks/BlockGridItem.cs | 22 + .../Models/Blocks/BlockGridLayoutAreaItem.cs | 36 ++ .../Models/Blocks/BlockGridLayoutItem.cs | 43 +- .../Models/Blocks/BlockItemData.cs | 52 ++- .../Models/Blocks/BlockItemVariation.cs | 32 +- .../Models/Blocks/BlockLayoutItemBase.cs | 32 +- .../Blocks/BlockListEditorDataConverter.cs | 7 +- .../Models/Blocks/BlockListItem.cs | 22 + .../Models/Blocks/BlockListLayoutItem.cs | 23 +- .../Models/Blocks/BlockModelCollection.cs | 21 +- .../Models/Blocks/BlockPropertyValue.cs | 16 +- src/Umbraco.Core/Models/Blocks/BlockValue.cs | 12 +- .../Blocks/ContentAndSettingsReference.cs | 56 +++ .../Models/Blocks/IBlockLayoutItem.cs | 41 ++ .../Models/Blocks/RichTextBlockItem.cs | 36 +- .../Models/Blocks/RichTextBlockLayoutItem.cs | 23 +- .../RichTextEditorBlockDataConverter.cs | 9 +- .../Blocks/SingleBlockEditorDataConverter.cs | 7 +- .../Models/Blocks/SingleBlockLayoutItem.cs | 3 + src/Umbraco.Core/Models/CacheEntrySettings.cs | 42 +- src/Umbraco.Core/Models/CacheSettings.cs | 35 ++ src/Umbraco.Core/Models/Content.cs | 6 + src/Umbraco.Core/Models/ContentBase.cs | 44 +- .../Models/ContentDataIntegrityReport.cs | 19 + .../Models/ContentDataIntegrityReportEntry.cs | 13 + .../ContentDataIntegrityReportOptions.cs | 3 + .../ContentBlueprintCreateModel.cs | 3 + .../ContentBlueprintUpdateModel.cs | 3 + .../ContentEditing/ContentCreateModel.cs | 8 +- .../ContentEditing/ContentCreateResult.cs | 5 +- .../ContentEditing/ContentCreateResultBase.cs | 12 +- .../ContentCreationModelBase.cs | 14 +- .../ContentEditing/ContentEditingModelBase.cs | 11 +- .../Models/ContentEditing/ContentModelBase.cs | 13 +- .../ContentEditing/ContentUpdateModel.cs | 8 +- .../ContentEditing/ContentUpdateResult.cs | 5 +- .../ContentEditing/ContentUpdateResultBase.cs | 12 +- .../ContentEditing/ContentValidationResult.cs | 8 +- .../Models/ContentEditing/DomainModel.cs | 11 +- .../ContentEditing/DomainUpdateResult.cs | 11 +- .../ContentEditing/DomainsUpdateModel.cs | 11 +- .../GetAvailableCompositionsFilter.cs | 6 + .../Models/ContentEditing/HistoryCleanup.cs | 12 + .../ContentEditing/IHasCultureAndSegment.cs | 11 +- .../Models/ContentEditing/LinkDisplay.cs | 44 ++ .../Models/ContentEditing/MediaCreateModel.cs | 5 +- .../ContentEditing/MediaCreateResult.cs | 5 +- .../Models/ContentEditing/MediaUpdateModel.cs | 5 +- .../ContentEditing/MediaUpdateResult.cs | 5 +- .../ContentEditing/MemberCreateModel.cs | 15 +- .../ContentEditing/MemberCreateResult.cs | 5 +- .../ContentEditing/MemberEditingModelBase.cs | 17 +- .../ContentEditing/MemberUpdateModel.cs | 17 +- .../ContentEditing/MemberUpdateResult.cs | 5 +- .../ContentEditing/PropertyValueModel.cs | 17 +- .../RichTextEditorCommandMode.cs | 14 + .../Models/ContentEditing/SortingModel.cs | 11 +- .../ValidateContentUpdateModel.cs | 6 + .../Validation/PropertyValidationError.cs | 20 +- .../Models/ContentEditing/ValueModelBase.cs | 17 +- .../ContentEditing/ValueResponseModelBase.cs | 8 +- .../Models/ContentEditing/VariantModel.cs | 14 +- .../Models/ContentEditing/VariantModelBase.cs | 14 +- .../Models/ContentModel{TContent}.cs | 8 + .../Models/ContentPropertySettings.cs | 18 +- .../ContentPublishingBranchInternalResult.cs | 18 + .../ContentPublishingBranchItemResult.cs | 11 +- .../ContentPublishingBranchResult.cs | 15 + .../ContentPublishingResult.cs | 11 +- .../CultureAndScheduleModel.cs | 10 + .../CulturePublishScheduleModel.cs | 12 + .../ContentScheduleQueryResult.cs | 14 + .../Models/ContentRepositoryExtensions.cs | 28 +- src/Umbraco.Core/Models/ContentSchedule.cs | 12 + .../Models/ContentScheduleCollection.cs | 36 ++ src/Umbraco.Core/Models/ContentType.cs | 9 + .../ContentTypeAvailableCompositionsResult.cs | 11 + ...ContentTypeAvailableCompositionsResults.cs | 14 + src/Umbraco.Core/Models/ContentTypeBase.cs | 38 ++ .../Models/ContentTypeBaseExtensions.cs | 5 + .../Models/ContentTypeCompositionBase.cs | 20 + .../Models/ContentTypeEditing/Composition.cs | 11 +- .../ContentTypeEditing/CompositionType.cs | 12 +- .../ContentTypeEditing/ContentTypeCleanup.cs | 14 +- .../ContentTypeCreateModel.cs | 11 +- .../ContentTypeEditingModelBase.cs | 41 +- .../ContentTypeModelBase.cs | 14 +- .../ContentTypePropertyContainerModel.cs | 5 +- .../ContentTypePropertyTypeModel.cs | 5 +- .../ContentTypeUpdateModel.cs | 5 +- .../MediaTypeCreateModel.cs | 11 +- .../ContentTypeEditing/MediaTypeModelBase.cs | 5 +- .../MediaTypePropertyContainerModel.cs | 5 +- .../MediaTypePropertyTypeModel.cs | 5 +- .../MediaTypeUpdateModel.cs | 5 +- .../MemberTypeCreateModel.cs | 9 + .../ContentTypeEditing/MemberTypeModelBase.cs | 5 +- .../MemberTypePropertyContainerModel.cs | 5 +- .../MemberTypePropertyTypeModel.cs | 14 +- .../MemberTypeUpdateModel.cs | 5 +- .../PropertyTypeAppearance.cs | 8 +- .../PropertyTypeContainerModelBase.cs | 24 +- .../PropertyTypeModelBase.cs | 38 +- .../PropertyTypeValidation.cs | 17 +- src/Umbraco.Core/Models/ContentTypeSort.cs | 20 +- .../ContentVersionCleanupPolicySettings.cs | 37 ++ src/Umbraco.Core/Models/ContentVersionMeta.cs | 53 +++ src/Umbraco.Core/Models/CultureImpact.cs | 24 + src/Umbraco.Core/Models/DeepCloneHelper.cs | 10 + .../Models/DefaultPayloadModel.cs | 8 +- .../Models/DeliveryApi/ApiBlockGridArea.cs | 24 +- .../Models/DeliveryApi/ApiBlockGridItem.cs | 26 +- .../Models/DeliveryApi/ApiBlockGridModel.cs | 16 +- .../Models/DeliveryApi/ApiBlockItem.cs | 16 +- .../Models/DeliveryApi/ApiBlockListModel.cs | 10 + .../Models/DeliveryApi/ApiContent.cs | 17 + .../Models/DeliveryApi/ApiContentResponse.cs | 22 +- .../Models/DeliveryApi/ApiContentRoute.cs | 13 +- .../Models/DeliveryApi/ApiContentStartItem.cs | 12 +- .../Models/DeliveryApi/ApiElement.cs | 17 + .../Models/DeliveryApi/ApiLink.cs | 55 +++ .../Models/DeliveryApi/ApiMedia.cs | 26 +- .../Models/DeliveryApi/IApiContent.cs | 15 + .../Models/DeliveryApi/IApiContentResponse.cs | 8 +- .../Models/DeliveryApi/IApiContentRoute.cs | 14 +- .../DeliveryApi/IApiContentStartItem.cs | 11 +- .../Models/DeliveryApi/IApiElement.cs | 15 + .../Models/DeliveryApi/IApiMedia.cs | 32 +- .../Models/DeliveryApi/IApiMediaWithCrops.cs | 11 +- .../DeliveryApi/IApiMediaWithCropsResponse.cs | 14 +- .../Models/DeliveryApi/IRichTextElement.cs | 8 +- .../Models/DeliveryApi/ImageCrop.cs | 24 +- .../DeliveryApi/ImageCropCoordinates.cs | 24 +- .../Models/DeliveryApi/ImageFocalPoint.cs | 22 +- .../Models/DeliveryApi/ProtectedAccess.cs | 17 + .../DeliveryApi/RichTextGenericElement.cs | 18 +- .../Models/DeliveryApi/RichTextModel.cs | 15 +- .../Models/DeliveryApi/RichTextRootElement.cs | 21 +- .../Models/DeliveryApi/RichTextTextElement.cs | 13 +- src/Umbraco.Core/Models/DictionaryItem.cs | 9 + .../Models/DictionaryItemExtensions.cs | 3 + .../Models/DictionaryTranslation.cs | 12 + .../Models/Editors/ContentPropertyData.cs | 5 + src/Umbraco.Core/Models/Email/EmailMessage.cs | 67 +++ .../Models/Email/EmailMessageAttachment.cs | 14 + .../Models/Email/NotificationEmailAddress.cs | 11 + .../Models/Email/NotificationEmailModel.cs | 42 ++ .../Models/Entities/BeingDirtyBase.cs | 5 +- .../Models/Entities/ContentEntitySlim.cs | 1 + .../Models/Entities/DocumentEntitySlim.cs | 1 + .../Models/Entities/EntityBase.cs | 13 + .../Models/Entities/EntityExtensions.cs | 3 + .../Models/Entities/EntitySlim.cs | 68 ++- .../Models/Entities/ICanBeDirty.cs | 3 + src/Umbraco.Core/Models/Entities/IEntity.cs | 3 + .../Models/Entities/IMemberEntitySlim.cs | 3 + .../Models/Entities/MediaEntitySlim.cs | 1 + .../Models/Entities/MemberEntitySlim.cs | 3 + .../Models/EntityDataPickerValue.cs | 9 + src/Umbraco.Core/Models/File.cs | 22 +- .../Models/FileSystem/FolderCreateModel.cs | 11 +- .../Models/FileSystem/FolderModelBase.cs | 12 + .../PartialViewFolderCreateModel.cs | 5 +- .../FileSystem/PartialViewFolderModel.cs | 3 + .../FileSystem/ScriptFolderCreateModel.cs | 5 +- .../Models/FileSystem/ScriptFolderModel.cs | 3 + .../FileSystem/StylesheetFolderCreateModel.cs | 5 +- .../FileSystem/StylesheetFolderModel.cs | 3 + src/Umbraco.Core/Models/Folder.cs | 10 + src/Umbraco.Core/Models/IContent.cs | 3 + src/Umbraco.Core/Models/IDataValueEditor.cs | 12 +- src/Umbraco.Core/Models/IDeepCloneable.cs | 4 + src/Umbraco.Core/Models/IDictionaryItem.cs | 3 + .../Models/IDictionaryTranslation.cs | 3 + src/Umbraco.Core/Models/IKeyValue.cs | 9 + src/Umbraco.Core/Models/ILogViewerQuery.cs | 9 + src/Umbraco.Core/Models/IMedia.cs | 3 + src/Umbraco.Core/Models/IMember.cs | 3 + src/Umbraco.Core/Models/INavigationModel.cs | 3 + src/Umbraco.Core/Models/IPartialView.cs | 3 + src/Umbraco.Core/Models/IProperty.cs | 24 + .../Models/IPropertyCollection.cs | 20 + src/Umbraco.Core/Models/IPropertyType.cs | 6 + src/Umbraco.Core/Models/IPropertyValue.cs | 3 + .../Models/IReadOnlyContentBase.cs | 3 + src/Umbraco.Core/Models/IRelation.cs | 9 + .../Models/IRelationTypeWithIsDependency.cs | 6 + src/Umbraco.Core/Models/IScript.cs | 3 + .../Models/IServerRegistration.cs | 6 + src/Umbraco.Core/Models/ISimpleContentType.cs | 9 + src/Umbraco.Core/Models/IStylesheet.cs | 3 + .../Models/IStylesheetProperty.cs | 12 + src/Umbraco.Core/Models/ITwoFactorLogin.cs | 12 + src/Umbraco.Core/Models/IWebhook.cs | 27 +- src/Umbraco.Core/Models/ImageCropAnchor.cs | 38 ++ src/Umbraco.Core/Models/ImageCropMode.cs | 3 + .../Models/ImageUrlGenerationOptions.cs | 81 ++++ .../Models/ImportExport/EntityXmlAnalysis.cs | 12 + .../Models/Installer/ConsentLevelModel.cs | 9 + .../Models/Installer/DatabaseInstallData.cs | 32 +- .../Models/Installer/DatabaseSettingsModel.cs | 41 +- .../Models/Installer/InstallData.cs | 14 +- .../Models/Installer/InstallSettingsModel.cs | 9 + .../Models/Installer/InstallationResult.cs | 5 +- .../Models/Installer/PasswordSettingsModel.cs | 9 + .../Models/Installer/UpgradeSettingsModel.cs | 17 +- .../Models/Installer/UserInstallData.cs | 17 +- .../Models/Installer/UserSettingsModel.cs | 9 + src/Umbraco.Core/Models/KeyValue.cs | 1 + src/Umbraco.Core/Models/Link.cs | 18 + src/Umbraco.Core/Models/LinkType.cs | 14 + src/Umbraco.Core/Models/ListViewPagedModel.cs | 10 + src/Umbraco.Core/Models/LogViewerQuery.cs | 10 + .../Models/Mapping/CommonMapper.cs | 19 + .../Models/Mapping/TagMapDefinition.cs | 13 + src/Umbraco.Core/Models/MediaExtensions.cs | 3 + .../Models/MediaPropertySettings.cs | 16 +- src/Umbraco.Core/Models/MediaType.cs | 3 + src/Umbraco.Core/Models/Member.cs | 20 + src/Umbraco.Core/Models/MemberGroup.cs | 6 + .../Models/MemberPropertyModel.cs | 23 +- .../Models/MemberPropertySettings.cs | 16 +- src/Umbraco.Core/Models/MemberType.cs | 27 ++ .../Models/MemberTypePropertyProfileAccess.cs | 15 + .../ChangeBackOfficeUserPasswordModel.cs | 8 +- .../Membership/ChangeUserPasswordModel.cs | 17 +- .../Models/Membership/ContentPermissionSet.cs | 14 + .../Models/Membership/EntityPermission.cs | 22 + .../Membership/EntityPermissionCollection.cs | 7 + .../Models/Membership/EntityPermissionSet.cs | 5 + .../Models/Membership/ErrorMessageResult.cs | 8 +- .../Models/Membership/IMembershipUser.cs | 27 ++ .../Models/Membership/IProfile.cs | 6 + .../Models/Membership/IReadOnlyUserGroup.cs | 52 ++- src/Umbraco.Core/Models/Membership/IUser.cs | 35 ++ .../Models/Membership/IUserData.cs | 18 + .../Membership/IdentityCreationResult.cs | 19 +- .../Models/Membership/MemberCountType.cs | 11 + .../Models/Membership/MemberExportModel.cs | 42 ++ .../Models/Membership/MemberExportProperty.cs | 21 + .../Models/Membership/MemberFilter.cs | 20 +- .../Models/Membership/MemberKind.cs | 12 +- .../Permissions/DocumentGranularPermission.cs | 17 +- ...DocumentPropertyValueGranularPermission.cs | 16 + .../Permissions/IGranularPermission.cs | 12 + .../Permissions/INodeGranularPermission.cs | 7 + .../UnknownTypeGranularPermission.cs | 12 + .../Models/Membership/ReadOnlyUserGroup.cs | 62 +++ src/Umbraco.Core/Models/Membership/User.cs | 63 ++- .../Models/Membership/UserCreationResult.cs | 11 +- .../Models/Membership/UserData.cs | 8 + .../Models/Membership/UserFilter.cs | 24 +- .../Models/Membership/UserGroup.cs | 19 + .../Models/Membership/UserGroupExtensions.cs | 18 + .../Models/Membership/UserInvitationResult.cs | 8 +- .../Models/Membership/UserKind.cs | 12 +- .../Models/Membership/UserOrder.cs | 44 +- .../Models/Membership/UserProfile.cs | 25 + .../Models/Membership/UserState.cs | 23 + .../Models/Membership/UserUnlockResult.cs | 5 +- .../Models/Navigation/NavigationNode.cs | 40 ++ src/Umbraco.Core/Models/NodePermissions.cs | 8 +- src/Umbraco.Core/Models/Notification.cs | 22 + .../Models/NotificationEmailBodyParams.cs | 36 ++ .../Models/NotificationEmailSubjectParams.cs | 19 + src/Umbraco.Core/Models/OutOfDateType.cs | 16 +- .../Models/Packaging/CompiledPackage.cs | 42 ++ .../Packaging/CompiledPackageContentBase.cs | 8 + .../Models/Packaging/InstallWarnings.cs | 9 + src/Umbraco.Core/Models/PagedModel.cs | 20 +- src/Umbraco.Core/Models/PagedResult.cs | 18 + src/Umbraco.Core/Models/PagedResult{T}.cs | 9 + src/Umbraco.Core/Models/PartialView.cs | 9 + .../Models/PartialViewCreateModel.cs | 6 +- .../Models/PartialViewRenameModel.cs | 3 + .../Models/PartialViewUpdateModel.cs | 6 +- src/Umbraco.Core/Models/Property.cs | 63 ++- src/Umbraco.Core/Models/PropertyCollection.cs | 7 + src/Umbraco.Core/Models/PropertyGroup.cs | 14 + .../Models/PropertyGroupCollection.cs | 37 ++ .../Models/PropertyGroupExtensions.cs | 13 + .../Models/PropertyTagsExtensions.cs | 22 +- .../Models/PropertyTypeCollection.cs | 44 +- src/Umbraco.Core/Models/PublicAccessEntry.cs | 56 +++ .../Models/PublicAccessEntrySlim.cs | 20 +- .../PublicAccessNodesValidationResult.cs | 15 +- src/Umbraco.Core/Models/PublicAccessRule.cs | 20 + .../HybridVariationContextAccessor.cs | 4 + .../PublishedContent/IPublishedMember.cs | 34 ++ .../PublishedContent/IPublishedMemberCache.cs | 3 + .../PublishedContent/IPublishedProperty.cs | 3 + .../Models/PublishedContent/ModelType.cs | 65 ++- .../PublishedContent/PublishedContentBase.cs | 11 +- .../PublishedContentTypeConverter.cs | 8 + .../PublishedContentTypeFactory.cs | 6 + .../PublishedContent/PublishedSearchResult.cs | 14 + .../PublishedContent/RawValueProperty.cs | 13 + .../ThreadCultureVariationContextAccessor.cs | 1 + .../VariationContextAccessorExtensions.cs | 35 ++ .../Models/ReadOnlyContentBaseAdapter.cs | 25 + src/Umbraco.Core/Models/ReadOnlyRelation.cs | 36 ++ .../RedirectUrlManagement/RedirectStatus.cs | 12 +- src/Umbraco.Core/Models/Relation.cs | 2 + .../Models/RelationDirectionFilter.cs | 11 + src/Umbraco.Core/Models/RelationItem.cs | 45 ++ src/Umbraco.Core/Models/RelationItemModel.cs | 39 ++ src/Umbraco.Core/Models/RelationType.cs | 25 +- .../Models/RelationTypeExtensions.cs | 16 + .../Models/RequestPasswordResetModel.cs | 6 + ...esolvedUserToUserGroupManipulationModel.cs | 11 +- src/Umbraco.Core/Models/Script.cs | 9 + src/Umbraco.Core/Models/ScriptCreateModel.cs | 5 +- src/Umbraco.Core/Models/ScriptRenameModel.cs | 5 +- src/Umbraco.Core/Models/ScriptUpdateModel.cs | 6 +- src/Umbraco.Core/Models/Segment.cs | 12 + .../Models/ServerEvents/ServerEvent.cs | 14 +- .../SeverEventAuthorizationResult.cs | 5 +- src/Umbraco.Core/Models/ServerInformation.cs | 17 + src/Umbraco.Core/Models/SimpleContentType.cs | 17 + .../Models/SimpleValidationModel.cs | 14 + src/Umbraco.Core/Models/Stylesheet.cs | 12 + .../Models/StylesheetCreateModel.cs | 5 +- src/Umbraco.Core/Models/StylesheetProperty.cs | 6 + .../Models/StylesheetRenameModel.cs | 3 + .../Models/StylesheetUpdateModel.cs | 5 +- src/Umbraco.Core/Models/TagModel.cs | 15 + .../Models/TaggableObjectTypes.cs | 15 + src/Umbraco.Core/Models/TelemetryLevel.cs | 14 + src/Umbraco.Core/Models/TelemetryResource.cs | 6 + src/Umbraco.Core/Models/Template.cs | 42 ++ .../Models/TemplateQuery/ContentTypeModel.cs | 9 + .../Models/TemplateQuery/Operator.cs | 34 ++ .../Models/TemplateQuery/OperatorFactory.cs | 10 + .../Models/TemplateQuery/OperatorTerm.cs | 21 + .../Models/TemplateQuery/PropertyModel.cs | 12 + .../Models/TemplateQuery/QueryCondition.cs | 12 + .../TemplateQuery/QueryConditionExtensions.cs | 10 + .../Models/TemplateQuery/QueryModel.cs | 18 + .../Models/TemplateQuery/SortExpression.cs | 9 + .../Models/TemplateQuery/SourceModel.cs | 9 + .../CreateTemporaryFileModel.cs | 5 +- .../TemporaryFileUpload/TemporaryFileModel.cs | 6 + .../TemporaryFileModelBase.cs | 12 + .../Models/TextFileCreateModel.cs | 20 +- .../Models/TextFileRenameModel.cs | 3 + .../Models/TextFileUpdateModel.cs | 5 +- src/Umbraco.Core/Models/TwoFactorLogin.cs | 15 + .../Models/UmbracoUserExtensions.cs | 23 + src/Umbraco.Core/Models/UsageInformation.cs | 14 + src/Umbraco.Core/Models/UserCreateModel.cs | 26 +- src/Umbraco.Core/Models/UserExtensions.cs | 93 ++++ .../Models/UserExternalLoginProviderModel.cs | 28 ++ .../Models/UserForgotPasswordMessage.cs | 9 + .../Models/UserInvitationMessage.cs | 17 +- src/Umbraco.Core/Models/UserInviteModel.cs | 11 +- .../Models/UserResendInviteModel.cs | 12 +- .../Models/UserTwoFactorProviderModel.cs | 14 + src/Umbraco.Core/Models/UserUpdateModel.cs | 41 +- .../UsersToUserGroupManipulationModel.cs | 14 + .../Validation/PropertyValidationContext.cs | 27 +- src/Umbraco.Core/Models/Verify2FACodeModel.cs | 8 +- src/Umbraco.Core/Models/Webhook.cs | 35 ++ src/Umbraco.Core/Models/WebhookLog.cs | 47 +- src/Umbraco.Core/Models/WebhookRequest.cs | 20 +- src/Umbraco.Core/Net/IIpResolver.cs | 7 + src/Umbraco.Core/Net/ISessionIdResolver.cs | 6 + src/Umbraco.Core/Net/IUserAgentProvider.cs | 7 + src/Umbraco.Core/Net/NullSessionIdResolver.cs | 7 + .../ApplicationCacheRefresherNotification.cs | 15 + .../AssignedMemberRolesNotification.cs | 19 +- ...ssignedUserGroupPermissionsNotification.cs | 18 + .../CacheRefresherNotification.cs | 21 +- .../CancelableEnumerableObjectNotification.cs | 19 + .../Notifications/CancelableNotification.cs | 22 + .../CancelableObjectNotification.cs | 19 + .../ContentCacheRefresherNotification.cs | 19 +- .../ContentCopiedNotification.cs | 39 +- .../ContentCopyingNotification.cs | 35 +- .../ContentDeletedBlueprintNotification.cs | 18 +- .../ContentDeletedNotification.cs | 12 +- .../ContentDeletingNotification.cs | 17 +- .../ContentEmptiedRecycleBinNotification.cs | 17 +- .../ContentEmptyingRecycleBinNotification.cs | 17 +- .../Notifications/ContentMovedNotification.cs | 24 +- .../ContentMovedToRecycleBinNotification.cs | 18 +- .../ContentMovingNotification.cs | 24 +- .../ContentMovingToRecycleBinNotification.cs | 17 +- .../ContentNotificationExtensions.cs | 16 + .../ContentPublishedNotification.cs | 28 +- .../ContentPublishingNotification.cs | 19 +- .../ContentRefreshNotification.cs | 16 + .../ContentRolledBackNotification.cs | 12 +- .../ContentRollingBackNotification.cs | 12 +- .../ContentSavedBlueprintNotification.cs | 19 +- .../Notifications/ContentSavedNotification.cs | 16 +- .../ContentSavingNotification.cs | 16 +- .../ContentScaffoldedNotification.cs | 9 +- .../ContentSendingToPublishNotification.cs | 15 +- .../ContentSentToPublishNotification.cs | 11 +- .../ContentSortedNotification.cs | 7 +- .../ContentSortingNotification.cs | 11 +- .../ContentTreeChangeNotification.cs | 45 ++ .../ContentTypeCacheRefresherNotification.cs | 15 + .../ContentTypeChangeNotification.cs | 26 ++ .../ContentTypeChangedNotification.cs | 20 +- .../ContentTypeDeletedNotification.cs | 20 +- .../ContentTypeDeletingNotification.cs | 20 +- .../ContentTypeMovedNotification.cs | 18 +- .../ContentTypeMovingNotification.cs | 22 +- .../ContentTypeRefreshNotification.cs | 22 + .../ContentTypeRefreshedNotification.cs | 22 + .../ContentTypeSavedNotification.cs | 20 +- .../ContentTypeSavingNotification.cs | 20 +- .../ContentUnpublishedNotification.cs | 20 +- .../ContentUnpublishingNotification.cs | 20 +- .../Notifications/CopiedNotification.cs | 40 ++ .../Notifications/CopyingNotification.cs | 35 ++ .../Notifications/CreatedNotification.cs | 16 + .../Notifications/CreatingNotification.cs | 16 + .../DataTypeCacheRefresherNotification.cs | 15 + .../DataTypeDeletedNotification.cs | 15 +- .../DataTypeDeletingNotification.cs | 15 +- .../DataTypeMovedNotification.cs | 11 +- .../DataTypeMovingNotification.cs | 15 +- .../DataTypeSavedNotification.cs | 20 +- .../DataTypeSavingNotification.cs | 20 +- .../Notifications/DeletedNotification.cs | 21 + .../DeletedVersionsNotification.cs | 16 + .../DeletedVersionsNotificationBase.cs | 32 ++ .../Notifications/DeletingNotification.cs | 21 + .../DeletingVersionsNotification.cs | 17 + .../DictionaryCacheRefresherNotification.cs | 15 + .../DictionaryItemDeletingNotification.cs | 25 +- .../DictionaryItemMovedNotification.cs | 24 +- .../DictionaryItemMovingNotification.cs | 24 +- .../DictionaryItemSavedNotification.cs | 23 +- .../DictionaryItemSavingNotification.cs | 24 +- .../DomainCacheRefresherNotification.cs | 15 + .../DomainDeletedNotification.cs | 19 + .../DomainDeletingNotification.cs | 19 + .../Notifications/DomainSavedNotification.cs | 19 + .../Notifications/DomainSavingNotification.cs | 19 + .../EmptiedRecycleBinNotification.cs | 19 + .../EmptyingRecycleBinNotification.cs | 20 + .../EntityContainerDeletedNotification.cs | 15 + .../EntityContainerDeletingNotification.cs | 15 + .../EntityContainerRenamedNotification.cs | 15 + .../EntityContainerRenamingNotification.cs | 15 + .../EntityContainerSavedNotification.cs | 15 + .../EntityContainerSavingNotification.cs | 15 + .../EntityRefreshNotification.cs | 18 + .../EnumerableObjectNotification.cs | 18 + .../ExportedMemberNotification.cs | 21 + .../HealthCheckCompletedNotification.cs | 17 + .../Notifications/ICancelableNotification.cs | 13 + .../Notifications/IStatefulNotification.cs | 16 + .../ImportedPackageNotification.cs | 17 + .../ImportingPackageNotification.cs | 18 + .../LanguageCacheRefresherNotification.cs | 15 + .../LanguageDeletedNotification.cs | 8 +- .../LanguageDeletingNotification.cs | 12 + .../LanguageSavedNotification.cs | 12 + .../LanguageSavingNotification.cs | 12 + .../MediaCacheRefresherNotification.cs | 20 +- .../Notifications/MediaDeletedNotification.cs | 12 +- .../MediaDeletingNotification.cs | 23 +- .../MediaEmptiedRecycleBinNotification.cs | 12 + .../MediaEmptyingRecycleBinNotification.cs | 12 + .../Notifications/MediaMovedNotification.cs | 24 +- .../MediaMovedToRecycleBinNotification.cs | 16 +- .../Notifications/MediaMovingNotification.cs | 24 +- .../MediaMovingToRecycleBinNotification.cs | 17 +- .../Notifications/MediaRefreshNotification.cs | 15 + .../Notifications/MediaSavedNotification.cs | 23 +- .../Notifications/MediaSavingNotification.cs | 23 +- .../MediaTreeChangeNotification.cs | 36 ++ .../MediaTypeChangedNotification.cs | 12 + .../MediaTypeDeletedNotification.cs | 6 + .../MediaTypeDeletingNotification.cs | 6 + .../MediaTypeMovedNotification.cs | 6 + .../MediaTypeMovingNotification.cs | 6 + .../MediaTypeRefreshedNotification.cs | 22 + .../MediaTypeSavedNotification.cs | 26 +- .../MediaTypeSavingNotification.cs | 26 +- .../MemberCacheRefresherNotification.cs | 20 +- .../MemberDeletedNotification.cs | 17 +- .../MemberDeletingNotification.cs | 23 +- .../MemberGroupCacheRefresherNotification.cs | 15 + .../MemberGroupDeletedNotification.cs | 15 + .../MemberGroupDeletingNotification.cs | 22 + .../MemberGroupSavedNotification.cs | 22 + .../MemberGroupSavingNotification.cs | 22 + .../MemberRefreshNotification.cs | 15 + .../Notifications/MemberRolesNotification.cs | 20 + .../Notifications/MemberSavedNotification.cs | 24 +- .../Notifications/MemberSavingNotification.cs | 23 +- .../MemberTwoFactorRequestedNotification.cs | 17 + .../MemberTypeChangedNotification.cs | 12 + .../MemberTypeDeletedNotification.cs | 6 + .../MemberTypeDeletingNotification.cs | 6 + .../MemberTypeMovedNotification.cs | 22 + .../MemberTypeMovingNotification.cs | 12 + .../MemberTypeRefreshedNotification.cs | 22 + .../MemberTypeSavedNotification.cs | 26 +- .../MemberTypeSavingNotification.cs | 26 +- .../Notifications/MovedNotification.cs | 20 +- .../MovedToRecycleBinNotification.cs | 21 + .../Notifications/MovingNotification.cs | 20 +- .../MovingToRecycleBinNotification.cs | 21 + .../Notifications/NotificationExtensions.cs | 21 + .../Notifications/ObjectNotification.cs | 19 + .../PartialViewCreatedNotification.cs | 12 + .../PartialViewCreatingNotification.cs | 12 + .../PartialViewDeletedNotification.cs | 12 + .../PartialViewDeletingNotification.cs | 19 + .../PartialViewSavedNotification.cs | 19 + .../PartialViewSavingNotification.cs | 19 + ...RuntimePremigrationsUpgradeNotification.cs | 11 +- .../PublicAccessCacheRefresherNotification.cs | 15 + .../PublicAccessEntryDeletedNotification.cs | 12 + .../PublicAccessEntryDeletingNotification.cs | 19 + .../PublicAccessEntrySavedNotification.cs | 19 + .../PublicAccessEntrySavingNotification.cs | 19 + .../RelationDeletedNotification.cs | 6 + .../RelationDeletingNotification.cs | 6 + .../RelationSavedNotification.cs | 6 + .../RelationSavingNotification.cs | 6 + .../RelationTypeCacheRefresherNotification.cs | 15 + .../RelationTypeDeletedNotification.cs | 6 + .../RelationTypeDeletingNotification.cs | 6 + .../RelationTypeSavedNotification.cs | 6 + .../RelationTypeSavingNotification.cs | 6 + .../RemovedMemberRolesNotification.cs | 19 +- .../Notifications/RenamedNotification.cs | 23 + .../Notifications/RenamingNotification.cs | 23 + .../Notifications/RolledBackNotification.cs | 16 + .../Notifications/RollingBackNotification.cs | 16 + ...RuntimePremigrationsUpgradeNotification.cs | 26 +- .../RuntimeUnattendedUpgradeNotification.cs | 21 + .../Notifications/SavedNotification.cs | 21 + .../Notifications/SavingNotification.cs | 21 + .../Notifications/ScaffoldedNotification.cs | 23 + .../ScopedEntityRemoveNotification.cs | 18 + .../ScriptDeletedNotification.cs | 6 + .../ScriptDeletingNotification.cs | 12 + .../Notifications/ScriptSavedNotification.cs | 17 +- .../Notifications/ScriptSavingNotification.cs | 17 +- .../Notifications/SendEmailNotification.cs | 19 + .../Notifications/SortedNotification.cs | 16 + .../Notifications/SortingNotification.cs | 16 + .../Notifications/StatefulNotification.cs | 15 +- .../StylesheetDeletedNotification.cs | 6 + .../StylesheetDeletingNotification.cs | 12 + .../StylesheetSavedNotification.cs | 19 +- .../StylesheetSavingNotification.cs | 19 +- .../TemplateCacheRefresherNotification.cs | 17 +- .../TemplateDeletedNotification.cs | 6 + .../TemplateDeletingNotification.cs | 12 + .../TemplateSavedNotification.cs | 24 +- .../TemplateSavingNotification.cs | 28 +- .../Notifications/TreeChangeNotification.cs | 26 ++ .../UmbracoApplicationStartedNotification.cs | 13 +- .../UmbracoApplicationStartingNotification.cs | 20 +- .../UmbracoApplicationStoppedNotification.cs | 13 +- .../UmbracoApplicationStoppingNotification.cs | 13 +- .../UserCacheRefresherNotification.cs | 20 +- .../Notifications/UserDeletedNotification.cs | 12 + .../Notifications/UserDeletingNotification.cs | 17 + .../UserForgotPasswordChangedNotification.cs | 16 + ...UserForgotPasswordRequestedNotification.cs | 16 + .../UserGroupCacheRefresherNotification.cs | 17 +- .../UserGroupDeletedNotification.cs | 19 + .../UserGroupDeletingNotification.cs | 19 + .../UserGroupSavedNotification.cs | 19 + .../UserGroupSavingNotification.cs | 19 + .../UserGroupWithUsersSavedNotification.cs | 18 + .../UserGroupWithUsersSavingNotification.cs | 19 + .../Notifications/UserLockedNotification.cs | 16 + .../UserLoginFailedNotification.cs | 15 + ...erLoginRequiresVerificationNotification.cs | 16 + .../UserLoginSuccessNotification.cs | 15 + .../UserLogoutSuccessNotification.cs | 21 + .../Notifications/UserNotification.cs | 27 +- .../UserPasswordChangedNotification.cs | 15 + .../UserPasswordResetNotification.cs | 15 + .../UserPasswordResettingNotification.cs | 22 +- .../UserResetAccessFailedCountNotification.cs | 16 + .../Notifications/UserSavedNotification.cs | 17 + .../Notifications/UserSavingNotification.cs | 17 + .../UserTwoFactorRequestedNotification.cs | 17 + .../Notifications/UserUnlockedNotification.cs | 15 + .../WebhookDeletedNotification.cs | 15 + .../WebhookDeletingNotification.cs | 22 + .../Notifications/WebhookSavedNotification.cs | 22 + .../WebhookSavingNotification.cs | 22 + .../Packaging/CompiledPackageXmlParser.cs | 19 +- .../Packaging/ConflictingPackageData.cs | 20 + .../Packaging/IPackageDefinitionRepository.cs | 27 +- .../Packaging/IPackageInstallation.cs | 31 +- .../Packaging/InstallationSummary.cs | 50 ++ .../Packaging/InstalledPackage.cs | 21 + .../InstalledPackageMigrationPlans.cs | 7 + .../Packaging/PackageDefinition.cs | 48 ++ .../Packaging/PackageDefinitionXmlParser.cs | 19 +- .../Packaging/PackageMigrationResource.cs | 45 ++ .../Packaging/PackagesRepository.cs | 97 +++- src/Umbraco.Core/PaginationHelper.cs | 13 +- .../Persistence/Constants-DatabaseSchema.cs | 304 ++++++++++++- .../Persistence/Querying/IUserDataFilter.cs | 12 + .../Querying/StringPropertyMatchType.cs | 21 +- .../Querying/ValuePropertyMatchType.cs | 21 +- .../Repositories/IAuditRepository.cs | 13 + .../Repositories/IContentRepository.cs | 5 + .../Repositories/IContentTypeRepository.cs | 8 + .../IContentTypeRepositoryBase.cs | 15 + .../IDataTypeContainerRepository.cs | 3 + .../Repositories/IDataTypeRepository.cs | 15 +- .../Repositories/IDataTypeUsageRepository.cs | 11 + .../Repositories/IDictionaryRepository.cs | 33 ++ .../IDocumentBlueprintContainerRepository.cs | 5 +- .../IDocumentBlueprintRepository.cs | 3 + .../Repositories/IDocumentRepository.cs | 27 ++ .../IDocumentTypeContainerRepository.cs | 3 + .../Repositories/IDocumentUrlRepository.cs | 17 + .../IDocumentVersionRepository.cs | 3 + .../Repositories/IDomainRepository.cs | 24 + .../IEntityContainerRepository.cs | 26 ++ .../Repositories/IEntityRepository.cs | 137 +++++- .../Repositories/IFileRepository.cs | 18 + .../IFileWithFoldersRepository.cs | 21 + .../Repositories/IIdKeyMapRepository.cs | 15 + .../Repositories/IInstallationRepository.cs | 8 + .../Repositories/IKeyValueRepository.cs | 3 + .../Repositories/ILanguageRepository.cs | 8 + .../Repositories/ILogViewerQueryRepository.cs | 8 + .../Repositories/IMediaRepository.cs | 12 + .../IMediaTypeContainerRepository.cs | 3 + .../Repositories/IMediaTypeRepository.cs | 3 + .../Repositories/IMemberGroupRepository.cs | 18 + .../Repositories/IMemberRepository.cs | 21 + .../IMemberTypeContainerRepository.cs | 3 + .../Repositories/IMemberTypeRepository.cs | 3 + .../Repositories/INavigationRepository.cs | 3 + .../Repositories/INodeCountRepository.cs | 12 + .../Repositories/INotificationsRepository.cs | 52 +++ .../Repositories/IPartialViewRepository.cs | 3 + .../Repositories/IPublicAccessRepository.cs | 3 + .../Repositories/IPublishStatusRepository.cs | 22 + .../Repositories/IRelationRepository.cs | 39 ++ .../Repositories/IRelationTypeRepository.cs | 3 + .../Repositories/IScriptRepository.cs | 3 + .../IServerRegistrationRepository.cs | 10 + .../Repositories/IStylesheetRepository.cs | 3 + .../Repositories/ITagRepository.cs | 11 +- .../Repositories/ITemplateRepository.cs | 23 + .../ITrackedReferencesRepository.cs | 3 + .../Repositories/ITwoFactorLoginRepository.cs | 19 + .../Repositories/IUpgradeCheckRepository.cs | 8 + .../Repositories/IUserDataRepository.cs | 30 ++ .../Repositories/IUserGroupRepository.cs | 3 + .../Repositories/IUserRepository.cs | 69 +++ .../Repositories/IWebProfilerRepository.cs | 14 + .../Repositories/IWebhookLogRepository.cs | 31 ++ .../Repositories/IWebhookRepository.cs | 3 + .../Repositories/IWebhookRequestRepository.cs | 5 +- .../Repositories/InstallationRepository.cs | 9 +- .../Repositories/UpgradeCheckRepository.cs | 8 + .../Persistence/SqlExpressionExtensions.cs | 48 ++ .../Persistence/TextColumnType.cs | 10 + .../Preview/IPreviewTokenGenerator.cs | 18 + .../Preview/NoopPreviewTokenGenerator.cs | 9 + .../PropertyEditors/BlockGridConfiguration.cs | 60 +++ .../PropertyEditors/BlockListConfiguration.cs | 23 + .../ColorPickerConfiguration.cs | 15 + .../ConfigurationEditor{TConfiguration}.cs | 6 + .../ContentPickerConfiguration.cs | 4 + .../ContentPickerConfigurationEditor.cs | 7 + .../ContentPickerPropertyEditor.cs | 27 +- .../PropertyEditors/DataEditor.cs | 13 +- .../PropertyEditors/DataEditorCollection.cs | 7 + .../DataEditorCollectionBuilder.cs | 6 +- .../PropertyEditors/DataValueEditor.cs | 13 +- .../PropertyEditors/DataValueEditorFactory.cs | 8 + .../DataValueReferenceFactoryCollection.cs | 5 + ...aValueReferenceFactoryCollectionBuilder.cs | 6 +- .../PropertyEditors/DateTimeConfiguration.cs | 9 + .../PropertyEditors/DateValueEditor.cs | 8 + .../DecimalConfigurationEditor.cs | 3 + .../DefaultPropertyValueConverterAttribute.cs | 8 + .../IDeliveryApiPropertyValueConverter.cs | 7 + .../DropDownFlexibleConfiguration.cs | 6 + .../EntityDataPickerConfiguration.cs | 18 + .../EntityDataPickerConfigurationEditor.cs | 7 + .../EntityDataPickerPropertyEditor.cs | 6 + .../EyeDropperColorPickerPropertyEditor.cs | 7 + .../FileExtensionConfigItem.cs | 5 + .../FileUploadConfiguration.cs | 3 + .../FileUploadConfigurationEditor.cs | 4 + .../PropertyEditors/IBlockConfiguration.cs | 12 + .../IBlockValuePropertyIndexValueFactory.cs | 7 + .../PropertyEditors/IDataEditor.cs | 6 + .../IDataValueEditorFactory.cs | 9 + .../IDataValueReferenceFactory.cs | 8 +- .../IFileExtensionConfigItem.cs | 9 + .../IIgnoreUserStartNodesConfig.cs | 3 + .../IPropertyCacheCompressionOptions.cs | 3 + .../IRichTextEditorIntermediateValue.cs | 11 +- .../IRichTextPropertyIndexValueFactory.cs | 9 +- .../ITagPropertyIndexValueFactory.cs | 7 + .../PropertyEditors/IndexValue.cs | 18 + .../IntegerConfigurationEditor.cs | 3 + .../JsonPropertyIndexValueFactoryBase.cs | 4 + .../PropertyEditors/LabelConfiguration.cs | 3 + .../LabelConfigurationEditor.cs | 7 +- .../PropertyEditors/LabelPropertyEditor.cs | 11 +- .../PropertyEditors/ListViewConfiguration.cs | 15 + .../ListViewConfigurationEditor.cs | 6 +- .../MarkDownPropertyValueEditor.cs | 12 + .../MediaPicker3Configuration.cs | 40 ++ .../MediaUrlGeneratorCollection.cs | 14 + .../MediaUrlGeneratorCollectionBuilder.cs | 4 + .../MemberGroupPickerPropertyEditor.cs | 11 + .../MemberPickerPropertyEditor.cs | 11 + .../PropertyEditors/MissingPropertyEditor.cs | 14 +- .../MultiNodePickerConfiguration.cs | 13 + .../MultiNodePickerConfigurationEditor.cs | 4 + .../MultiNodePickerConfigurationTreeSource.cs | 33 ++ .../MultiUrlPickerConfiguration.cs | 10 + .../MultiUrlPickerConfigurationEditor.cs | 7 + .../MultipleTextStringConfiguration.cs | 7 +- .../NoopPropertyCacheCompressionOptions.cs | 1 + .../PlainTimePropertyEditor.cs | 6 +- .../PropertyCacheCompression.cs | 8 + .../PropertyEditorCollection.cs | 20 +- .../PropertyValueConverterCollection.cs | 18 + ...PropertyValueConverterCollectionBuilder.cs | 6 +- .../PropertyEditors/RichTextConfiguration.cs | 16 + .../RichTextConfigurationEditor.cs | 6 +- .../SingleBlockConfiguration.cs | 8 +- .../PropertyEditors/SliderConfiguration.cs | 12 + .../SliderConfigurationEditor.cs | 4 + .../PropertyEditors/TagConfiguration.cs | 10 +- .../PropertyEditors/TagConfigurationEditor.cs | 4 + .../TagPropertyIndexValueFactory.cs | 10 + .../PropertyEditors/TextAreaConfiguration.cs | 3 + .../TextAreaConfigurationEditor.cs | 6 +- .../PropertyEditors/TextOnlyValueEditor.cs | 14 +- .../TextStringValueConverter.cs | 16 + .../PropertyEditors/TextboxConfiguration.cs | 3 + ...dContentPropertyCacheCompressionOptions.cs | 1 + .../UserPickerPropertyEditor.cs | 11 + .../Validation/IJsonPathValidationResult.cs | 8 +- .../Validation/INestedValidationResults.cs | 8 +- .../Validation/ITypedJsonValidator.cs | 8 + .../Validation/JsonPathExpression.cs | 12 +- .../Validation/JsonPathValidationError.cs | 11 +- .../Validation/JsonPathValidator.cs | 10 +- .../NestedJsonPathValidationResults.cs | 11 +- .../Validation/NestedValidationResults.cs | 9 +- .../Validators/RequiredValidator.cs | 3 + .../BigintValueTypeConverter.cs | 11 + .../CheckboxListValueConverter.cs | 11 + .../ColorPickerValueConverter.cs | 26 ++ .../ContentPickerValueConverter.cs | 17 + .../DatePickerValueConverter.cs | 12 + .../DateTimeValueTypeConverter.cs | 11 + .../ValueConverters/DecimalValueConverter.cs | 12 + .../DecimalValueTypeConverter.cs | 11 + .../EmailAddressValueConverter.cs | 7 + .../EyeDropperValueConverter.cs | 7 + .../FlexibleDropdownPropertyValueConverter.cs | 11 + .../ValueConverters/IntegerValueConverter.cs | 7 + .../IntegerValueTypeConverter.cs | 11 + .../ValueConverters/LabelValueConverter.cs | 4 + .../MemberGroupPickerValueConverter.cs | 14 + .../MemberPickerValueConverter.cs | 20 +- .../MissingPropertyEditorValueConverter.cs | 6 +- .../MultiNodeTreePickerValueConverter.cs | 19 + .../MultipleTextStringValueConverter.cs | 7 + .../MustBeStringValueConverter.cs | 4 + .../RadioButtonListValueConverter.cs | 7 + .../SimpleRichtextValueConverter.cs | 5 + .../TextStringValueTypeConverter.cs | 13 +- .../ValueConverters/TimeValueTypeConverter.cs | 13 +- .../UploadPropertyConverter.cs | 6 +- .../ValueTypePropertyValueConverterBase.cs | 13 +- .../ValueConverters/XmlValueTypeConverter.cs | 21 +- .../ValueConverters/YesNoValueConverter.cs | 7 + .../PropertyEditors/ValueListConfiguration.cs | 3 + .../PublishedCache/ICacheManager.cs | 10 +- .../PublishedCache/IDocumentCacheService.cs | 71 ++- .../PublishedCache/IDomainCache.cs | 3 + .../PublishedCache/IDomainCacheService.cs | 19 +- .../PublishedCache/IMediaCacheService.cs | 69 ++- .../PublishedCache/IPublishedContentCache.cs | 7 + .../IPublishedContentTypeCache.cs | 9 +- .../PublishedCache/IPublishedMediaCache.cs | 7 + src/Umbraco.Core/PublishedCache/ITagQuery.cs | 8 + .../Internal/InternalPublishedContent.cs | 58 +++ .../Internal/InternalPublishedProperty.cs | 27 ++ .../PublishedCache/PublishedCacheBase.cs | 32 ++ .../PublishedCache/PublishedElement.cs | 50 +- .../PublishedElementPropertyBase.cs | 85 +++- src/Umbraco.Core/Routing/AliasUrlProvider.cs | 10 + .../ContentFinderByIdentifierPathBase.cs | 25 +- .../Routing/ContentFinderByKeyPath.cs | 1 + .../Routing/ContentFinderCollection.cs | 7 + .../Routing/ContentFinderCollectionBuilder.cs | 6 +- .../Routing/DefaultMediaUrlProvider.cs | 5 + .../Routing/DefaultUrlAssembler.cs | 10 +- .../Routing/DefaultUrlProvider.cs | 10 + src/Umbraco.Core/Routing/DomainAndUri.cs | 1 + .../Routing/IPublishedUrlInfoProvider.cs | 5 +- .../Routing/IPublishedUrlProvider.cs | 10 + src/Umbraco.Core/Routing/IUrlAssembler.cs | 10 + .../Routing/MediaUrlProviderCollection.cs | 7 + .../MediaUrlProviderCollectionBuilder.cs | 6 +- src/Umbraco.Core/Routing/PublishedRequest.cs | 3 + .../Routing/PublishedRequestBuilder.cs | 3 + .../Routing/PublishedRequestExtensions.cs | 3 + src/Umbraco.Core/Routing/PublishedRouter.cs | 7 + .../Routing/PublishedUrlInfoProvider.cs | 14 + src/Umbraco.Core/Routing/SiteDomainMapper.cs | 12 + .../Routing/UmbracoRequestPathsOptions.cs | 5 +- .../Routing/UmbracoRouteResult.cs | 3 + src/Umbraco.Core/Routing/UriUtility.cs | 75 ++- src/Umbraco.Core/Routing/UrlInfo.cs | 41 ++ src/Umbraco.Core/Routing/UrlProvider.cs | 1 + .../Routing/UrlProviderCollection.cs | 7 + .../Routing/UrlProviderCollectionBuilder.cs | 6 +- .../Routing/UrlProviderExtensions.cs | 3 + src/Umbraco.Core/Routing/WebPath.cs | 12 + .../Runtime/EssentialDirectoryCreator.cs | 14 + .../Runtime/IUmbracoBootPermissionChecker.cs | 13 + src/Umbraco.Core/Runtime/MainDom.cs | 41 +- .../Runtime/MainDomSemaphoreLock.cs | 20 +- src/Umbraco.Core/Scoping/CoreScope.cs | 89 +++- src/Umbraco.Core/Scoping/ICoreScope.cs | 21 + .../Scoping/IInstanceIdentifiable.cs | 3 + src/Umbraco.Core/Scoping/ILockingMechanism.cs | 60 ++- src/Umbraco.Core/Scoping/IScopeContext.cs | 4 + src/Umbraco.Core/Scoping/LockingMechanism.cs | 29 +- .../ContentPermissionAuthorizer.cs | 5 + .../ContentPermissionResource.cs | 3 +- .../DictionaryPermissionAuthorizer.cs | 6 + .../DictionaryPermissionResource.cs | 10 +- .../Authorization/FeatureAuthorizer.cs | 4 + .../IContentPermissionAuthorizer.cs | 6 + .../IDictionaryPermissionAuthorizer.cs | 9 + .../Authorization/IPermissionResource.cs | 3 + .../MediaPermissionAuthorizer.cs | 4 + .../UserGroupPermissionAuthorizer.cs | 4 + .../Authorization/UserPermissionAuthorizer.cs | 4 + .../BackOfficeAuthenticationTypeSettings.cs | 18 + .../BackOfficeExternalLoginProviderErrors.cs | 19 +- .../BackOfficeUserPasswordCheckerResult.cs | 13 +- .../Security/ClaimsPrincipalExtensions.cs | 8 + .../Security/ContentPermissions.cs | 36 ++ .../Security/ExternalLoginToken.cs | 3 + .../Security/FileStreamSecurityValidator.cs | 8 + .../Security/IBackOfficePasswordChanger.cs | 11 +- .../Security/IBackOfficeUserStore.cs | 12 +- .../Security/IBackofficeSecurity.cs | 3 + .../Security/IBackofficeSecurityAccessor.cs | 6 + .../Security/ICoreBackOfficeSignInManager.cs | 8 + .../Security/ICoreBackOfficeUserManager.cs | 57 ++- .../Security/IFileStreamSecurityAnalyzer.cs | 3 + .../Security/IFileStreamSecurityValidator.cs | 3 + .../Security/IForgotPasswordUriProvider.cs | 8 + src/Umbraco.Core/Security/IHtmlSanitizer.cs | 3 + .../Security/IInviteUriProvider.cs | 10 +- .../Security/ILocalLoginSettingProvider.cs | 12 +- src/Umbraco.Core/Security/IPasswordHasher.cs | 3 + .../Security/IPublicAccessChecker.cs | 3 + .../Security/IUserForgotPasswordSender.cs | 12 + .../Security/IUserInviteSender.cs | 14 +- .../Security/IdentityAuditEventArgs.cs | 59 +++ .../Security/IdentityUserToken.cs | 3 + src/Umbraco.Core/Security/MediaPermissions.cs | 26 ++ .../Security/NoopHtmlSanitizer.cs | 8 + .../Security/PasswordGenerator.cs | 8 + .../Security/PublicAccessStatus.cs | 22 + .../Security/UpdateMemberProfileResult.cs | 21 + .../Security/UpdateMemberProfileStatus.cs | 10 + src/Umbraco.Core/Semver/SemVersion.cs | 6 + .../Serialization/IWebhookJsonSerializer.cs | 9 +- .../EventSourceAuthorizerCollection.cs | 13 +- .../EventSourceAuthorizerCollectionBuilder.cs | 10 +- .../IServerEventAuthorizationService.cs | 11 +- .../ServerEvents/IServerEventHub.cs | 17 +- .../Services/AuditEntryService.cs | 49 +- .../ContentAuthorizationStatus.cs | 34 ++ .../DictionaryAuthorizationStatus.cs | 10 + .../MediaAuthorizationStatus.cs | 22 + .../UserAuthorizationStatus.cs | 10 + .../UserGroupAuthorizationStatus.cs | 26 ++ src/Umbraco.Core/Services/BasicAuthService.cs | 13 + .../Services/Changes/ContentTypeChange.cs | 15 + .../Changes/ContentTypeChangeExtensions.cs | 27 ++ .../Changes/ContentTypeChangeTypes.cs | 6 + .../Services/Changes/DomainChangeTypes.cs | 18 + .../Services/Changes/TreeChange.cs | 46 ++ .../Services/Changes/TreeChangeExtensions.cs | 33 ++ .../Services/Changes/TreeChangeTypes.cs | 18 + .../ContentBlueprintContainerService.cs | 19 +- .../ContentBlueprintEditingService.cs | 82 +++- .../Services/ContentEditingService.cs | 41 ++ .../Services/ContentEditingServiceBase.cs | 140 ++++++ .../ContentEditingServiceWithSortingBase.cs | 43 ++ .../Services/ContentPermissionService.cs | 8 + .../Services/ContentPublishingService.cs | 17 + src/Umbraco.Core/Services/ContentService.cs | 187 +++++++- .../Services/ContentServiceExtensions.cs | 20 + .../ContentTypeBaseServiceProvider.cs | 11 + .../Services/ContentTypeContainerService.cs | 19 +- .../ContentTypeEditingService.cs | 37 ++ .../ContentTypeEditingServiceBase.cs | 216 +++++++++ .../ElementSwitchValidator.cs | 17 + .../IContentTypeEditingService.cs | 39 +- .../IElementSwitchValidator.cs | 58 +++ .../IMediaTypeEditingService.cs | 63 ++- .../IMemberTypeEditingService.cs | 37 ++ .../MediaTypeEditingService.cs | 35 ++ .../MemberTypeEditingService.cs | 43 ++ .../Services/ContentTypeService.cs | 98 ++++ .../Services/ContentTypeServiceBase.cs | 9 + ...ntentTypeServiceBase{TRepository,TItem}.cs | 309 ++++++++++++- .../Services/ContentTypeServiceExtensions.cs | 17 +- .../Services/ContentValidationService.cs | 11 +- .../Services/ContentValidationServiceBase.cs | 21 + .../Services/ContentVersionService.cs | 25 + .../Services/CultureImpactFactory.cs | 8 + src/Umbraco.Core/Services/CultureService.cs | 8 + .../Services/DataTypeContainerService.cs | 23 +- src/Umbraco.Core/Services/DataTypeService.cs | 168 +++++++ .../Services/DataTypeUsageService.cs | 9 + .../Services/DateTypeServiceExtensions.cs | 15 + .../DefaultContentVersionCleanupPolicy.cs | 12 + .../Services/DictionaryItemService.cs | 70 ++- .../Services/DictionaryPermissionService.cs | 7 + .../Services/DictionaryService.cs | 10 +- ...rlServiceInitializerNotificationHandler.cs | 9 + src/Umbraco.Core/Services/DomainService.cs | 41 ++ src/Umbraco.Core/Services/EntityService.cs | 21 + .../Services/EntityTypeContainerService.cs | 31 ++ .../Services/EntityXmlSerializer.cs | 151 +++++-- .../Services/ExternalLoginService.cs | 21 + src/Umbraco.Core/Services/FileService.cs | 88 +++- src/Umbraco.Core/Services/FileServiceBase.cs | 42 +- .../Services/FileServiceOperationBase.cs | 155 ++++++- .../FileSystem/FolderServiceOperationBase.cs | 94 ++++ .../FileSystem/IPartialViewFolderService.cs | 30 +- .../FileSystem/IScriptFolderService.cs | 30 +- .../FileSystem/IStylesheetFolderService.cs | 30 +- .../FileSystem/PartialViewFolderService.cs | 24 +- .../FileSystem/ScriptFolderService.cs | 24 +- .../FileSystem/StylesheetFolderService.cs | 24 +- .../Services/Filters/IContentTypeFilter.cs | 1 + src/Umbraco.Core/Services/IAuditService.cs | 31 ++ .../Services/IBasicAuthService.cs | 23 + .../Services/IConflictingRouteService.cs | 8 + .../IContentBlueprintContainerService.cs | 9 +- .../IContentBlueprintEditingService.cs | 58 +++ .../Services/IContentEditingService.cs | 80 +++- .../Services/IContentListViewService.cs | 16 + .../Services/IContentPublishingService.cs | 5 +- .../Services/IContentSearchService.cs | 6 +- .../IContentSearchService{TContent}.cs | 15 +- .../Services/IContentServiceBase.cs | 15 + .../Services/IContentTypeBaseService.cs | 195 +++++++- .../Services/IContentTypeContainerService.cs | 9 +- .../Services/IContentTypeSearchService.cs | 17 +- .../Services/IContentTypeService.cs | 16 +- .../Services/IContentValidationService.cs | 5 +- .../Services/IContentValidationServiceBase.cs | 18 +- .../Services/IContentVersionService.cs | 40 ++ .../Services/ICultureImpactFactory.cs | 6 +- src/Umbraco.Core/Services/ICultureService.cs | 7 + .../Services/IDataTypeContainerService.cs | 9 +- src/Umbraco.Core/Services/IDataTypeService.cs | 90 +++- .../Services/IDataTypeUsageService.cs | 3 + .../Services/IDictionaryItemService.cs | 15 +- .../Services/IDictionaryPermissionService.cs | 10 +- .../Services/IDictionaryService.cs | 11 +- src/Umbraco.Core/Services/IDomainService.cs | 65 ++- .../Services/IEntitySearchService.cs | 10 +- src/Umbraco.Core/Services/IEntityService.cs | 45 ++ .../Services/IEntityTypeContainerService.cs | 38 +- .../Services/IEntityXmlSerializer.cs | 73 ++- .../Services/IExamineIndexCountService.cs | 7 + .../Services/IExternalLoginWithKeyService.cs | 3 + src/Umbraco.Core/Services/IFileService.cs | 41 ++ src/Umbraco.Core/Services/IIdKeyMap.cs | 40 ++ .../Services/IIndexedEntitySearchService.cs | 15 +- .../Services/IInstallationService.cs | 8 + .../Services/IIpAddressUtilities.cs | 9 + src/Umbraco.Core/Services/ILanguageService.cs | 3 + .../Services/ILocalizationService.cs | 6 + .../Services/ILogViewerService.cs | 3 + .../Services/IMediaEditingService.cs | 117 ++++- .../Services/IMediaImportService.cs | 14 +- .../Services/IMediaListViewService.cs | 15 + .../Services/IMediaSearchService.cs | 8 +- src/Umbraco.Core/Services/IMediaService.cs | 37 ++ .../Services/IMediaTypeContainerService.cs | 8 +- .../Services/IMediaValidationService.cs | 8 +- .../Services/IMemberContentEditingService.cs | 33 +- .../Services/IMemberEditingService.cs | 40 +- .../Services/IMemberGroupService.cs | 36 ++ src/Umbraco.Core/Services/IMemberService.cs | 17 +- .../Services/IMemberTypeContainerService.cs | 6 + .../Services/IMemberTypeService.cs | 4 + .../Services/IMemberValidationService.cs | 8 +- .../Services/IMembershipRoleService.cs | 104 +++++ .../Services/IMetricsConsentService.cs | 12 + .../Services/INodeCountService.cs | 12 + .../Services/INotificationService.cs | 3 + .../Services/IPackageDataInstallation.cs | 52 ++- .../Services/IPackagingService.cs | 14 + .../Services/IPartialViewService.cs | 5 +- src/Umbraco.Core/Services/IPreviewService.cs | 24 +- .../Services/IPropertyValidationService.cs | 3 + .../Services/IPublicAccessService.cs | 3 + .../Services/IRedirectUrlService.cs | 3 +- src/Umbraco.Core/Services/IRelationService.cs | 30 ++ .../Services/IReservedFieldNamesService.cs | 17 +- src/Umbraco.Core/Services/IRuntimeState.cs | 6 + src/Umbraco.Core/Services/IScriptService.cs | 5 +- src/Umbraco.Core/Services/ISegmentService.cs | 3 + .../Services/IServerInformationService.cs | 17 + .../Services/IServerRegistrationService.cs | 3 + .../Services/IStylesheetService.cs | 5 +- ...SystemTroubleshootingInformationService.cs | 5 +- src/Umbraco.Core/Services/ITagService.cs | 13 + .../Services/ITemplateContentParserService.cs | 10 +- src/Umbraco.Core/Services/ITemplateService.cs | 5 +- .../Services/ITemporaryFileService.cs | 25 + .../Services/ITrackedReferencesService.cs | 11 + .../Services/ITreeEntitySortingService.cs | 12 +- src/Umbraco.Core/Services/IUpgradeService.cs | 8 + .../Services/IUsageInformationService.cs | 7 + src/Umbraco.Core/Services/IUserDataService.cs | 30 ++ .../Services/IUserGroupService.cs | 25 +- src/Umbraco.Core/Services/IUserService.cs | 187 ++++++-- .../Services/IWebProfilerService.cs | 13 + .../Services/IWebhookFiringService.cs | 13 +- .../Services/IWebhookLogFactory.cs | 16 +- .../Services/IWebhookLogService.cs | 21 + .../Services/IWebhookRequestService.cs | 9 +- src/Umbraco.Core/Services/IWebhookService.cs | 3 + src/Umbraco.Core/Services/IdKeyMap.cs | 63 ++- .../ImportExport/ContentTypeImportService.cs | 28 +- .../ImportExport/IContentTypeImportService.cs | 17 + .../ImportExport/IMediaTypeImportService.cs | 17 + .../ImportExport/IMemberTypeImportService.cs | 17 + .../ITemporaryFileToXmlImportService.cs | 43 ++ .../ImportExport/MediaTypeImportService.cs | 12 + .../ImportExport/MemberTypeImportService.cs | 12 + .../TemporaryFileToXmlImportService.cs | 54 ++- .../Services/InstallationService.cs | 8 + .../Services/Installer/IInstallService.cs | 10 +- .../Services/Installer/IUpgradeService.cs | 9 +- .../Services/Installer/InstallService.cs | 16 +- .../Services/Installer/UpgradeService.cs | 16 +- src/Umbraco.Core/Services/KeyValueService.cs | 8 + src/Umbraco.Core/Services/LanguageService.cs | 15 + .../Services/LocalizationService.cs | 23 + .../Services/LocalizedTextService.cs | 32 +- .../LocalizedTextServiceExtensions.cs | 22 + .../LocalizedTextServiceFileSources.cs | 30 +- ...lizedTextServiceSupplementaryFileSource.cs | 18 +- .../Services/Locking/ContentTypeLocks.cs | 23 +- .../Services/Locking/MediaTypeLocks.cs | 23 +- .../Services/Locking/MemberTypeLocks.cs | 21 + .../Services/MediaEditingService.cs | 44 ++ .../Services/MediaImportService.cs | 15 + .../Services/MediaPermissionService.cs | 6 + src/Umbraco.Core/Services/MediaService.cs | 185 +++++++- .../Services/MediaServiceExtensions.cs | 17 + .../Services/MediaTypeContainerService.cs | 22 +- src/Umbraco.Core/Services/MediaTypeService.cs | 65 +++ .../Services/MediaValidationService.cs | 11 +- .../Services/MemberContentEditingService.cs | 65 +++ .../Services/MemberGroupService.cs | 31 ++ src/Umbraco.Core/Services/MemberService.cs | 80 ++++ .../Services/MemberTwoFactorLoginService.cs | 7 + .../Services/MemberTypeContainerService.cs | 20 + .../Services/MemberTypeService.cs | 79 ++++ .../Services/MemberValidationService.cs | 11 +- .../Services/MetricsConsentService.cs | 15 + .../ContentNavigationServiceBase.cs | 245 ++++++++++ .../Navigation/DocumentNavigationService.cs | 17 + .../IDocumentNavigationManagementService.cs | 9 + .../IDocumentNavigationQueryService.cs | 9 + .../IMediaNavigationManagementService.cs | 9 + .../IMediaNavigationQueryService.cs | 9 + .../INavigationManagementService.cs | 5 + .../Navigation/INavigationQueryService.cs | 143 ++++++ .../IRecycleBinNavigationManagementService.cs | 5 + .../IRecycleBinNavigationQueryService.cs | 58 +++ .../Navigation/MediaNavigationService.cs | 17 + ...gationInitializationNotificationHandler.cs | 23 + src/Umbraco.Core/Services/NodeCountService.cs | 14 + .../Services/NoopSegmentService.cs | 5 + .../Services/NotificationService.cs | 39 ++ src/Umbraco.Core/Services/OperationResult.cs | 131 ++++++ .../ApiContentQueryOperationStatus.cs | 18 + .../ApiMediaQueryOperationStatus.cs | 20 +- .../AuditLogOperationStatus.cs | 12 +- .../ContentCollectionOperationStatus.cs | 46 ++ .../ContentEditingOperationStatus.cs | 92 +++- .../ContentPublishingOperationStatus.cs | 113 ++++- .../ContentQueryOperationStatus.cs | 16 +- .../ContentTypeImportOperationStatus.cs | 30 ++ .../ContentTypeOperationStatus.cs | 98 ++++ .../ContentTypeStructureOperationStatus.cs | 22 + .../ContentVersionOperationStatus.cs | 26 ++ .../DataTypeOperationStatus.cs | 48 +- .../DictionaryItemOperationStatus.cs | 36 +- .../OperationStatus/DomainOperationStatus.cs | 32 +- .../EntityContainerOperationStatus.cs | 40 +- .../ExternalLoginOperationStatus.cs | 54 +++ .../GetReferencesOperationStatus.cs | 10 + .../OperationStatus/InstallOperationStatus.cs | 28 +- .../LanguageOperationStatus.cs | 40 +- .../LogViewerOperationStatus.cs | 18 + .../MediaTypeImportOperationStatus.cs | 30 ++ .../MemberEditingOperationStatus.cs | 64 ++- .../OperationStatus/MemberEditingStatus.cs | 11 +- .../MemberGroupOperationStatus.cs | 28 +- .../MemberTypeImportOperationStatus.cs | 30 ++ .../OperationStatus/OEmbedOperationStatus.cs | 18 + .../PackageMigrationOperationStatus.cs | 14 + .../OperationStatus/PackageOperationStatus.cs | 18 + .../PartialViewFolderOperationStatus.cs | 28 +- .../PartialViewOperationStatus.cs | 36 +- .../PropertyTypeOperationStatus.cs | 12 +- .../PublicAccessOperationStatus.cs | 36 +- .../RelationOperationStatus.cs | 12 +- .../RelationTypeOperationStatus.cs | 32 +- .../ScriptFolderOperationStatus.cs | 28 +- .../OperationStatus/ScriptOperationStatus.cs | 36 +- .../OperationStatus/SegmentOperationStatus.cs | 6 + .../StylesheetFolderOperationStatus.cs | 28 +- .../StylesheetOperationStatus.cs | 36 +- .../TemplateOperationStatus.cs | 36 +- .../TemporaryFileOperationStatus.cs | 26 ++ .../TemporaryFileXmlImportOperationStatus.cs | 14 + .../TwoFactorOperationStatus.cs | 22 + .../OperationStatus/UpgradeOperationStatus.cs | 12 +- .../UserClientCredentialsOperationStatus.cs | 20 +- .../UserDataOperationStatus.cs | 21 +- .../UserGroupOperationStatus.cs | 84 +++- .../OperationStatus/UserOperationStatus.cs | 147 ++++++ .../WebProfilerOperationStatus.cs | 10 + .../OperationStatus/WebhookOperationStatus.cs | 20 +- src/Umbraco.Core/Services/Ordering.cs | 3 + .../Pagination/PaginationConverter.cs | 26 ++ .../Services/PartialViewService.cs | 57 +++ src/Umbraco.Core/Services/PreviewService.cs | 19 + .../Services/ProcessInstructionsResult.cs | 24 + .../Services/PropertyValidationService.cs | 13 + .../Services/PublicAccessService.cs | 40 ++ .../Services/PublicAccessServiceExtensions.cs | 23 + .../IPublishStatusManagementService.cs | 33 ++ ...IPublishedContentStatusFilteringService.cs | 9 +- .../IPublishedMediaStatusFilteringService.cs | 9 +- .../IPublishedStatusFilteringService.cs | 11 +- .../PublishStatus/PublishStatusService.cs | 40 +- .../PublishedContentStatusFilteringService.cs | 23 + .../PublishedMediaStatusFilteringService.cs | 18 +- .../DocumentRecycleBinQueryService.cs | 10 + .../IDocumentRecycleBinQueryService.cs | 11 + .../IMediaRecycleBinQueryService.cs | 11 + .../RecycleBin/MediaRecycleBinQueryService.cs | 10 + .../RecycleBin/RecycleBinQueryResultType.cs | 32 +- src/Umbraco.Core/Services/RelationService.cs | 58 ++- .../Services/RepositoryService.cs | 20 + src/Umbraco.Core/Services/ScriptService.cs | 55 ++- .../Services/StylesheetService.cs | 55 ++- src/Umbraco.Core/Services/TagService.cs | 20 + .../Services/TemplateContentParserService.cs | 6 +- src/Umbraco.Core/Services/TemplateService.cs | 108 ++++- .../Services/TemporaryFileService.cs | 33 ++ .../Services/TrackedReferencesService.cs | 20 + .../Services/TreeEntitySortingService.cs | 6 +- .../Services/TwoFactorLoginServiceBase.cs | 32 +- src/Umbraco.Core/Services/UpgradeService.cs | 8 + src/Umbraco.Core/Services/UserDataService.cs | 21 + .../Services/UserGroupPermissionService.cs | 7 + src/Umbraco.Core/Services/UserGroupService.cs | 52 +++ .../Services/UserPermissionService.cs | 4 + src/Umbraco.Core/Services/UserService.cs | 427 ++++++++---------- .../Services/UserServiceExtensions.cs | 24 + .../Services/UserTwoFactorLoginService.cs | 7 + .../Services/WebProfilerService.cs | 12 + .../Services/WebhookLogFactory.cs | 16 +- .../Services/WebhookLogService.cs | 11 + .../Services/WebhookRequestService.cs | 19 +- src/Umbraco.Core/Services/WebhookService.cs | 14 + src/Umbraco.Core/SimpleMainDom.cs | 13 + .../Snippets/PartialViewSnippet.cs | 14 +- .../Snippets/PartialViewSnippetCollection.cs | 11 + .../PartialViewSnippetCollectionBuilder.cs | 7 + .../Snippets/PartialViewSnippetSlim.cs | 11 +- src/Umbraco.Core/StaticApplicationLogging.cs | 24 + src/Umbraco.Core/StringUdi.cs | 5 + .../Strings/Css/StylesheetHelper.cs | 28 +- .../Strings/Css/StylesheetRule.cs | 16 + .../Strings/DefaultShortStringHelper.cs | 54 ++- .../Strings/DefaultShortStringHelperConfig.cs | 121 ++++- .../Strings/DefaultUrlSegmentProvider.cs | 12 + src/Umbraco.Core/Strings/PathUtility.cs | 3 + .../Strings/UrlSegmentProviderCollection.cs | 11 + .../UrlSegmentProviderCollectionBuilder.cs | 9 +- src/Umbraco.Core/Sync/LastSyncedManager.cs | 18 +- src/Umbraco.Core/Sync/MessageType.cs | 29 +- .../Sync/NonRuntimeLevelBootStateAccessor.cs | 7 +- src/Umbraco.Core/Sync/RefreshInstruction.cs | 37 ++ src/Umbraco.Core/Sync/RefreshMethodType.cs | 56 +-- .../Sync/SingleServerRoleAccessor.cs | 19 +- src/Umbraco.Core/Sync/SyncBootState.cs | 13 +- src/Umbraco.Core/SystemLock.cs | 55 ++- .../Telemetry/Models/TelemetryReportData.cs | 3 + .../Telemetry/SiteIdentifierService.cs | 6 + .../Templates/HtmlImageSourceParser.cs | 13 +- .../Templates/HtmlLocalLinkParser.cs | 51 ++- src/Umbraco.Core/Templates/HtmlUrlParser.cs | 10 + .../Templates/ITemplateRenderer.cs | 7 + src/Umbraco.Core/Udi.cs | 30 ++ src/Umbraco.Core/UdiDefinitionAttribute.cs | 19 + src/Umbraco.Core/UdiEntityTypeHelper.cs | 15 + src/Umbraco.Core/UdiParser.cs | 16 + src/Umbraco.Core/UdiRange.cs | 21 + src/Umbraco.Core/UdiTypeConverter.cs | 2 + .../UmbracoApiControllerTypeCollection.cs | 7 + src/Umbraco.Core/UmbracoContextReference.cs | 5 + src/Umbraco.Core/UnknownTypeUdi.cs | 13 + src/Umbraco.Core/UpgradeResult.cs | 18 + src/Umbraco.Core/UriUtilityCore.cs | 29 ++ .../Web/CookieManagerExtensions.cs | 8 + src/Umbraco.Core/Web/IRequestAccessor.cs | 14 +- src/Umbraco.Core/Web/ISessionManager.cs | 17 + src/Umbraco.Core/Web/IUmbracoContext.cs | 4 + .../Web/IUmbracoContextAccessor.cs | 21 +- .../Web/Mvc/PluginControllerMetadata.cs | 21 +- .../Content/ContentCopiedWebhookEvent.cs | 12 + .../ContentDeletedBlueprintWebhookEvent.cs | 13 + .../ContentDeletedVersionsWebhookEvent.cs | 13 + .../Content/ContentDeletedWebhookEvent.cs | 13 + .../ContentEmptiedRecycleBinWebhookEvent.cs | 14 + .../ContentMovedToRecycleBinWebhookEvent.cs | 12 + .../Content/ContentMovedWebhookEvent.cs | 12 + .../Content/ContentPublishedWebhookEvent.cs | 15 + .../Content/ContentRolledBackWebhookEvent.cs | 15 + .../ContentSavedBlueprintWebhookEvent.cs | 13 + .../Content/ContentSavedWebhookEvent.cs | 15 + .../Content/ContentSortedWebhookEvent.cs | 14 + .../Content/ContentUnpublishedWebhookEvent.cs | 13 + .../DocumentTypeChangedWebhookEvent.cs | 12 + .../DocumentTypeDeletedWebhookEvent.cs | 12 + .../DocumentTypeMovedWebhookEvent.cs | 12 + .../DocumentTypeSavedWebhookEvent.cs | 12 + .../MediaTypeChangedWebhookEvent.cs | 12 + .../MediaTypeDeletedWebhookEvent.cs | 12 + .../ContentType/MediaTypeMovedWebhookEvent.cs | 12 + .../ContentType/MediaTypeSavedWebhookEvent.cs | 12 + .../MemberTypeChangedWebhookEvent.cs | 12 + .../MemberTypeDeletedWebhookEvent.cs | 12 + .../MemberTypeMovedWebhookEvent.cs | 12 + .../MemberTypeSavedWebhookEvent.cs | 12 + .../DataType/DataTypeDeletedWebhookEvent.cs | 12 + .../DataType/DataTypeMovedWebhookEvent.cs | 12 + .../DataType/DataTypeSavedWebhookEvent.cs | 12 + .../DictionaryItemDeletedWebhookEvent.cs | 12 + .../DictionaryItemSavedWebhookEvent.cs | 12 + .../Domain/DomainDeletedWebhookEvent.cs | 12 + .../Events/Domain/DomainSavedWebhookEvent.cs | 12 + .../File/PartialViewDeletedWebhookEvent.cs | 12 + .../File/PartialViewSavedWebhookEvent.cs | 12 + .../Events/File/ScriptDeletedWebhookEvent.cs | 12 + .../Events/File/ScriptSavedWebhookEvent.cs | 12 + .../File/StylesheetDeletedWebhookEvent.cs | 12 + .../File/StylesheetSavedWebhookEvent.cs | 12 + .../File/TemplateDeletedWebhookEvent.cs | 12 + .../Events/File/TemplateSavedWebhookEvent.cs | 12 + .../HealthCheckCompletedWebhookEvent.cs | 12 + .../Language/LanguageDeletedWebhookEvent.cs | 12 + .../Language/LanguageSavedWebhookEvent.cs | 12 + .../Events/Media/MediaDeletedWebhookEvent.cs | 13 + .../MediaEmptiedRecycleBinWebhookEvent.cs | 13 + .../MediaMovedToRecycleBinWebhookEvent.cs | 13 + .../Events/Media/MediaMovedWebhookEvent.cs | 13 + .../Events/Media/MediaSavedWebhookEvent.cs | 15 + .../Member/AssignedMemberRolesWebhookEvent.cs | 13 + .../Member/ExportedMemberWebhookEvent.cs | 12 + .../Member/MemberDeletedWebhookEvent.cs | 12 + .../Member/MemberGroupDeletedWebhookEvent.cs | 12 + .../Member/MemberGroupSavedWebhookEvent.cs | 12 + .../Events/Member/MemberSavedWebhookEvent.cs | 12 + .../Member/RemovedMemberRolesWebhookEvent.cs | 13 + .../Package/ImportedPackageWebhookEvent.cs | 12 + .../PublicAccessEntryDeletedWebhookEvent.cs | 12 + .../PublicAccessEntrySavedWebhookEvent.cs | 12 + .../Relation/RelationDeletedWebhookEvent.cs | 12 + .../Relation/RelationSavedWebhookEvent.cs | 12 + .../RelationTypeDeletedWebhookEvent.cs | 13 +- .../RelationTypeSavedWebhookEvent.cs | 12 + .../Events/User/UserDeletedWebhookEvent.cs | 12 + ...UserForgotPasswordRequestedWebhookEvent.cs | 12 + .../User/UserGroupDeletedWebhookEvent.cs | 12 + .../Events/User/UserGroupSavedWebhookEvent.cs | 12 + .../Events/User/UserLockedWebhookEvent.cs | 12 + .../User/UserLoginFailedWebhookEvent.cs | 12 + ...erLoginRequiresVerificationWebhookEvent.cs | 12 + .../User/UserLoginSuccessWebhookEvent.cs | 12 + .../User/UserLogoutSuccessWebhookEvent.cs | 12 + .../User/UserPasswordChangedWebhookEvent.cs | 12 + .../User/UserPasswordResetWebhookEvent.cs | 12 + .../Events/User/UserSavedWebhookEvent.cs | 12 + .../UserTwoFactorRequestedWebhookEvent.cs | 12 + .../Events/User/UserUnlockedWebhookEvent.cs | 12 + .../ExtendedContentPublishedWebhookEvent.cs | 17 + .../ExtendedContentSavedWebhookEvent.cs | 17 + .../ExtendedContentWebhookEventBase.cs | 19 + .../Media/ExtendedMediaSavedWebhookEvent.cs | 15 + src/Umbraco.Core/Webhooks/IWebhookEvent.cs | 14 +- .../LegacyContentCopiedWebhookEvent.cs | 12 + ...gacyContentDeletedBlueprintWebhookEvent.cs | 13 + ...egacyContentDeletedVersionsWebhookEvent.cs | 12 + .../LegacyContentDeletedWebhookEvent.cs | 13 + ...acyContentEmptiedRecycleBinWebhookEvent.cs | 14 + ...acyContentMovedToRecycleBinWebhookEvent.cs | 12 + .../Content/LegacyContentMovedWebhookEvent.cs | 12 + .../LegacyContentPublishedWebhookEvent.cs | 15 + .../LegacyContentRolledBackWebhookEvent.cs | 15 + ...LegacyContentSavedBlueprintWebhookEvent.cs | 13 + .../Content/LegacyContentSavedWebhookEvent.cs | 15 + .../LegacyContentSortedWebhookEvent.cs | 14 + .../LegacyContentUnpublishedWebhookEvent.cs | 13 + .../LegacyDocumentTypeChangedWebhookEvent.cs | 12 + .../LegacyDocumentTypeDeletedWebhookEvent.cs | 12 + .../LegacyDocumentTypeMovedWebhookEvent.cs | 12 + .../LegacyDocumentTypeSavedWebhookEvent.cs | 12 + .../LegacyMediaTypeChangedWebhookEvent.cs | 12 + .../LegacyMediaTypeDeletedWebhookEvent.cs | 12 + .../LegacyMediaTypeMovedWebhookEvent.cs | 12 + .../LegacyMediaTypeSavedWebhookEvent.cs | 12 + .../LegacyMemberTypeChangedWebhookEvent.cs | 12 + .../LegacyMemberTypeDeletedWebhookEvent.cs | 12 + .../LegacyMemberTypeMovedWebhookEvent.cs | 12 + .../LegacyMemberTypeSavedWebhookEvent.cs | 12 + .../LegacyDataTypeDeletedWebhookEvent.cs | 12 + .../LegacyDataTypeMovedWebhookEvent.cs | 12 + .../LegacyDataTypeSavedWebhookEvent.cs | 12 + ...LegacyDictionaryItemDeletedWebhookEvent.cs | 12 + .../LegacyDictionaryItemSavedWebhookEvent.cs | 12 + .../Domain/LegacyDomainDeletedWebhookEvent.cs | 12 + .../Domain/LegacyDomainSavedWebhookEvent.cs | 12 + .../LegacyPartialViewDeletedWebhookEvent.cs | 12 + .../LegacyPartialViewSavedWebhookEvent.cs | 12 + .../File/LegacyScriptDeletedWebhookEvent.cs | 12 + .../File/LegacyScriptSavedWebhookEvent.cs | 12 + .../LegacyStylesheetDeletedWebhookEvent.cs | 12 + .../File/LegacyStylesheetSavedWebhookEvent.cs | 12 + .../File/LegacyTemplateDeletedWebhookEvent.cs | 12 + .../File/LegacyTemplateSavedWebhookEvent.cs | 12 + .../LegacyHealthCheckCompletedWebhookEvent.cs | 12 + .../LegacyLanguageDeletedWebhookEvent.cs | 12 + .../LegacyLanguageSavedWebhookEvent.cs | 12 + .../Media/LegacyMediaDeletedWebhookEvent.cs | 13 + ...egacyMediaEmptiedRecycleBinWebhookEvent.cs | 13 + ...egacyMediaMovedToRecycleBinWebhookEvent.cs | 13 + .../Media/LegacyMediaMovedWebhookEvent.cs | 13 + .../Media/LegacyMediaSavedWebhookEvent.cs | 15 + .../LegacyAssignedMemberRolesWebhookEvent.cs | 11 + .../LegacyExportedMemberWebhookEvent.cs | 12 + .../Member/LegacyMemberDeletedWebhookEvent.cs | 12 + .../LegacyMemberGroupDeletedWebhookEvent.cs | 12 + .../LegacyMemberGroupSavedWebhookEvent.cs | 12 + .../Member/LegacyMemberSavedWebhookEvent.cs | 12 + .../LegacyRemovedMemberRolesWebhookEvent.cs | 11 + .../LegacyImportedPackageWebhookEvent.cs | 11 + ...acyPublicAccessEntryDeletedWebhookEvent.cs | 12 + ...egacyPublicAccessEntrySavedWebhookEvent.cs | 12 + .../LegacyRelationDeletedWebhookEvent.cs | 12 + .../LegacyRelationSavedWebhookEvent.cs | 12 + .../LegacyRelationTypeDeletedWebhookEvent.cs | 13 +- .../LegacyRelationTypeSavedWebhookEvent.cs | 12 + ...ssignedUserGroupPermissionsWebhookEvent.cs | 12 + .../User/LegacyUserDeletedWebhookEvent.cs | 12 + ...UserForgotPasswordRequestedWebhookEvent.cs | 12 +- .../LegacyUserGroupDeletedWebhookEvent.cs | 12 + .../User/LegacyUserGroupSavedWebhookEvent.cs | 12 + .../User/LegacyUserLockedWebhookEvent.cs | 11 + .../User/LegacyUserLoginFailedWebhookEvent.cs | 11 + ...erLoginRequiresVerificationWebhookEvent.cs | 12 +- .../LegacyUserLoginSuccessWebhookEvent.cs | 11 + .../LegacyUserLogoutSuccessWebhookEvent.cs | 11 + .../LegacyUserPasswordChangedWebhookEvent.cs | 12 +- .../LegacyUserPasswordResetWebhookEvent.cs | 11 + .../User/LegacyUserSavedWebhookEvent.cs | 12 + ...egacyUserTwoFactorRequestedWebhookEvent.cs | 12 +- .../User/LegacyUserUnlockedWebhookEvent.cs | 11 + .../Webhooks/WebhookEventAttribute.cs | 14 +- src/Umbraco.Core/Webhooks/WebhookEventBase.cs | 26 +- .../Webhooks/WebhookEventCollection.cs | 9 +- .../Webhooks/WebhookEventCollectionBuilder.cs | 15 + ...hookEventCollectionBuilderCmsExtensions.cs | 35 ++ ...WebhookEventCollectionBuilderExtensions.cs | 7 + .../Webhooks/WebhookEventContentBase.cs | 24 + .../Webhooks/WebhookPayloadType.cs | 3 + src/Umbraco.Core/Xml/XmlNodeListFactory.cs | 10 + 1927 files changed, 35808 insertions(+), 1711 deletions(-) diff --git a/src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs b/src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs index 65fe4932cc9b..9c9d9e3b093e 100644 --- a/src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs +++ b/src/Umbraco.Core/Actions/ActionDocumentPropertyRead.cs @@ -1,5 +1,11 @@ -namespace Umbraco.Cms.Core.Actions; +namespace Umbraco.Cms.Core.Actions; +/// +/// Represents the action that allows reading document property values. +/// +/// +/// This action is used for permission control when accessing property values on documents. +/// public class ActionDocumentPropertyRead : IAction { /// diff --git a/src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs b/src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs index 8effd527aea1..b9221e11bf9f 100644 --- a/src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs +++ b/src/Umbraco.Core/Actions/ActionDocumentPropertyWrite.cs @@ -1,5 +1,11 @@ -namespace Umbraco.Cms.Core.Actions; +namespace Umbraco.Cms.Core.Actions; +/// +/// Represents the action that allows writing document property values. +/// +/// +/// This action is used for permission control when modifying property values on documents. +/// public class ActionDocumentPropertyWrite : IAction { /// diff --git a/src/Umbraco.Core/Blocks/IPartialViewBlockEngine.cs b/src/Umbraco.Core/Blocks/IPartialViewBlockEngine.cs index 3b462d086502..5763fdfdcd1d 100644 --- a/src/Umbraco.Core/Blocks/IPartialViewBlockEngine.cs +++ b/src/Umbraco.Core/Blocks/IPartialViewBlockEngine.cs @@ -1,9 +1,17 @@ -using Umbraco.Cms.Core.Models.Blocks; +using Umbraco.Cms.Core.Models.Blocks; using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.Blocks; +/// +/// Defines a contract for rendering block references using partial views. +/// public interface IPartialViewBlockEngine { + /// + /// Executes the partial view associated with the given block reference and returns the rendered output. + /// + /// The block reference containing content and settings elements to render. + /// A task that represents the asynchronous operation. The task result contains the rendered HTML string. Task ExecuteAsync(IBlockReference blockReference); } diff --git a/src/Umbraco.Core/Cache/AppCacheExtensions.cs b/src/Umbraco.Core/Cache/AppCacheExtensions.cs index 32c1b772f014..435b48d7f8a5 100644 --- a/src/Umbraco.Core/Cache/AppCacheExtensions.cs +++ b/src/Umbraco.Core/Cache/AppCacheExtensions.cs @@ -3,10 +3,20 @@ namespace Umbraco.Extensions; /// -/// Extensions for strongly typed access +/// Provides extension methods for strongly typed access to and . /// public static class AppCacheExtensions { + /// + /// Gets a strongly typed cache item with the specified key, creating it if necessary using the provided factory. + /// + /// The type of the cached item. + /// The cache provider. + /// The cache key. + /// A factory function that creates the item if not found. + /// An optional cache timeout. + /// Whether the timeout is sliding (resets on access). + /// The cached item, or default if not found and factory returns null. public static T? GetCacheItem( this IAppPolicyCache provider, string cacheKey, @@ -18,6 +28,15 @@ public static class AppCacheExtensions return result == null ? default : result.TryConvertTo().Result; } + /// + /// Inserts a strongly typed cache item with the specified key. + /// + /// The type of the cached item. + /// The cache provider. + /// The cache key. + /// A factory function that creates the item to cache. + /// An optional cache timeout. + /// Whether the timeout is sliding (resets on access). public static void InsertCacheItem( this IAppPolicyCache provider, string cacheKey, @@ -26,18 +45,39 @@ public static void InsertCacheItem( bool isSliding = false) => provider.Insert(cacheKey, () => getCacheItem(), timeout, isSliding); + /// + /// Gets strongly typed cache items with keys starting with the specified value. + /// + /// The type of the cached items. + /// The cache provider. + /// The key prefix to search for. + /// A collection of cached items matching the search. public static IEnumerable GetCacheItemsByKeySearch(this IAppCache provider, string keyStartsWith) { IEnumerable result = provider.SearchByKey(keyStartsWith); return result.Select(x => x.TryConvertTo().Result); } + /// + /// Gets strongly typed cache items with keys matching a regular expression. + /// + /// The type of the cached items. + /// The cache provider. + /// The regular expression pattern to match keys against. + /// A collection of cached items matching the search. public static IEnumerable GetCacheItemsByKeyExpression(this IAppCache provider, string regexString) { IEnumerable result = provider.SearchByRegex(regexString); return result.Select(x => x.TryConvertTo().Result); } + /// + /// Gets a strongly typed cache item with the specified key. + /// + /// The type of the cached item. + /// The cache provider. + /// The cache key. + /// The cached item, or default if not found. public static T? GetCacheItem(this IAppCache provider, string cacheKey) { var result = provider.Get(cacheKey); @@ -56,6 +96,14 @@ public static void InsertCacheItem( return result.TryConvertTo().Result; } + /// + /// Gets a strongly typed cache item with the specified key, creating it if necessary using the provided factory. + /// + /// The type of the cached item. + /// The cache provider. + /// The cache key. + /// A factory function that creates the item if not found. + /// The cached item, or default if not found and factory returns null. public static T? GetCacheItem(this IAppCache provider, string cacheKey, Func getCacheItem) { var result = provider.Get(cacheKey, () => getCacheItem()); @@ -74,6 +122,16 @@ public static void InsertCacheItem( return result.TryConvertTo().Result; } + /// + /// Asynchronously gets a strongly typed cache item with the specified key, creating it if necessary using the provided factory. + /// + /// The type of the cached item. + /// The cache provider. + /// The cache key. + /// An async factory function that creates the item if not found. + /// An optional cache timeout. + /// Whether the timeout is sliding (resets on access). + /// A task representing the asynchronous operation, containing the cached item. public static async Task GetCacheItemAsync( this IAppPolicyCache provider, string cacheKey, @@ -108,6 +166,16 @@ public static void InsertCacheItem( private static bool RequestedNullRepresentationInCache() => typeof(T) == typeof(string); + /// + /// Asynchronously inserts a strongly typed cache item with the specified key. + /// + /// The type of the cached item. + /// The cache provider. + /// The cache key. + /// An async factory function that creates the item to cache. + /// An optional cache timeout. + /// Whether the timeout is sliding (resets on access). + /// A task representing the asynchronous operation. public static async Task InsertCacheItemAsync( this IAppPolicyCache provider, string cacheKey, diff --git a/src/Umbraco.Core/Cache/AppCaches.cs b/src/Umbraco.Core/Cache/AppCaches.cs index 60c7d0ed2275..82a406906106 100644 --- a/src/Umbraco.Core/Cache/AppCaches.cs +++ b/src/Umbraco.Core/Cache/AppCaches.cs @@ -69,17 +69,27 @@ public AppCaches( /// public IsolatedCaches IsolatedCaches { get; } + /// + /// Creates a new instance of with the specified request cache. + /// + /// The request cache to use. + /// A new instance. public static AppCaches Create(IRequestCache requestCache) => new( new DeepCloneAppCache(new ObjectCacheAppCache()), requestCache, new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); + /// public void Dispose() => // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method Dispose(true); + /// + /// Releases the unmanaged resources used by the and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (!_disposedValue) diff --git a/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs b/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs index 788e95f90924..039ab9e6eb8f 100644 --- a/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs +++ b/src/Umbraco.Core/Cache/AppPolicedCacheDictionary.cs @@ -24,6 +24,7 @@ public abstract class AppPolicedCacheDictionary : IDisposable /// protected AppPolicedCacheDictionary(Func cacheFactory) => _cacheFactory = cacheFactory; + /// public void Dispose() => // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method @@ -75,6 +76,10 @@ protected void ClearCache(TKey key) } } + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (!_disposedValue) diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs index 0e75b6820db5..49c0e6f8e553 100644 --- a/src/Umbraco.Core/Cache/CacheKeys.cs +++ b/src/Umbraco.Core/Cache/CacheKeys.cs @@ -1,27 +1,68 @@ namespace Umbraco.Cms.Core.Cache; /// -/// Constants storing cache keys used in caching +/// Constants storing cache keys used in caching. /// public static class CacheKeys { - public const string ApplicationsCacheKey = "ApplicationCache"; // used by SectionService + /// + /// Cache key for applications (sections) cache, used by SectionService. + /// + public const string ApplicationsCacheKey = "ApplicationCache"; + /// + /// Cache key prefix for template front-end cache. + /// // TODO: this one can probably be removed public const string TemplateFrontEndCacheKey = "template"; + /// + /// Cache key prefix for user group lookup by alias. + /// public const string UserGroupGetByAliasCacheKeyPrefix = "UserGroupRepository_GetByAlias_"; + /// + /// Cache key prefix for user's content start nodes. + /// public const string UserAllContentStartNodesPrefix = "AllContentStartNodes"; + + /// + /// Cache key prefix for user's media start nodes. + /// public const string UserAllMediaStartNodesPrefix = "AllMediaStartNodes"; + + /// + /// Cache key prefix for user's media start node paths. + /// public const string UserMediaStartNodePathsPrefix = "MediaStartNodePaths"; + + /// + /// Cache key prefix for user's content start node paths. + /// public const string UserContentStartNodePathsPrefix = "ContentStartNodePaths"; + /// + /// Cache key for content recycle bin. + /// public const string ContentRecycleBinCacheKey = "recycleBin_content"; + + /// + /// Cache key for media recycle bin. + /// public const string MediaRecycleBinCacheKey = "recycleBin_media"; + /// + /// Cache key prefix for preview (draft) property cache values. + /// public const string PreviewPropertyCacheKeyPrefix = "Cache.Property.CacheValues[D:"; + + /// + /// Cache key prefix for published property cache values. + /// public const string PropertyCacheKeyPrefix = "Cache.Property.CacheValues[P:"; + /// + /// Cache key prefix for member username lookups. + /// public const string MemberUserNameCachePrefix = "uRepo_userNameKey+"; } diff --git a/src/Umbraco.Core/Cache/DataTypeConfigurationCache.cs b/src/Umbraco.Core/Cache/DataTypeConfigurationCache.cs index 70c9b4161be9..f7b99a755408 100644 --- a/src/Umbraco.Core/Cache/DataTypeConfigurationCache.cs +++ b/src/Umbraco.Core/Cache/DataTypeConfigurationCache.cs @@ -6,20 +6,32 @@ namespace Umbraco.Cms.Core.Cache; /// -/// This cache is a temporary measure to reduce the amount of computational power required to deserialize and initialize when fetched from the main cache/database, -/// because datatypes are fetched multiple times troughout a (backoffice content) request with a lot of content (or nested content) and each of these fetches initializes certain fields on the datatypes. +/// Implements to cache data type configurations. /// +/// +/// This cache is a temporary measure to reduce the amount of computational power required to +/// deserialize and initialize when fetched from the main cache/database, +/// because data types are fetched multiple times throughout a (backoffice content) request with +/// a lot of content (or nested content) and each of these fetches initializes certain fields on the data types. +/// internal sealed class DataTypeConfigurationCache : IDataTypeConfigurationCache { private readonly IDataTypeService _dataTypeService; private readonly IMemoryCache _memoryCache; + /// + /// Initializes a new instance of the class. + /// + /// The data type service. + /// The memory cache. + /// The ID/key map service. public DataTypeConfigurationCache(IDataTypeService dataTypeService, IMemoryCache memoryCache, IIdKeyMap idKeyMap) { _dataTypeService = dataTypeService; _memoryCache = memoryCache; } + /// public T? GetConfigurationAs(Guid key) where T : class { @@ -39,6 +51,7 @@ public DataTypeConfigurationCache(IDataTypeService dataTypeService, IMemoryCache return configuration; } + /// public void ClearCache(IEnumerable keys) { foreach (Guid key in keys) diff --git a/src/Umbraco.Core/Cache/DataTypeConfigurationCacheRefresher.cs b/src/Umbraco.Core/Cache/DataTypeConfigurationCacheRefresher.cs index 071acc795f4d..68311f748ef4 100644 --- a/src/Umbraco.Core/Cache/DataTypeConfigurationCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/DataTypeConfigurationCacheRefresher.cs @@ -3,13 +3,25 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Handles to clear the data type configuration cache. +/// +/// +/// This handler ensures that the is cleared when +/// data types are modified, keeping cached configurations in sync with the database. +/// internal sealed class DataTypeConfigurationCacheRefresher : INotificationHandler { private readonly IDataTypeConfigurationCache _dataTypeConfigurationCache; + /// + /// Initializes a new instance of the class. + /// + /// The data type configuration cache. public DataTypeConfigurationCacheRefresher(IDataTypeConfigurationCache dataTypeConfigurationCache) => _dataTypeConfigurationCache = dataTypeConfigurationCache; + /// public void Handle(DataTypeCacheRefresherNotification notification) => _dataTypeConfigurationCache.ClearCache(((DataTypeCacheRefresher.JsonPayload[])notification.MessageObject).Select(x => x.Key)); } diff --git a/src/Umbraco.Core/Cache/DeepCloneAppCache.cs b/src/Umbraco.Core/Cache/DeepCloneAppCache.cs index ae9fb11c967c..4de30422466f 100644 --- a/src/Umbraco.Core/Cache/DeepCloneAppCache.cs +++ b/src/Umbraco.Core/Cache/DeepCloneAppCache.cs @@ -124,11 +124,16 @@ public void Insert(string key, Func factory, TimeSpan? timeout = null, /// public void ClearByRegex(string regex) => InnerCache.ClearByRegex(regex); + /// public void Dispose() => // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method Dispose(true); + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (!_disposedValue) diff --git a/src/Umbraco.Core/Cache/DictionaryAppCache.cs b/src/Umbraco.Core/Cache/DictionaryAppCache.cs index fa0ec1b0e0b2..f7a9cd0320e4 100644 --- a/src/Umbraco.Core/Cache/DictionaryAppCache.cs +++ b/src/Umbraco.Core/Cache/DictionaryAppCache.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using System.Collections.Concurrent; using System.Text.RegularExpressions; using Umbraco.Extensions; @@ -15,6 +15,9 @@ public class DictionaryAppCache : IRequestCache /// private readonly ConcurrentDictionary _items = new(); + /// + /// Gets the number of items in the cache. + /// public int Count => _items.Count; /// @@ -38,8 +41,10 @@ public class DictionaryAppCache : IRequestCache return null; } + /// public bool Set(string key, object? value) => _items.TryAdd(key, value); + /// public bool Remove(string key) => _items.TryRemove(key, out _); /// @@ -109,7 +114,12 @@ public virtual void ClearByRegex(string regex) _items.RemoveAll(kvp => compiled.IsMatch(kvp.Key)); } + /// + /// Returns an enumerator that iterates through the cache items. + /// + /// An enumerator for the cache items. public IEnumerator> GetEnumerator() => _items.GetEnumerator(); + /// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } diff --git a/src/Umbraco.Core/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Core/Cache/DistributedCacheExtensions.cs index 3786951370e4..d08cf004c685 100644 --- a/src/Umbraco.Core/Cache/DistributedCacheExtensions.cs +++ b/src/Umbraco.Core/Cache/DistributedCacheExtensions.cs @@ -16,6 +16,10 @@ public static class DistributedCacheExtensions { #region PublicAccessCacheRefresher + /// + /// Refreshes all public access entries in the distributed cache. + /// + /// The distributed cache. public static void RefreshPublicAccess(this DistributedCache dc) => dc.RefreshAll(PublicAccessCacheRefresher.UniqueId); @@ -23,6 +27,11 @@ public static void RefreshPublicAccess(this DistributedCache dc) #region UserCacheRefresher + /// + /// Removes the specified users from the distributed cache. + /// + /// The distributed cache. + /// The users to remove from cache. public static void RemoveUserCache(this DistributedCache dc, IEnumerable users) { IEnumerable payloads = users.Select(x => new UserCacheRefresher.JsonPayload() @@ -34,6 +43,11 @@ public static void RemoveUserCache(this DistributedCache dc, IEnumerable dc.RefreshByPayload(UserCacheRefresher.UniqueId, payloads); } + /// + /// Refreshes the specified users in the distributed cache. + /// + /// The distributed cache. + /// The users to refresh in cache. public static void RefreshUserCache(this DistributedCache dc, IEnumerable users) { IEnumerable payloads = users.Select(x => new UserCacheRefresher.JsonPayload() @@ -45,6 +59,10 @@ public static void RefreshUserCache(this DistributedCache dc, IEnumerable dc.RefreshByPayload(UserCacheRefresher.UniqueId, payloads); } + /// + /// Refreshes all users in the distributed cache. + /// + /// The distributed cache. public static void RefreshAllUserCache(this DistributedCache dc) => dc.RefreshAll(UserCacheRefresher.UniqueId); @@ -52,18 +70,42 @@ public static void RefreshAllUserCache(this DistributedCache dc) #region UserGroupCacheRefresher + /// + /// Removes a user group from the distributed cache by user identifier. + /// + /// The distributed cache. + /// The user identifier. public static void RemoveUserGroupCache(this DistributedCache dc, int userId) => dc.Remove(UserGroupCacheRefresher.UniqueId, userId); + /// + /// Removes the specified user groups from the distributed cache. + /// + /// The distributed cache. + /// The user groups to remove from cache. public static void RemoveUserGroupCache(this DistributedCache dc, IEnumerable userGroups) => dc.Remove(UserGroupCacheRefresher.UniqueId, userGroups.Select(x => x.Id).Distinct().ToArray()); + /// + /// Refreshes a user group in the distributed cache by user identifier. + /// + /// The distributed cache. + /// The user identifier. public static void RefreshUserGroupCache(this DistributedCache dc, int userId) => dc.Refresh(UserGroupCacheRefresher.UniqueId, userId); + /// + /// Refreshes the specified user groups in the distributed cache. + /// + /// The distributed cache. + /// The user groups to refresh in cache. public static void RefreshUserGroupCache(this DistributedCache dc, IEnumerable userGroups) => dc.Refresh(UserGroupCacheRefresher.UniqueId, userGroups.Select(x => x.Id).Distinct().ToArray()); + /// + /// Refreshes all user groups in the distributed cache. + /// + /// The distributed cache. public static void RefreshAllUserGroupCache(this DistributedCache dc) => dc.RefreshAll(UserGroupCacheRefresher.UniqueId); @@ -71,15 +113,35 @@ public static void RefreshAllUserGroupCache(this DistributedCache dc) #region TemplateCacheRefresher + /// + /// Refreshes a template in the distributed cache. + /// + /// The distributed cache. + /// The template identifier. public static void RefreshTemplateCache(this DistributedCache dc, int templateId) => dc.Refresh(TemplateCacheRefresher.UniqueId, templateId); + /// + /// Refreshes the specified templates in the distributed cache. + /// + /// The distributed cache. + /// The templates to refresh in cache. public static void RefreshTemplateCache(this DistributedCache dc, IEnumerable templates) => dc.Refresh(TemplateCacheRefresher.UniqueId, templates.Select(x => x.Id).Distinct().ToArray()); + /// + /// Removes a template from the distributed cache. + /// + /// The distributed cache. + /// The template identifier. public static void RemoveTemplateCache(this DistributedCache dc, int templateId) => dc.Remove(TemplateCacheRefresher.UniqueId, templateId); + /// + /// Removes the specified templates from the distributed cache. + /// + /// The distributed cache. + /// The templates to remove from cache. public static void RemoveTemplateCache(this DistributedCache dc, IEnumerable templates) => dc.Remove(TemplateCacheRefresher.UniqueId, templates.Select(x => x.Id).Distinct().ToArray()); @@ -87,15 +149,35 @@ public static void RemoveTemplateCache(this DistributedCache dc, IEnumerable + /// Refreshes a dictionary item in the distributed cache. + /// + /// The distributed cache. + /// The dictionary item identifier. public static void RefreshDictionaryCache(this DistributedCache dc, int dictionaryItemId) => dc.Refresh(DictionaryCacheRefresher.UniqueId, dictionaryItemId); + /// + /// Refreshes the specified dictionary items in the distributed cache. + /// + /// The distributed cache. + /// The dictionary items to refresh in cache. public static void RefreshDictionaryCache(this DistributedCache dc, IEnumerable dictionaryItems) => dc.Refresh(DictionaryCacheRefresher.UniqueId, dictionaryItems.Select(x => x.Id).Distinct().ToArray()); + /// + /// Removes a dictionary item from the distributed cache. + /// + /// The distributed cache. + /// The dictionary item identifier. public static void RemoveDictionaryCache(this DistributedCache dc, int dictionaryItemId) => dc.Remove(DictionaryCacheRefresher.UniqueId, dictionaryItemId); + /// + /// Removes the specified dictionary items from the distributed cache. + /// + /// The distributed cache. + /// The dictionary items to remove from cache. public static void RemoveDictionaryCache(this DistributedCache dc, IEnumerable dictionaryItems) => dc.Remove(DictionaryCacheRefresher.UniqueId, dictionaryItems.Select(x => x.Id).Distinct().ToArray()); @@ -103,9 +185,19 @@ public static void RemoveDictionaryCache(this DistributedCache dc, IEnumerable + /// Refreshes the specified data types in the distributed cache. + /// + /// The distributed cache. + /// The data types to refresh in cache. public static void RefreshDataTypeCache(this DistributedCache dc, IEnumerable dataTypes) => dc.RefreshByPayload(DataTypeCacheRefresher.UniqueId, dataTypes.DistinctBy(x => (x.Id, x.Key)).Select(x => new DataTypeCacheRefresher.JsonPayload(x.Id, x.Key, false))); + /// + /// Removes the specified data types from the distributed cache. + /// + /// The distributed cache. + /// The data types to remove from cache. public static void RemoveDataTypeCache(this DistributedCache dc, IEnumerable dataTypes) => dc.RefreshByPayload(DataTypeCacheRefresher.UniqueId, dataTypes.DistinctBy(x => (x.Id, x.Key)).Select(x => new DataTypeCacheRefresher.JsonPayload(x.Id, x.Key, true))); @@ -113,6 +205,11 @@ public static void RemoveDataTypeCache(this DistributedCache dc, IEnumerable + /// Refreshes the value editor cache for the specified data types. + /// + /// The distributed cache. + /// The data types whose value editors should be refreshed. public static void RefreshValueEditorCache(this DistributedCache dc, IEnumerable dataTypes) => dc.RefreshByPayload(ValueEditorCacheRefresher.UniqueId, dataTypes.DistinctBy(x => (x.Id, x.Key)).Select(x => new DataTypeCacheRefresher.JsonPayload(x.Id, x.Key, false))); @@ -120,6 +217,10 @@ public static void RefreshValueEditorCache(this DistributedCache dc, IEnumerable #region ContentCacheRefresher + /// + /// Refreshes all content in the distributed cache. + /// + /// The distributed cache. public static void RefreshAllContentCache(this DistributedCache dc) { ContentCacheRefresher.JsonPayload[] payloads = new[] @@ -134,6 +235,11 @@ public static void RefreshAllContentCache(this DistributedCache dc) dc.RefreshByPayload(ContentCacheRefresher.UniqueId, payloads); } + /// + /// Refreshes the content cache for the specified content changes. + /// + /// The distributed cache. + /// The content changes to refresh. public static void RefreshContentCache(this DistributedCache dc, IEnumerable> changes) { IEnumerable payloads = changes.Select(x => new ContentCacheRefresher.JsonPayload() @@ -153,25 +259,54 @@ public static void RefreshContentCache(this DistributedCache dc, IEnumerable + /// Refreshes the specified members in the distributed cache. + /// + /// The distributed cache. + /// The members to refresh in cache. [Obsolete("Please use the overload taking all parameters. Scheduled for removal in Umbraco 18.")] public static void RefreshMemberCache(this DistributedCache dc, IEnumerable members) => dc.RefreshMemberCache(members, new Dictionary()); + /// + /// Refreshes the specified members in the distributed cache. + /// + /// The distributed cache. + /// The members to refresh in cache. + /// The notification state. public static void RefreshMemberCache(this DistributedCache dc, IEnumerable members, IDictionary state) => dc.RefreshByPayload( MemberCacheRefresher.UniqueId, GetPayloads(members, state, false)); + /// + /// Removes the specified members from the distributed cache. + /// + /// The distributed cache. + /// The members to remove from cache. [Obsolete("Please use the overload taking all parameters. Scheduled for removal in Umbraco 18.")] public static void RemoveMemberCache(this DistributedCache dc, IEnumerable members) => dc.RemoveMemberCache(members, new Dictionary()); + /// + /// Removes the specified members from the distributed cache. + /// + /// The distributed cache. + /// The members to remove from cache. + /// The notification state. public static void RemoveMemberCache(this DistributedCache dc, IEnumerable members, IDictionary state) => dc.RefreshByPayload( MemberCacheRefresher.UniqueId, GetPayloads(members, state, true)); - // Internal for unit test. + /// + /// Gets the JSON payloads for member cache refresh operations. + /// + /// The members to create payloads for. + /// The notification state dictionary. + /// Whether the members were removed. + /// An enumerable of JSON payloads for the member cache refresher. + /// Internal for unit test. internal static IEnumerable GetPayloads(IEnumerable members, IDictionary state, bool removed) => members .DistinctBy(x => (x.Id, x.Username)) @@ -201,15 +336,35 @@ public static void RemoveMemberCache(this DistributedCache dc, IEnumerable + /// Refreshes a member group in the distributed cache. + /// + /// The distributed cache. + /// The member group identifier. public static void RefreshMemberGroupCache(this DistributedCache dc, int memberGroupId) => dc.Refresh(MemberGroupCacheRefresher.UniqueId, memberGroupId); + /// + /// Refreshes the specified member groups in the distributed cache. + /// + /// The distributed cache. + /// The member groups to refresh in cache. public static void RefreshMemberGroupCache(this DistributedCache dc, IEnumerable memberGroups) => dc.Refresh(MemberGroupCacheRefresher.UniqueId, memberGroups.Select(x => x.Id).Distinct().ToArray()); + /// + /// Removes a member group from the distributed cache. + /// + /// The distributed cache. + /// The member group identifier. public static void RemoveMemberGroupCache(this DistributedCache dc, int memberGroupId) => dc.Remove(MemberGroupCacheRefresher.UniqueId, memberGroupId); + /// + /// Removes the specified member groups from the distributed cache. + /// + /// The distributed cache. + /// The member groups to remove from cache. public static void RemoveMemberGroupCache(this DistributedCache dc, IEnumerable memberGroups) => dc.Remove(MemberGroupCacheRefresher.UniqueId, memberGroups.Select(x => x.Id).Distinct().ToArray()); @@ -217,11 +372,19 @@ public static void RemoveMemberGroupCache(this DistributedCache dc, IEnumerable< #region MediaCacheRefresher + /// + /// Refreshes all media in the distributed cache. + /// + /// The distributed cache. public static void RefreshAllMediaCache(this DistributedCache dc) // note: refresh all media cache does refresh content types too => dc.RefreshByPayload(MediaCacheRefresher.UniqueId, new MediaCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll).Yield()); - + /// + /// Refreshes the media cache for the specified media changes. + /// + /// The distributed cache. + /// The media changes to refresh. public static void RefreshMediaCache(this DistributedCache dc, IEnumerable> changes) => dc.RefreshByPayload(MediaCacheRefresher.UniqueId, changes.DistinctBy(x => (x.Item.Id, x.Item.Key, x.ChangeTypes)).Select(x => new MediaCacheRefresher.JsonPayload(x.Item.Id, x.Item.Key, x.ChangeTypes))); @@ -229,6 +392,10 @@ public static void RefreshMediaCache(this DistributedCache dc, IEnumerable + /// Refreshes all published snapshots including content, media, and domain caches. + /// + /// The distributed cache. public static void RefreshAllPublishedSnapshot(this DistributedCache dc) { // note: refresh all content & media caches does refresh content types too @@ -241,12 +408,27 @@ public static void RefreshAllPublishedSnapshot(this DistributedCache dc) #region ContentTypeCacheRefresher + /// + /// Refreshes the content type cache for the specified content type changes. + /// + /// The distributed cache. + /// The content type changes to refresh. public static void RefreshContentTypeCache(this DistributedCache dc, IEnumerable> changes) => dc.RefreshByPayload(ContentTypeCacheRefresher.UniqueId, changes.DistinctBy(x => (x.Item.Id, x.ChangeTypes)).Select(x => new ContentTypeCacheRefresher.JsonPayload(typeof(IContentType).Name, x.Item.Id, x.ChangeTypes))); + /// + /// Refreshes the content type cache for the specified media type changes. + /// + /// The distributed cache. + /// The media type changes to refresh. public static void RefreshContentTypeCache(this DistributedCache dc, IEnumerable> changes) => dc.RefreshByPayload(ContentTypeCacheRefresher.UniqueId, changes.DistinctBy(x => (x.Item.Id, x.ChangeTypes)).Select(x => new ContentTypeCacheRefresher.JsonPayload(typeof(IMediaType).Name, x.Item.Id, x.ChangeTypes))); + /// + /// Refreshes the content type cache for the specified member type changes. + /// + /// The distributed cache. + /// The member type changes to refresh. public static void RefreshContentTypeCache(this DistributedCache dc, IEnumerable> changes) => dc.RefreshByPayload(ContentTypeCacheRefresher.UniqueId, changes.DistinctBy(x => (x.Item.Id, x.ChangeTypes)).Select(x => new ContentTypeCacheRefresher.JsonPayload(typeof(IMemberType).Name, x.Item.Id, x.ChangeTypes))); @@ -254,12 +436,26 @@ public static void RefreshContentTypeCache(this DistributedCache dc, IEnumerable #region DomainCacheRefresher + /// + /// Refreshes the specified domains in the distributed cache. + /// + /// The distributed cache. + /// The domains to refresh in cache. public static void RefreshDomainCache(this DistributedCache dc, IEnumerable domains) => dc.RefreshByPayload(DomainCacheRefresher.UniqueId, domains.DistinctBy(x => x.Id).Select(x => new DomainCacheRefresher.JsonPayload(x.Id, DomainChangeTypes.Refresh))); + /// + /// Removes the specified domains from the distributed cache. + /// + /// The distributed cache. + /// The domains to remove from cache. public static void RemoveDomainCache(this DistributedCache dc, IEnumerable domains) => dc.RefreshByPayload(DomainCacheRefresher.UniqueId, domains.DistinctBy(x => x.Id).Select(x => new DomainCacheRefresher.JsonPayload(x.Id, DomainChangeTypes.Remove))); + /// + /// Refreshes all domains in the distributed cache. + /// + /// The distributed cache. public static void RefreshAllDomainCache(this DistributedCache dc) => dc.RefreshByPayload(DomainCacheRefresher.UniqueId, new DomainCacheRefresher.JsonPayload(0, DomainChangeTypes.RefreshAll).Yield()); @@ -267,6 +463,11 @@ public static void RefreshAllDomainCache(this DistributedCache dc) #region LanguageCacheRefresher + /// + /// Refreshes the specified languages in the distributed cache. + /// + /// The distributed cache. + /// The languages to refresh in cache. public static void RefreshLanguageCache(this DistributedCache dc, IEnumerable languages) => dc.RefreshByPayload(LanguageCacheRefresher.UniqueId, languages.DistinctBy(x => (x.Id, x.IsoCode)).Select(x => new LanguageCacheRefresher.JsonPayload( x.Id, @@ -275,6 +476,11 @@ public static void RefreshLanguageCache(this DistributedCache dc, IEnumerable + /// Removes the specified languages from the distributed cache. + /// + /// The distributed cache. + /// The languages to remove from cache. public static void RemoveLanguageCache(this DistributedCache dc, IEnumerable languages) => dc.RefreshByPayload(LanguageCacheRefresher.UniqueId, languages.DistinctBy(x => (x.Id, x.IsoCode)).Select(x => new LanguageCacheRefresher.JsonPayload(x.Id, x.IsoCode, LanguageCacheRefresher.JsonPayload.LanguageChangeType.Remove))); @@ -282,15 +488,35 @@ public static void RemoveLanguageCache(this DistributedCache dc, IEnumerable + /// Refreshes a relation type in the distributed cache. + /// + /// The distributed cache. + /// The relation type identifier. public static void RefreshRelationTypeCache(this DistributedCache dc, int id) => dc.Refresh(RelationTypeCacheRefresher.UniqueId, id); + /// + /// Refreshes the specified relation types in the distributed cache. + /// + /// The distributed cache. + /// The relation types to refresh in cache. public static void RefreshRelationTypeCache(this DistributedCache dc, IEnumerable relationTypes) => dc.Refresh(RelationTypeCacheRefresher.UniqueId, relationTypes.Select(x => x.Id).Distinct().ToArray()); + /// + /// Removes a relation type from the distributed cache. + /// + /// The distributed cache. + /// The relation type identifier. public static void RemoveRelationTypeCache(this DistributedCache dc, int id) => dc.Remove(RelationTypeCacheRefresher.UniqueId, id); + /// + /// Removes the specified relation types from the distributed cache. + /// + /// The distributed cache. + /// The relation types to remove from cache. public static void RemoveRelationTypeCache(this DistributedCache dc, IEnumerable relationTypes) => dc.Remove(RelationTypeCacheRefresher.UniqueId, relationTypes.Select(x => x.Id).Distinct().ToArray()); diff --git a/src/Umbraco.Core/Cache/FastDictionaryAppCache.cs b/src/Umbraco.Core/Cache/FastDictionaryAppCache.cs index e99cdad89986..9e94f014d587 100644 --- a/src/Umbraco.Core/Cache/FastDictionaryAppCache.cs +++ b/src/Umbraco.Core/Cache/FastDictionaryAppCache.cs @@ -14,8 +14,14 @@ public class FastDictionaryAppCache : IAppCache /// private readonly ConcurrentDictionary> _items = new(); + /// + /// Gets all cache keys. + /// public IEnumerable Keys => _items.Keys; + /// + /// Gets the number of items in the cache. + /// public int Count => _items.Count; /// diff --git a/src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs b/src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs index 967d5aa5a70b..e46b1c660bfe 100644 --- a/src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs +++ b/src/Umbraco.Core/Cache/FastDictionaryAppCacheBase.cs @@ -8,7 +8,9 @@ namespace Umbraco.Cms.Core.Cache; /// public abstract class FastDictionaryAppCacheBase : IAppCache { - // prefix cache keys so we know which one are ours + /// + /// The prefix used for all cache keys to distinguish them from other cache entries. + /// protected const string CacheItemPrefix = "umbrtmche"; #region IAppCache @@ -264,26 +266,53 @@ public virtual void ClearByRegex(string regex) #region Dictionary - // manipulate the underlying cache entries - // these *must* be called from within the appropriate locks - // and use the full prefixed cache keys + /// + /// Gets all dictionary entries from the underlying cache. + /// + /// The dictionary entries. + /// Must be called from within the appropriate locks. protected abstract IEnumerable> GetDictionaryEntries(); + /// + /// Removes an entry from the underlying cache. + /// + /// The full prefixed cache key. + /// Must be called from within the appropriate locks. protected abstract void RemoveEntry(string key); + /// + /// Gets an entry from the underlying cache. + /// + /// The full prefixed cache key. + /// The cached value, or null if not found. + /// Must be called from within the appropriate locks. protected abstract object? GetEntry(string key); - // read-write lock the underlying cache - // protected abstract IDisposable ReadLock { get; } - // protected abstract IDisposable WriteLock { get; } + /// + /// Enters a read lock on the underlying cache. + /// protected abstract void EnterReadLock(); + /// + /// Exits the read lock on the underlying cache. + /// protected abstract void ExitReadLock(); + /// + /// Enters a write lock on the underlying cache. + /// protected abstract void EnterWriteLock(); + /// + /// Exits the write lock on the underlying cache. + /// protected abstract void ExitWriteLock(); + /// + /// Gets the prefixed cache key. + /// + /// The public cache key. + /// The full prefixed cache key. protected string GetCacheKey(string key) => $"{CacheItemPrefix}-{key}"; #endregion diff --git a/src/Umbraco.Core/Cache/IRepositoryCachePolicy.cs b/src/Umbraco.Core/Cache/IRepositoryCachePolicy.cs index 4352f9be31df..004c233a84ce 100644 --- a/src/Umbraco.Core/Cache/IRepositoryCachePolicy.cs +++ b/src/Umbraco.Core/Cache/IRepositoryCachePolicy.cs @@ -2,6 +2,16 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Defines a repository cache policy for managing cached entities. +/// +/// The type of the entity. +/// The type of the entity identifier. +/// +/// Repository cache policies control how repositories interact with caches, +/// determining when to read from cache, when to populate cache, and how to +/// keep caches in sync with the underlying data store. +/// public interface IRepositoryCachePolicy where TEntity : class, IEntity { diff --git a/src/Umbraco.Core/Cache/IRequestCache.cs b/src/Umbraco.Core/Cache/IRequestCache.cs index f88bc3bb249c..3819e94cc3de 100644 --- a/src/Umbraco.Core/Cache/IRequestCache.cs +++ b/src/Umbraco.Core/Cache/IRequestCache.cs @@ -1,13 +1,34 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Defines a request-level cache that stores items for the duration of a single HTTP request. +/// +/// +/// The request cache is designed to store transient data that is only valid within the context +/// of a single HTTP request. Outside a web environment, the behavior of this cache is unspecified. +/// public interface IRequestCache : IAppCache, IEnumerable> { /// - /// Returns true if the request cache is available otherwise false + /// Gets a value indicating whether the request cache is available. /// + /// + /// true if the request cache is available; otherwise, false. + /// bool IsAvailable { get; } + /// + /// Sets a value in the request cache. + /// + /// The key of the item to set. + /// The value to store in the cache. + /// true if the value was set successfully; otherwise, false. bool Set(string key, object? value); + /// + /// Removes a value from the request cache. + /// + /// The key of the item to remove. + /// true if the item was removed successfully; otherwise, false. bool Remove(string key); } diff --git a/src/Umbraco.Core/Cache/IValueEditorCache.cs b/src/Umbraco.Core/Cache/IValueEditorCache.cs index 790907c7500a..0061922927e6 100644 --- a/src/Umbraco.Core/Cache/IValueEditorCache.cs +++ b/src/Umbraco.Core/Cache/IValueEditorCache.cs @@ -3,9 +3,26 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Provides caching for instances associated with data types. +/// +/// +/// This cache reduces the computational overhead of repeatedly creating value editors for +/// the same data type and editor combinations during request processing. +/// public interface IValueEditorCache { + /// + /// Gets the value editor for the specified data editor and data type combination. + /// + /// The data editor. + /// The data type. + /// The cached or newly created . public IDataValueEditor GetValueEditor(IDataEditor dataEditor, IDataType dataType); + /// + /// Clears the cached value editors for the specified data type identifiers. + /// + /// The data type identifiers to clear from the cache. public void ClearCache(IEnumerable dataTypeIds); } diff --git a/src/Umbraco.Core/Cache/NoAppCache.cs b/src/Umbraco.Core/Cache/NoAppCache.cs index f140680b8c9d..5a61696e1de0 100644 --- a/src/Umbraco.Core/Cache/NoAppCache.cs +++ b/src/Umbraco.Core/Cache/NoAppCache.cs @@ -7,6 +7,12 @@ namespace Umbraco.Cms.Core.Cache; /// public class NoAppCache : IAppPolicyCache, IRequestCache { + /// + /// Initializes a new instance of the class. + /// + /// + /// Protected to enforce singleton pattern via . + /// protected NoAppCache() { } @@ -74,12 +80,19 @@ public virtual void ClearByRegex(string regex) { } + /// public bool Set(string key, object? value) => false; + /// public bool Remove(string key) => false; + /// + /// Returns an enumerator that iterates through an empty collection. + /// + /// An enumerator for an empty collection. public IEnumerator> GetEnumerator() => new Dictionary().GetEnumerator(); + /// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } diff --git a/src/Umbraco.Core/Cache/NoCacheRepositoryCachePolicy.cs b/src/Umbraco.Core/Cache/NoCacheRepositoryCachePolicy.cs index 2b662d4c2cde..4a347bba5747 100644 --- a/src/Umbraco.Core/Cache/NoCacheRepositoryCachePolicy.cs +++ b/src/Umbraco.Core/Cache/NoCacheRepositoryCachePolicy.cs @@ -2,32 +2,55 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Implements with no caching behavior. +/// +/// The type of the entity. +/// The type of the entity identifier. +/// +/// This policy bypasses all caching and directly delegates to the repository methods. +/// Used when caching is not desired for a particular repository. +/// public class NoCacheRepositoryCachePolicy : IRepositoryCachePolicy where TEntity : class, IEntity { + /// + /// Initializes a new instance of the class. + /// private NoCacheRepositoryCachePolicy() { } + /// + /// Gets the singleton instance of the no-cache policy. + /// public static NoCacheRepositoryCachePolicy Instance { get; } = new(); + /// public TEntity? Get(TId? id, Func performGet, Func?> performGetAll) => performGet(id); + /// public TEntity? GetCached(TId id) => null; + /// public bool Exists(TId id, Func performExists, Func?> performGetAll) => performExists(id); + /// public void Create(TEntity entity, Action persistNew) => persistNew(entity); + /// public void Update(TEntity entity, Action persistUpdated) => persistUpdated(entity); + /// public void Delete(TEntity entity, Action persistDeleted) => persistDeleted(entity); + /// public TEntity[] GetAll(TId[]? ids, Func?> performGetAll) => performGetAll(ids)?.ToArray() ?? Array.Empty(); + /// public void ClearAll() { } diff --git a/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs index 4b9d237ea4c6..e6cd6a792171 100644 --- a/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs +++ b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs @@ -330,10 +330,15 @@ private void ClearByPredicate(Func predicate) } } + /// public void Dispose() // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method => Dispose(true); + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (!_disposedValue) diff --git a/src/Umbraco.Core/Cache/Refreshers/CacheRefresherBase.cs b/src/Umbraco.Core/Cache/Refreshers/CacheRefresherBase.cs index 0873d32cb853..acc6ea166143 100644 --- a/src/Umbraco.Core/Cache/Refreshers/CacheRefresherBase.cs +++ b/src/Umbraco.Core/Cache/Refreshers/CacheRefresherBase.cs @@ -85,6 +85,9 @@ public virtual void Remove(int id) => /// protected AppCaches AppCaches { get; } + /// + /// Gets the event aggregator for publishing notifications. + /// protected IEventAggregator EventAggregator { get; } /// diff --git a/src/Umbraco.Core/Cache/Refreshers/CacheRefresherCollection.cs b/src/Umbraco.Core/Cache/Refreshers/CacheRefresherCollection.cs index 301f6bbdaf1b..51f63d610d4f 100644 --- a/src/Umbraco.Core/Cache/Refreshers/CacheRefresherCollection.cs +++ b/src/Umbraco.Core/Cache/Refreshers/CacheRefresherCollection.cs @@ -2,13 +2,28 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Represents a collection of instances. +/// +/// +/// This collection provides access to all registered cache refreshers, allowing lookup by unique identifier. +/// public class CacheRefresherCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the cache refresher instances. public CacheRefresherCollection(Func> items) : base(items) { } + /// + /// Gets the cache refresher with the specified unique identifier. + /// + /// The unique identifier of the cache refresher. + /// The cache refresher with the specified identifier, or null if not found. public ICacheRefresher? this[Guid id] => this.FirstOrDefault(x => x.RefresherUniqueId == id); } diff --git a/src/Umbraco.Core/Cache/Refreshers/CacheRefresherCollectionBuilder.cs b/src/Umbraco.Core/Cache/Refreshers/CacheRefresherCollectionBuilder.cs index 79b44ab53d14..3cf7abd3c0eb 100644 --- a/src/Umbraco.Core/Cache/Refreshers/CacheRefresherCollectionBuilder.cs +++ b/src/Umbraco.Core/Cache/Refreshers/CacheRefresherCollectionBuilder.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Builds a from registered instances. +/// +/// +/// Use this builder to register custom cache refreshers during application composition. +/// public class CacheRefresherCollectionBuilder : LazyCollectionBuilderBase { + /// protected override CacheRefresherCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/Cache/Refreshers/CacheRefresherNotificationFactory.cs b/src/Umbraco.Core/Cache/Refreshers/CacheRefresherNotificationFactory.cs index 40bab16b12dd..4a12a3d2ea16 100644 --- a/src/Umbraco.Core/Cache/Refreshers/CacheRefresherNotificationFactory.cs +++ b/src/Umbraco.Core/Cache/Refreshers/CacheRefresherNotificationFactory.cs @@ -12,6 +12,10 @@ public sealed class CacheRefresherNotificationFactory : ICacheRefresherNotificat { private readonly IServiceProvider _serviceProvider; + /// + /// Initializes a new instance of the class. + /// + /// The service provider. public CacheRefresherNotificationFactory(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; /// diff --git a/src/Umbraco.Core/Cache/Refreshers/ICacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/ICacheRefresher.cs index dba0cd3b3fa4..b570873901a1 100644 --- a/src/Umbraco.Core/Cache/Refreshers/ICacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/ICacheRefresher.cs @@ -3,35 +3,68 @@ namespace Umbraco.Cms.Core.Cache; /// -/// The IcacheRefresher Interface is used for load balancing. +/// Defines a cache refresher used for distributed cache invalidation in load-balanced environments. /// +/// +/// Cache refreshers are responsible for invalidating or refreshing cached data across all servers +/// in a load-balanced cluster when data changes occur. +/// public interface ICacheRefresher : IDiscoverable { + /// + /// Gets the unique identifier for this cache refresher. + /// Guid RefresherUniqueId { get; } + /// + /// Gets the name of this cache refresher. + /// string Name { get; } + /// + /// Refreshes all cached items managed by this refresher. + /// void RefreshAll(); + /// + /// Refreshes a specific cached item by its integer identifier. + /// + /// The identifier of the item to refresh. void Refresh(int id); + /// + /// Removes a specific cached item by its integer identifier. + /// + /// The identifier of the item to remove. void Remove(int id); + /// + /// Refreshes a specific cached item by its GUID identifier. + /// + /// The GUID of the item to refresh. void Refresh(Guid id); } /// -/// Strongly type cache refresher that is able to refresh cache of real instances of objects as well as IDs +/// Defines a strongly typed cache refresher that can refresh cache using object instances. /// -/// +/// The type of entity being cached. /// -/// This is much better for performance when we're not running in a load balanced environment so we can refresh the -/// cache -/// against a already resolved object instead of looking the object back up by id. +/// This interface provides better performance in non-load-balanced environments by allowing +/// cache refresh operations on already-resolved object instances, avoiding the need to +/// re-lookup objects by their identifiers. /// public interface ICacheRefresher : ICacheRefresher { + /// + /// Refreshes the cache for the specified instance. + /// + /// The instance to refresh in the cache. void Refresh(T instance); + /// + /// Removes the specified instance from the cache. + /// + /// The instance to remove from the cache. void Remove(T instance); } diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/ApplicationCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/ApplicationCacheRefresher.cs index 11ddd8a18349..7b43a087b0c8 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/ApplicationCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/ApplicationCacheRefresher.cs @@ -3,31 +3,48 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for application section (tree) caches. +/// public sealed class ApplicationCacheRefresher : CacheRefresherBase { + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("B15F34A1-BC1D-4F8B-8369-3222728AB4C8"); + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The event aggregator. + /// The notification factory. public ApplicationCacheRefresher(AppCaches appCaches, IEventAggregator eventAggregator, ICacheRefresherNotificationFactory factory) : base(appCaches, eventAggregator, factory) { } + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "Application Cache Refresher"; + /// public override void RefreshAll() { AppCaches.RuntimeCache.Clear(CacheKeys.ApplicationsCacheKey); base.RefreshAll(); } + /// public override void Refresh(int id) { Remove(id); base.Refresh(id); } + /// public override void Remove(int id) { AppCaches.RuntimeCache.Clear(CacheKeys.ApplicationsCacheKey); diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/ContentTypeCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/ContentTypeCacheRefresher.cs index 831520c4a951..5f68a46df7e6 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/ContentTypeCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/ContentTypeCacheRefresher.cs @@ -11,6 +11,9 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for content type, media type, and member type caches. +/// public sealed class ContentTypeCacheRefresher : PayloadCacheRefresherBase { private readonly IContentTypeCommonRepository _contentTypeCommonRepository; @@ -21,6 +24,20 @@ public sealed class ContentTypeCacheRefresher : PayloadCacheRefresherBase + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The JSON serializer. + /// The ID-key mapping service. + /// The content type common repository. + /// The event aggregator. + /// The cache refresher notification factory. + /// The published model factory. + /// The published content type factory. + /// The document cache service. + /// The published content type cache. + /// The media cache service. public ContentTypeCacheRefresher( AppCaches appCaches, IJsonSerializer serializer, @@ -46,8 +63,17 @@ public ContentTypeCacheRefresher( #region Json + /// + /// Represents the JSON payload for content type cache refresh operations. + /// public class JsonPayload { + /// + /// Initializes a new instance of the class. + /// + /// The type name of the content type. + /// The identifier of the content type. + /// The types of changes that occurred. public JsonPayload(string itemType, int id, ContentTypeChangeTypes changeTypes) { ItemType = itemType; @@ -55,10 +81,19 @@ public JsonPayload(string itemType, int id, ContentTypeChangeTypes changeTypes) ChangeTypes = changeTypes; } + /// + /// Gets the type name of the content type (e.g., IContentType, IMediaType, IMemberType). + /// public string ItemType { get; } + /// + /// Gets the identifier of the content type. + /// public int Id { get; } + /// + /// Gets the types of changes that occurred. + /// public ContentTypeChangeTypes ChangeTypes { get; } } @@ -66,16 +101,22 @@ public JsonPayload(string itemType, int id, ContentTypeChangeTypes changeTypes) #region Define + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("6902E22C-9C10-483C-91F3-66B7CAE9E2F5"); + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "Content Type Cache Refresher"; #endregion #region Refresher + /// public override void RefreshInternal(JsonPayload[] payloads) { // TODO: refactor @@ -127,6 +168,7 @@ public override void RefreshInternal(JsonPayload[] payloads) base.RefreshInternal(payloads); } + /// public override void Refresh(JsonPayload[] payloads) { _publishedContentTypeCache.ClearContentTypes(payloads.Select(x => x.Id)); @@ -144,12 +186,16 @@ public override void Refresh(JsonPayload[] payloads) base.Refresh(payloads); } + /// public override void RefreshAll() => throw new NotSupportedException(); + /// public override void Refresh(int id) => throw new NotSupportedException(); + /// public override void Refresh(Guid id) => throw new NotSupportedException(); + /// public override void Remove(int id) => throw new NotSupportedException(); #endregion diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/DataTypeCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/DataTypeCacheRefresher.cs index 364536b85239..cf939ad88186 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/DataTypeCacheRefresher.cs @@ -12,6 +12,9 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for data type caches. +/// public sealed class DataTypeCacheRefresher : PayloadCacheRefresherBase { private readonly IIdKeyMap _idKeyMap; @@ -22,6 +25,20 @@ public sealed class DataTypeCacheRefresher : PayloadCacheRefresherBase + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The JSON serializer. + /// The ID-key mapping service. + /// The event aggregator. + /// The cache refresher notification factory. + /// The published model factory. + /// The published content type factory. + /// The published content type cache. + /// The document cache service. + /// The media cache service. + /// The content type common repository. public DataTypeCacheRefresher( AppCaches appCaches, IJsonSerializer serializer, @@ -45,6 +62,19 @@ public DataTypeCacheRefresher( _contentTypeCommonRepository = contentTypeCommonRepository; } + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The JSON serializer. + /// The ID-key mapping service. + /// The event aggregator. + /// The cache refresher notification factory. + /// The published model factory. + /// The published content type factory. + /// The published content type cache. + /// The document cache service. + /// The media cache service. [Obsolete("Use the non-obsolete constructor instead. Scheduled for removal in V18.")] public DataTypeCacheRefresher( AppCaches appCaches, @@ -74,8 +104,17 @@ public DataTypeCacheRefresher( #region Json + /// + /// Represents the JSON payload for data type cache refresh operations. + /// public class JsonPayload { + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the data type. + /// The unique key of the data type. + /// Whether the data type was removed. public JsonPayload(int id, Guid key, bool removed) { Id = id; @@ -83,10 +122,19 @@ public JsonPayload(int id, Guid key, bool removed) Removed = removed; } + /// + /// Gets the identifier of the data type. + /// public int Id { get; } + /// + /// Gets the unique key of the data type. + /// public Guid Key { get; } + /// + /// Gets a value indicating whether the data type was removed. + /// public bool Removed { get; } } @@ -94,16 +142,22 @@ public JsonPayload(int id, Guid key, bool removed) #region Define + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("35B16C25-A17E-45D7-BC8F-EDAB1DCC28D2"); + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "Data Type Cache Refresher"; #endregion #region Refresher + /// public override void RefreshInternal(JsonPayload[] payloads) { // we need to clear the ContentType runtime cache since that is what caches the @@ -134,6 +188,7 @@ public override void RefreshInternal(JsonPayload[] payloads) base.RefreshInternal(payloads); } + /// public override void Refresh(JsonPayload[] payloads) { List removedContentTypes = new(); @@ -162,12 +217,17 @@ public override void Refresh(JsonPayload[] payloads) // these events should never trigger // everything should be PAYLOAD/JSON + + /// public override void RefreshAll() => throw new NotSupportedException(); + /// public override void Refresh(int id) => throw new NotSupportedException(); + /// public override void Refresh(Guid id) => throw new NotSupportedException(); + /// public override void Remove(int id) => throw new NotSupportedException(); #endregion diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/DictionaryCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/DictionaryCacheRefresher.cs index c10640986caa..3d010b9541db 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/DictionaryCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/DictionaryCacheRefresher.cs @@ -4,25 +4,41 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for dictionary item caches. +/// public sealed class DictionaryCacheRefresher : CacheRefresherBase { + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("D1D7E227-F817-4816-BFE9-6C39B6152884"); + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The event aggregator. + /// The notification factory. public DictionaryCacheRefresher(AppCaches appCaches, IEventAggregator eventAggregator, ICacheRefresherNotificationFactory factory) : base(appCaches, eventAggregator, factory) { } + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "Dictionary Cache Refresher"; + /// public override void Refresh(int id) { ClearAllIsolatedCacheByEntityType(); base.Refresh(id); } + /// public override void Remove(int id) { ClearAllIsolatedCacheByEntityType(); diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/DomainCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/DomainCacheRefresher.cs index 55dd2444a364..970b31d2cfa5 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/DomainCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/DomainCacheRefresher.cs @@ -7,10 +7,21 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for domain caches. +/// public sealed class DomainCacheRefresher : PayloadCacheRefresherBase { private readonly IDomainCacheService _domainCacheService; + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The JSON serializer. + /// The event aggregator. + /// The cache refresher notification factory. + /// The domain cache service. public DomainCacheRefresher( AppCaches appCaches, IJsonSerializer serializer, @@ -24,16 +35,30 @@ public DomainCacheRefresher( #region Json + /// + /// Represents the JSON payload for domain cache refresh operations. + /// public class JsonPayload { + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the domain. + /// The type of change that occurred. public JsonPayload(int id, DomainChangeTypes changeType) { Id = id; ChangeType = changeType; } + /// + /// Gets the identifier of the domain. + /// public int Id { get; } + /// + /// Gets the type of change that occurred. + /// public DomainChangeTypes ChangeType { get; } } @@ -41,16 +66,22 @@ public JsonPayload(int id, DomainChangeTypes changeType) #region Define + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("11290A79-4B57-4C99-AD72-7748A3CF38AF"); + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "Domain Cache Refresher"; #endregion #region Refresher + /// public override void RefreshInternal(JsonPayload[] payloads) { ClearAllIsolatedCacheByEntityType(); @@ -67,12 +98,17 @@ public override void RefreshInternal(JsonPayload[] payloads) // these events should never trigger // everything should be PAYLOAD/JSON + + /// public override void RefreshAll() => throw new NotSupportedException(); + /// public override void Refresh(int id) => throw new NotSupportedException(); + /// public override void Refresh(Guid id) => throw new NotSupportedException(); + /// public override void Remove(int id) => throw new NotSupportedException(); #endregion diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/LanguageCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/LanguageCacheRefresher.cs index 335065774860..65023c39a144 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/LanguageCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/LanguageCacheRefresher.cs @@ -8,11 +8,22 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for language caches. +/// public sealed class LanguageCacheRefresher : PayloadCacheRefresherBase { private readonly IDomainCacheService _domainCacheService; + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The JSON serializer. + /// The event aggregator. + /// The domain cache service. + /// The cache refresher notification factory. public LanguageCacheRefresher( AppCaches appCaches, IJsonSerializer serializer, @@ -43,8 +54,14 @@ private void RefreshDomains() #region Json + /// + /// Represents the JSON payload for language cache refresh operations. + /// public class JsonPayload { + /// + /// Defines the types of changes that can occur to a language. + /// public enum LanguageChangeType { /// @@ -68,6 +85,12 @@ public enum LanguageChangeType ChangeCulture = 3, } + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the language. + /// The ISO code of the language. + /// The type of change that occurred. public JsonPayload(int id, string isoCode, LanguageChangeType changeType) { Id = id; @@ -75,10 +98,19 @@ public JsonPayload(int id, string isoCode, LanguageChangeType changeType) ChangeType = changeType; } + /// + /// Gets the identifier of the language. + /// public int Id { get; } + /// + /// Gets the ISO code of the language. + /// public string IsoCode { get; } + /// + /// Gets the type of change that occurred. + /// public LanguageChangeType ChangeType { get; } } @@ -86,16 +118,22 @@ public JsonPayload(int id, string isoCode, LanguageChangeType changeType) #region Define + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("3E0F95D8-0BE5-44B8-8394-2B8750B62654"); + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "Language Cache Refresher"; #endregion #region Refresher + /// public override void RefreshInternal(JsonPayload[] payloads) { // Languages has no concept of "published" languages, so all caches are "internal" @@ -142,12 +180,17 @@ public override void RefreshInternal(JsonPayload[] payloads) // these events should never trigger // everything should be PAYLOAD/JSON + + /// public override void RefreshAll() => throw new NotSupportedException(); + /// public override void Refresh(int id) => throw new NotSupportedException(); + /// public override void Refresh(Guid id) => throw new NotSupportedException(); + /// public override void Remove(int id) => throw new NotSupportedException(); #endregion diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/MediaCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/MediaCacheRefresher.cs index f54c78de1b7a..00f78a5aea0b 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/MediaCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/MediaCacheRefresher.cs @@ -13,6 +13,9 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for media caches. +/// public sealed class MediaCacheRefresher : PayloadCacheRefresherBase { private readonly IIdKeyMap _idKeyMap; @@ -22,6 +25,19 @@ public sealed class MediaCacheRefresher : PayloadCacheRefresherBase + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The JSON serializer. + /// The ID-key mapping service. + /// The event aggregator. + /// The cache refresher notification factory. + /// The media navigation query service. + /// The media navigation management service. + /// The media service. + /// The media cache service. + /// The cache manager. public MediaCacheRefresher( AppCaches appCaches, IJsonSerializer serializer, @@ -47,14 +63,27 @@ public MediaCacheRefresher( #region Indirect + /// + /// Refreshes media type caches by clearing all cached media. + /// + /// The application caches. public static void RefreshMediaTypes(AppCaches appCaches) => appCaches.IsolatedCaches.ClearCache(); #endregion #region Json + /// + /// Represents the JSON payload for media cache refresh operations. + /// public class JsonPayload { + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the media item. + /// The unique key of the media item. + /// The types of changes that occurred. public JsonPayload(int id, Guid? key, TreeChangeTypes changeTypes) { Id = id; @@ -62,10 +91,19 @@ public JsonPayload(int id, Guid? key, TreeChangeTypes changeTypes) ChangeTypes = changeTypes; } + /// + /// Gets the identifier of the media item. + /// public int Id { get; } + /// + /// Gets the unique key of the media item. + /// public Guid? Key { get; } + /// + /// Gets the types of changes that occurred. + /// public TreeChangeTypes ChangeTypes { get; } } @@ -73,16 +111,22 @@ public JsonPayload(int id, Guid? key, TreeChangeTypes changeTypes) #region Define + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("B29286DD-2D40-4DDB-B325-681226589FEC"); + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "Media Cache Refresher"; #endregion #region Refresher + /// public override void RefreshInternal(JsonPayload[] payloads) { // actions that always need to happen @@ -125,6 +169,7 @@ public override void RefreshInternal(JsonPayload[] payloads) base.RefreshInternal(payloads); } + /// public override void Refresh(JsonPayload[]? payloads) { if (payloads is null) @@ -284,12 +329,17 @@ private void HandleNavigationForSingleMedia(IMedia media) // these events should never trigger // everything should be JSON + + /// public override void RefreshAll() => throw new NotSupportedException(); + /// public override void Refresh(int id) => throw new NotSupportedException(); + /// public override void Refresh(Guid id) => throw new NotSupportedException(); + /// public override void Remove(int id) => throw new NotSupportedException(); #endregion diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/MemberCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/MemberCacheRefresher.cs index 2a7b449aaf12..a9baafe0953d 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/MemberCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/MemberCacheRefresher.cs @@ -10,13 +10,27 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for member caches. +/// public sealed class MemberCacheRefresher : PayloadCacheRefresherBase { + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("E285DF34-ACDC-4226-AE32-C0CB5CF388DA"); private readonly IIdKeyMap _idKeyMap; private readonly IMemberPartialViewCacheInvalidator _memberPartialViewCacheInvalidator; + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The JSON serializer. + /// The ID-key mapping service. + /// The event aggregator. + /// The cache refresher notification factory. [Obsolete("Use the non obsoleted contructor instead. Planned for removal in V18")] public MemberCacheRefresher(AppCaches appCaches, IJsonSerializer serializer, IIdKeyMap idKeyMap, IEventAggregator eventAggregator, ICacheRefresherNotificationFactory factory) : this( @@ -29,6 +43,15 @@ public MemberCacheRefresher(AppCaches appCaches, IJsonSerializer serializer, IId { } + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The JSON serializer. + /// The ID-key mapping service. + /// The event aggregator. + /// The cache refresher notification factory. + /// The member partial view cache invalidator. public MemberCacheRefresher( AppCaches appCaches, IJsonSerializer serializer, @@ -44,13 +67,25 @@ public MemberCacheRefresher( #region Indirect + /// + /// Refreshes member type caches by clearing all cached members. + /// + /// The application caches. public static void RefreshMemberTypes(AppCaches appCaches) => appCaches.IsolatedCaches.ClearCache(); #endregion + /// + /// Represents the JSON payload for member cache refresh operations. + /// public class JsonPayload { - // [JsonConstructor] + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the member. + /// The username of the member. + /// Whether the member was removed. public JsonPayload(int id, string? username, bool removed) { Id = id; @@ -58,31 +93,48 @@ public JsonPayload(int id, string? username, bool removed) Removed = removed; } + /// + /// Gets the identifier of the member. + /// public int Id { get; } + /// + /// Gets the username of the member. + /// public string? Username { get; } + /// + /// Gets or sets the previous username of the member, if changed. + /// public string? PreviousUsername { get; set; } + /// + /// Gets a value indicating whether the member was removed. + /// public bool Removed { get; } } + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "Member Cache Refresher"; + /// public override void RefreshInternal(JsonPayload[] payloads) { ClearCache(payloads); base.RefreshInternal(payloads); } + /// public override void Refresh(int id) { ClearCache(new JsonPayload(id, null, false)); base.Refresh(id); } + /// public override void Remove(int id) { ClearCache(new JsonPayload(id, null, false)); diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/MemberGroupCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/MemberGroupCacheRefresher.cs index 0d5eaf0010c9..bca0df960493 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/MemberGroupCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/MemberGroupCacheRefresher.cs @@ -5,8 +5,18 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for member group caches. +/// public sealed class MemberGroupCacheRefresher : PayloadCacheRefresherBase { + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The JSON serializer. + /// The event aggregator. + /// The notification factory. public MemberGroupCacheRefresher(AppCaches appCaches, IJsonSerializer jsonSerializer, IEventAggregator eventAggregator, ICacheRefresherNotificationFactory factory) : base(appCaches, jsonSerializer, eventAggregator, factory) { @@ -14,16 +24,30 @@ public MemberGroupCacheRefresher(AppCaches appCaches, IJsonSerializer jsonSerial #region Json + /// + /// Represents the JSON payload for member group cache refresh operations. + /// public class JsonPayload { + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the member group. + /// The name of the member group. public JsonPayload(int id, string name) { Id = id; Name = name; } + /// + /// Gets the name of the member group. + /// public string Name { get; } + /// + /// Gets the identifier of the member group. + /// public int Id { get; } } @@ -31,28 +55,36 @@ public JsonPayload(int id, string name) #region Define + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("187F236B-BD21-4C85-8A7C-29FBA3D6C00C"); + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "Member Group Cache Refresher"; #endregion #region Refresher + /// public override void RefreshInternal(JsonPayload[] payloads) { ClearCache(); base.RefreshInternal(payloads); } + /// public override void Refresh(int id) { ClearCache(); base.Refresh(id); } + /// public override void Remove(int id) { ClearCache(); diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/PublicAccessCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/PublicAccessCacheRefresher.cs index 9124d7350ec3..8dd82beb3df5 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/PublicAccessCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/PublicAccessCacheRefresher.cs @@ -4,43 +4,61 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for public access entry caches. +/// public sealed class PublicAccessCacheRefresher : CacheRefresherBase { #region Define + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("1DB08769-B104-4F8B-850E-169CAC1DF2EC"); + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The event aggregator. + /// The notification factory. public PublicAccessCacheRefresher(AppCaches appCaches, IEventAggregator eventAggregator, ICacheRefresherNotificationFactory factory) : base(appCaches, eventAggregator, factory) { } + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "Public Access Cache Refresher"; #endregion #region Refresher + /// public override void Refresh(Guid id) { ClearAllIsolatedCacheByEntityType(); base.Refresh(id); } + /// public override void Refresh(int id) { ClearAllIsolatedCacheByEntityType(); base.Refresh(id); } + /// public override void RefreshAll() { ClearAllIsolatedCacheByEntityType(); base.RefreshAll(); } + /// public override void Remove(int id) { ClearAllIsolatedCacheByEntityType(); diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/RelationTypeCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/RelationTypeCacheRefresher.cs index 8da3cd5be0a4..e0e197ecd619 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/RelationTypeCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/RelationTypeCacheRefresher.cs @@ -5,25 +5,41 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for relation type caches. +/// public sealed class RelationTypeCacheRefresher : CacheRefresherBase { + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The event aggregator. + /// The notification factory. public RelationTypeCacheRefresher(AppCaches appCaches, IEventAggregator eventAggregator, ICacheRefresherNotificationFactory factory) : base(appCaches, eventAggregator, factory) { } + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("D8375ABA-4FB3-4F86-B505-92FBA1B6F7C9"); + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "Relation Type Cache Refresher"; + /// public override void RefreshAll() { ClearAllIsolatedCacheByEntityType(); base.RefreshAll(); } + /// public override void Refresh(int id) { Attempt cache = AppCaches.IsolatedCaches.Get(); @@ -35,9 +51,10 @@ public override void Refresh(int id) base.Refresh(id); } + /// public override void Refresh(Guid id) => throw new NotSupportedException(); - // base.Refresh(id); + /// public override void Remove(int id) { Attempt cache = AppCaches.IsolatedCaches.Get(); diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/TemplateCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/TemplateCacheRefresher.cs index 221ad7c8363a..daa44b599fa9 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/TemplateCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/TemplateCacheRefresher.cs @@ -6,13 +6,27 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for template caches. +/// public sealed class TemplateCacheRefresher : CacheRefresherBase { + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("DD12B6A0-14B9-46e8-8800-C154F74047C8"); private readonly IContentTypeCommonRepository _contentTypeCommonRepository; private readonly IIdKeyMap _idKeyMap; + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The ID/key map service. + /// The content type common repository. + /// The event aggregator. + /// The notification factory. public TemplateCacheRefresher( AppCaches appCaches, IIdKeyMap idKeyMap, @@ -25,16 +39,20 @@ public TemplateCacheRefresher( _contentTypeCommonRepository = contentTypeCommonRepository; } + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "Template Cache Refresher"; + /// public override void Refresh(int id) { RemoveFromCache(id); base.Refresh(id); } + /// public override void Remove(int id) { RemoveFromCache(id); diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/UserCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/UserCacheRefresher.cs index 2a142df1f67d..ced590db514d 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/UserCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/UserCacheRefresher.cs @@ -6,32 +6,58 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for user caches. +/// public sealed class UserCacheRefresher : PayloadCacheRefresherBase { + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The JSON serializer. + /// The event aggregator. + /// The notification factory. public UserCacheRefresher(AppCaches appCaches, IJsonSerializer serializer, IEventAggregator eventAggregator, ICacheRefresherNotificationFactory factory) : base(appCaches, serializer, eventAggregator, factory) { } + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("E057AF6D-2EE6-41F4-8045-3694010F0AA6"); + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "User Cache Refresher"; + /// + /// Represents the JSON payload for user cache refresh operations. + /// public record JsonPayload { + /// + /// Gets the identifier of the user. + /// public int Id { get; init; } + /// + /// Gets the unique key of the user. + /// public Guid Key { get; init; } } + /// public override void RefreshAll() { ClearAllIsolatedCacheByEntityType(); base.RefreshAll(); } + /// public override void RefreshInternal(JsonPayload[] payloads) { ClearCache(payloads); diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/UserGroupCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/UserGroupCacheRefresher.cs index ccf004a8d7d0..d3734336ec5e 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/UserGroupCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/UserGroupCacheRefresher.cs @@ -15,21 +15,33 @@ public sealed class UserGroupCacheRefresher : CacheRefresherBase + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("45178038-B232-4FE8-AA1A-F2B949C44762"); + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The event aggregator. + /// The notification factory. public UserGroupCacheRefresher(AppCaches appCaches, IEventAggregator eventAggregator, ICacheRefresherNotificationFactory factory) : base(appCaches, eventAggregator, factory) { } + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "User Group Cache Refresher"; #endregion #region Refresher + /// public override void RefreshAll() { ClearAllIsolatedCacheByEntityType(); @@ -45,12 +57,14 @@ public override void RefreshAll() base.RefreshAll(); } + /// public override void Refresh(int id) { Remove(id); base.Refresh(id); } + /// public override void Remove(int id) { Attempt userGroupCache = AppCaches.IsolatedCaches.Get(); diff --git a/src/Umbraco.Core/Cache/Refreshers/Implement/ValueEditorCacheRefresher.cs b/src/Umbraco.Core/Cache/Refreshers/Implement/ValueEditorCacheRefresher.cs index 2aed28d48897..be417bb4139a 100644 --- a/src/Umbraco.Core/Cache/Refreshers/Implement/ValueEditorCacheRefresher.cs +++ b/src/Umbraco.Core/Cache/Refreshers/Implement/ValueEditorCacheRefresher.cs @@ -4,12 +4,26 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Cache refresher for value editor caches. +/// public sealed class ValueEditorCacheRefresher : PayloadCacheRefresherBase { + /// + /// The unique identifier for this cache refresher. + /// public static readonly Guid UniqueId = Guid.Parse("D28A1DBB-2308-4918-9A92-2F8689B6CBFE"); private readonly IValueEditorCache _valueEditorCache; + /// + /// Initializes a new instance of the class. + /// + /// The application caches. + /// The JSON serializer. + /// The event aggregator. + /// The notification factory. + /// The value editor cache. public ValueEditorCacheRefresher( AppCaches appCaches, IJsonSerializer serializer, @@ -19,10 +33,13 @@ public ValueEditorCacheRefresher( : base(appCaches, serializer, eventAggregator, factory) => _valueEditorCache = valueEditorCache; + /// public override Guid RefresherUniqueId => UniqueId; + /// public override string Name => "ValueEditorCacheRefresher"; + /// public override void RefreshInternal(DataTypeCacheRefresher.JsonPayload[] payloads) { IEnumerable ids = payloads.Select(x => x.Id); @@ -32,11 +49,16 @@ public override void RefreshInternal(DataTypeCacheRefresher.JsonPayload[] payloa // these events should never trigger // everything should be PAYLOAD/JSON + + /// public override void RefreshAll() => throw new NotSupportedException(); + /// public override void Refresh(int id) => throw new NotSupportedException(); + /// public override void Refresh(Guid id) => throw new NotSupportedException(); + /// public override void Remove(int id) => throw new NotSupportedException(); } diff --git a/src/Umbraco.Core/Cache/Refreshers/JsonCacheRefresherBase.cs b/src/Umbraco.Core/Cache/Refreshers/JsonCacheRefresherBase.cs index 52f0d7439c8a..b2d764b0ba26 100644 --- a/src/Umbraco.Core/Cache/Refreshers/JsonCacheRefresherBase.cs +++ b/src/Umbraco.Core/Cache/Refreshers/JsonCacheRefresherBase.cs @@ -24,6 +24,9 @@ protected JsonCacheRefresherBase( : base(appCaches, eventAggregator, factory) => JsonSerializer = jsonSerializer; + /// + /// Gets the JSON serializer. + /// protected IJsonSerializer JsonSerializer { get; } /// @@ -47,6 +50,11 @@ public virtual void RefreshInternal(string json) /// The deserialized object payload. public TJsonPayload[]? Deserialize(string json) => JsonSerializer.Deserialize(json); + /// + /// Serializes the specified payloads to a JSON string. + /// + /// The payloads to serialize. + /// The JSON string representation of the payloads. public string Serialize(params TJsonPayload[] jsonPayloads) => JsonSerializer.Serialize(jsonPayloads); #endregion diff --git a/src/Umbraco.Core/Cache/Refreshers/PayloadCacheRefresherBase.cs b/src/Umbraco.Core/Cache/Refreshers/PayloadCacheRefresherBase.cs index 8fc8e1e4711b..a09a9f48ae20 100644 --- a/src/Umbraco.Core/Cache/Refreshers/PayloadCacheRefresherBase.cs +++ b/src/Umbraco.Core/Cache/Refreshers/PayloadCacheRefresherBase.cs @@ -30,6 +30,7 @@ protected PayloadCacheRefresherBase(AppCaches appCaches, IJsonSerializer seriali #region Refresher + /// public override void Refresh(string json) { TPayload[]? payload = Deserialize(json); @@ -56,6 +57,10 @@ public override void RefreshInternal(string json) public virtual void Refresh(TPayload[] payloads) => OnCacheUpdated(NotificationFactory.Create(payloads, MessageType.RefreshByPayload)); + /// + /// Performs internal cache refresh operations for the specified payloads. + /// + /// The payloads to process. public virtual void RefreshInternal(TPayload[] payloads) { } diff --git a/src/Umbraco.Core/Cache/RepositoryCacheVersionService.cs b/src/Umbraco.Core/Cache/RepositoryCacheVersionService.cs index 09269f92e15f..6f400259cb37 100644 --- a/src/Umbraco.Core/Cache/RepositoryCacheVersionService.cs +++ b/src/Umbraco.Core/Cache/RepositoryCacheVersionService.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence.Repositories; @@ -15,6 +15,13 @@ internal class RepositoryCacheVersionService : IRepositoryCacheVersionService private readonly IRepositoryCacheVersionAccessor _repositoryCacheVersionAccessor; private readonly ConcurrentDictionary _cacheVersions = new(); + /// + /// Initializes a new instance of the class. + /// + /// The scope provider. + /// The repository cache version repository. + /// The logger. + /// The repository cache version accessor. public RepositoryCacheVersionService( ICoreScopeProvider scopeProvider, IRepositoryCacheVersionRepository repositoryCacheVersionRepository, @@ -116,6 +123,11 @@ public async Task SetCachesSyncedAsync() scope.Complete(); } + /// + /// Gets the cache key for the specified entity type. + /// + /// The entity type. + /// The cache key for the entity type. internal string GetCacheKey() where TEntity : class => typeof(TEntity).FullName ?? typeof(TEntity).Name; diff --git a/src/Umbraco.Core/Cache/SafeLazy.cs b/src/Umbraco.Core/Cache/SafeLazy.cs index 40512ece67ac..f75864227579 100644 --- a/src/Umbraco.Core/Cache/SafeLazy.cs +++ b/src/Umbraco.Core/Cache/SafeLazy.cs @@ -2,11 +2,25 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Provides methods for creating and working with lazy values that safely handle exceptions. +/// +/// +/// Safe lazy values capture exceptions during evaluation and return them as null values +/// instead of re-throwing, preventing cache corruption from failed evaluations. +/// public static class SafeLazy { - // an object that represent a value that has not been created yet + /// + /// An object that represents a value that has not been created yet. + /// internal static readonly object ValueNotCreated = new(); + /// + /// Creates a safe lazy that catches exceptions during evaluation. + /// + /// The factory function to create the cached item. + /// A lazy value that wraps exceptions in an instead of throwing. public static Lazy GetSafeLazy(Func getCacheItem) => // try to generate the value and if it fails, @@ -25,6 +39,12 @@ public static class SafeLazy } }); + /// + /// Gets the value from a safe lazy, returning null for exceptions. + /// + /// The lazy value to evaluate. + /// If true, only returns the value if already created; otherwise returns . + /// The lazy value, if not yet created and is true, or null if an exception occurred. public static object? GetSafeLazyValue(Lazy? lazy, bool onlyIfValueIsCreated = false) { // if onlyIfValueIsCreated, do not trigger value creation @@ -55,10 +75,24 @@ public static class SafeLazy } } + /// + /// Holds an exception that occurred during lazy value evaluation. + /// + /// + /// Used to store exceptions in the cache without re-throwing them during normal access, + /// allowing the exception to be thrown once when the value is actually requested. + /// public class ExceptionHolder { + /// + /// Initializes a new instance of the class. + /// + /// The captured exception dispatch info. public ExceptionHolder(ExceptionDispatchInfo e) => Exception = e; + /// + /// Gets the captured exception dispatch info. + /// public ExceptionDispatchInfo Exception { get; } } } diff --git a/src/Umbraco.Core/Cache/ValueEditorCache.cs b/src/Umbraco.Core/Cache/ValueEditorCache.cs index e1ec12e5ef08..bcb6cf43eec7 100644 --- a/src/Umbraco.Core/Cache/ValueEditorCache.cs +++ b/src/Umbraco.Core/Cache/ValueEditorCache.cs @@ -3,17 +3,28 @@ namespace Umbraco.Cms.Core.Cache; +/// +/// Implements to cache instances. +/// +/// +/// This cache stores value editors keyed by data editor alias and data type ID to avoid +/// repeatedly creating value editor instances during request processing. +/// public class ValueEditorCache : IValueEditorCache { private readonly Lock _dictionaryLocker; private readonly Dictionary> _valueEditorCache; + /// + /// Initializes a new instance of the class. + /// public ValueEditorCache() { _valueEditorCache = new Dictionary>(); _dictionaryLocker = new Lock(); } + /// public IDataValueEditor GetValueEditor(IDataEditor editor, IDataType dataType) { // Lock just in case multiple threads uses the cache at the same time. @@ -41,6 +52,7 @@ public IDataValueEditor GetValueEditor(IDataEditor editor, IDataType dataType) } } + /// public void ClearCache(IEnumerable dataTypeIds) { lock (_dictionaryLocker) diff --git a/src/Umbraco.Core/CacheSyncService.cs b/src/Umbraco.Core/CacheSyncService.cs index c093b6f17921..98dd7e3b7730 100644 --- a/src/Umbraco.Core/CacheSyncService.cs +++ b/src/Umbraco.Core/CacheSyncService.cs @@ -4,12 +4,21 @@ namespace Umbraco.Cms.Core; +/// +/// Default implementation of that synchronizes caches across servers. +/// public class CacheSyncService : ICacheSyncService { private readonly IMachineInfoFactory _machineInfoFactory; private readonly CacheRefresherCollection _cacheRefreshers; private readonly ICacheInstructionService _cacheInstructionService; + /// + /// Initializes a new instance of the class. + /// + /// The factory for getting machine information. + /// The collection of cache refreshers. + /// The service for processing cache instructions. public CacheSyncService( IMachineInfoFactory machineInfoFactory, CacheRefresherCollection cacheRefreshers, diff --git a/src/Umbraco.Core/CodeAnnotations/UmbracoObjectTypeAttribute.cs b/src/Umbraco.Core/CodeAnnotations/UmbracoObjectTypeAttribute.cs index 13ec38f892c7..a268fe17fb29 100644 --- a/src/Umbraco.Core/CodeAnnotations/UmbracoObjectTypeAttribute.cs +++ b/src/Umbraco.Core/CodeAnnotations/UmbracoObjectTypeAttribute.cs @@ -1,20 +1,35 @@ namespace Umbraco.Cms.Core.CodeAnnotations; /// -/// Attribute to associate a GUID string and Type with an UmbracoObjectType Enum value +/// Attribute to associate a GUID string and Type with an UmbracoObjectType enum value. /// [AttributeUsage(AttributeTargets.Field)] public class UmbracoObjectTypeAttribute : Attribute { + /// + /// Initializes a new instance of the class with a GUID string. + /// + /// The GUID string representing the object type identifier. public UmbracoObjectTypeAttribute(string objectId) => ObjectId = new Guid(objectId); + /// + /// Initializes a new instance of the class with a GUID string and model type. + /// + /// The GUID string representing the object type identifier. + /// The CLR type associated with this object type. public UmbracoObjectTypeAttribute(string objectId, Type modelType) { ObjectId = new Guid(objectId); ModelType = modelType; } + /// + /// Gets the unique identifier for the Umbraco object type. + /// public Guid ObjectId { get; } + /// + /// Gets the CLR type associated with this object type, if specified. + /// public Type? ModelType { get; } } diff --git a/src/Umbraco.Core/CodeAnnotations/UmbracoUdiTypeAttribute.cs b/src/Umbraco.Core/CodeAnnotations/UmbracoUdiTypeAttribute.cs index 90df3185c677..5d88815db911 100644 --- a/src/Umbraco.Core/CodeAnnotations/UmbracoUdiTypeAttribute.cs +++ b/src/Umbraco.Core/CodeAnnotations/UmbracoUdiTypeAttribute.cs @@ -1,9 +1,22 @@ namespace Umbraco.Cms.Core.CodeAnnotations; +/// +/// Attribute to associate a UDI (Umbraco Document Identifier) type string with an enum value. +/// +/// +/// UDI types are string identifiers used in the Umbraco unified identifier system. +/// [AttributeUsage(AttributeTargets.Field)] public class UmbracoUdiTypeAttribute : Attribute { + /// + /// Initializes a new instance of the class. + /// + /// The UDI type string. public UmbracoUdiTypeAttribute(string udiType) => UdiType = udiType; + /// + /// Gets the UDI type string. + /// public string UdiType { get; } } diff --git a/src/Umbraco.Core/Collections/CompositeIntStringKey.cs b/src/Umbraco.Core/Collections/CompositeIntStringKey.cs index abbde4f3f05b..f4c06ddb17fd 100644 --- a/src/Umbraco.Core/Collections/CompositeIntStringKey.cs +++ b/src/Umbraco.Core/Collections/CompositeIntStringKey.cs @@ -27,18 +27,33 @@ public CompositeIntStringKey(int? key1, string? key2) _key2 = key2?.ToLowerInvariant() ?? "NULL"; } + /// + /// Determines whether two instances are equal. + /// + /// The first key to compare. + /// The second key to compare. + /// true if the two keys are equal; otherwise, false. public static bool operator ==(CompositeIntStringKey key1, CompositeIntStringKey key2) => key1._key2 == key2._key2 && key1._key1 == key2._key1; + /// + /// Determines whether two instances are not equal. + /// + /// The first key to compare. + /// The second key to compare. + /// true if the two keys are not equal; otherwise, false. public static bool operator !=(CompositeIntStringKey key1, CompositeIntStringKey key2) => key1._key2 != key2._key2 || key1._key1 != key2._key1; + /// public bool Equals(CompositeIntStringKey other) => _key2 == other._key2 && _key1 == other._key1; + /// public override bool Equals(object? obj) => obj is CompositeIntStringKey other && _key2 == other._key2 && _key1 == other._key1; + /// public override int GetHashCode() => (_key2.GetHashCode() * 31) + _key1; } diff --git a/src/Umbraco.Core/Collections/CompositeNStringNStringKey.cs b/src/Umbraco.Core/Collections/CompositeNStringNStringKey.cs index 0b3ec1aa929b..5bf443789b6c 100644 --- a/src/Umbraco.Core/Collections/CompositeNStringNStringKey.cs +++ b/src/Umbraco.Core/Collections/CompositeNStringNStringKey.cs @@ -21,18 +21,33 @@ public CompositeNStringNStringKey(string? key1, string? key2) _key2 = key2?.ToLowerInvariant() ?? "NULL"; } + /// + /// Determines whether two instances are equal. + /// + /// The first key to compare. + /// The second key to compare. + /// true if the two keys are equal; otherwise, false. public static bool operator ==(CompositeNStringNStringKey key1, CompositeNStringNStringKey key2) => key1._key2 == key2._key2 && key1._key1 == key2._key1; + /// + /// Determines whether two instances are not equal. + /// + /// The first key to compare. + /// The second key to compare. + /// true if the two keys are not equal; otherwise, false. public static bool operator !=(CompositeNStringNStringKey key1, CompositeNStringNStringKey key2) => key1._key2 != key2._key2 || key1._key1 != key2._key1; + /// public bool Equals(CompositeNStringNStringKey other) => _key2 == other._key2 && _key1 == other._key1; + /// public override bool Equals(object? obj) => obj is CompositeNStringNStringKey other && _key2 == other._key2 && _key1 == other._key1; + /// public override int GetHashCode() => (_key2.GetHashCode() * 31) + _key1.GetHashCode(); } diff --git a/src/Umbraco.Core/Collections/CompositeStringStringKey.cs b/src/Umbraco.Core/Collections/CompositeStringStringKey.cs index 6fd25f6c1212..5efdfa7335a6 100644 --- a/src/Umbraco.Core/Collections/CompositeStringStringKey.cs +++ b/src/Umbraco.Core/Collections/CompositeStringStringKey.cs @@ -21,18 +21,33 @@ public CompositeStringStringKey(string? key1, string? key2) _key2 = key2?.ToLowerInvariant() ?? throw new ArgumentNullException(nameof(key2)); } + /// + /// Determines whether two instances are equal. + /// + /// The first key to compare. + /// The second key to compare. + /// true if the two keys are equal; otherwise, false. public static bool operator ==(CompositeStringStringKey key1, CompositeStringStringKey key2) => key1._key2 == key2._key2 && key1._key1 == key2._key1; + /// + /// Determines whether two instances are not equal. + /// + /// The first key to compare. + /// The second key to compare. + /// true if the two keys are not equal; otherwise, false. public static bool operator !=(CompositeStringStringKey key1, CompositeStringStringKey key2) => key1._key2 != key2._key2 || key1._key1 != key2._key1; + /// public bool Equals(CompositeStringStringKey other) => _key2 == other._key2 && _key1 == other._key1; + /// public override bool Equals(object? obj) => obj is CompositeStringStringKey other && _key2 == other._key2 && _key1 == other._key1; + /// public override int GetHashCode() => (_key2.GetHashCode() * 31) + _key1.GetHashCode(); } diff --git a/src/Umbraco.Core/Collections/CompositeTypeTypeKey.cs b/src/Umbraco.Core/Collections/CompositeTypeTypeKey.cs index ea9a5a496f42..7cf1a497b2ce 100644 --- a/src/Umbraco.Core/Collections/CompositeTypeTypeKey.cs +++ b/src/Umbraco.Core/Collections/CompositeTypeTypeKey.cs @@ -25,9 +25,21 @@ public CompositeTypeTypeKey(Type type1, Type type2) /// public Type Type2 { get; } + /// + /// Determines whether two instances are equal. + /// + /// The first key to compare. + /// The second key to compare. + /// true if the two keys are equal; otherwise, false. public static bool operator ==(CompositeTypeTypeKey key1, CompositeTypeTypeKey key2) => key1.Type1 == key2.Type1 && key1.Type2 == key2.Type2; + /// + /// Determines whether two instances are not equal. + /// + /// The first key to compare. + /// The second key to compare. + /// true if the two keys are not equal; otherwise, false. public static bool operator !=(CompositeTypeTypeKey key1, CompositeTypeTypeKey key2) => key1.Type1 != key2.Type1 || key1.Type2 != key2.Type2; diff --git a/src/Umbraco.Core/Collections/ConcurrentHashSet.cs b/src/Umbraco.Core/Collections/ConcurrentHashSet.cs index ee4f5b707e22..cbb024dcc2f9 100644 --- a/src/Umbraco.Core/Collections/ConcurrentHashSet.cs +++ b/src/Umbraco.Core/Collections/ConcurrentHashSet.cs @@ -14,6 +14,13 @@ public class ConcurrentHashSet : ICollection, ISet private readonly HashSet _innerSet = new(); private readonly ReaderWriterLockSlim _instanceLocker = new(LockRecursionPolicy.NoRecursion); + /// + /// Initializes a new instance of the class. + /// + public ConcurrentHashSet() + { + } + /// /// Gets the number of elements contained in the . /// @@ -256,6 +263,10 @@ public void CopyTo(Array array, int index) Array.Copy(clone.ToArray(), 0, array, index, clone.Count); } + /// + /// Creates a thread-safe clone of the internal hash set. + /// + /// A new containing a copy of the elements. private HashSet GetThreadSafeClone() { HashSet? clone = null; @@ -275,6 +286,7 @@ private HashSet GetThreadSafeClone() return clone; } + /// public void ExceptWith(IEnumerable other) { try @@ -291,6 +303,7 @@ public void ExceptWith(IEnumerable other) } } + /// public void IntersectWith(IEnumerable other) { try @@ -307,6 +320,7 @@ public void IntersectWith(IEnumerable other) } } + /// public bool IsProperSubsetOf(IEnumerable other) { try @@ -323,6 +337,7 @@ public bool IsProperSubsetOf(IEnumerable other) } } + /// public bool IsProperSupersetOf(IEnumerable other) { try @@ -339,6 +354,7 @@ public bool IsProperSupersetOf(IEnumerable other) } } + /// public bool IsSubsetOf(IEnumerable other) { try @@ -355,6 +371,7 @@ public bool IsSubsetOf(IEnumerable other) } } + /// public bool IsSupersetOf(IEnumerable other) { try @@ -371,6 +388,7 @@ public bool IsSupersetOf(IEnumerable other) } } + /// public bool Overlaps(IEnumerable other) { try @@ -387,6 +405,7 @@ public bool Overlaps(IEnumerable other) } } + /// public bool SetEquals(IEnumerable other) { try @@ -403,6 +422,7 @@ public bool SetEquals(IEnumerable other) } } + /// public void SymmetricExceptWith(IEnumerable other) { try @@ -419,6 +439,7 @@ public void SymmetricExceptWith(IEnumerable other) } } + /// public void UnionWith(IEnumerable other) { try @@ -435,6 +456,7 @@ public void UnionWith(IEnumerable other) } } + /// bool ISet.Add(T item) { try diff --git a/src/Umbraco.Core/Collections/DeepCloneableList.cs b/src/Umbraco.Core/Collections/DeepCloneableList.cs index 4f22ac094e0d..67512e3c1d70 100644 --- a/src/Umbraco.Core/Collections/DeepCloneableList.cs +++ b/src/Umbraco.Core/Collections/DeepCloneableList.cs @@ -12,21 +12,33 @@ public class DeepCloneableList : List, IDeepCloneable, IRememberBeingDirty { private readonly ListCloneBehavior _listCloneBehavior; + /// + /// Initializes a new instance of the class with the specified clone behavior. + /// + /// The clone behavior for the list. public DeepCloneableList(ListCloneBehavior listCloneBehavior) => _listCloneBehavior = listCloneBehavior; + /// + /// Initializes a new instance of the class with a collection and the specified clone behavior. + /// + /// The collection whose elements are copied to the new list. + /// The clone behavior for the list. public DeepCloneableList(IEnumerable collection, ListCloneBehavior listCloneBehavior) : base(collection) => _listCloneBehavior = listCloneBehavior; /// - /// Default behavior is CloneOnce + /// Initializes a new instance of the class with a collection. /// - /// + /// The collection whose elements are copied to the new list. + /// Default behavior is . public DeepCloneableList(IEnumerable collection) : this(collection, ListCloneBehavior.CloneOnce) { } + /// + /// This event is not used by the list but is required by the interface. public event PropertyChangedEventHandler? PropertyChanged; // noop /// @@ -60,8 +72,10 @@ public object DeepClone() #region IRememberBeingDirty + /// public bool IsDirty() => this.OfType().Any(x => x.IsDirty()); + /// public bool WasDirty() => this.OfType().Any(x => x.WasDirty()); /// @@ -76,6 +90,7 @@ public object DeepClone() /// Always return an empty enumerable, the list has no properties that can be dirty. public IEnumerable GetDirtyProperties() => Enumerable.Empty(); + /// public void ResetDirtyProperties() { foreach (IRememberBeingDirty dc in this.OfType()) @@ -84,16 +99,19 @@ public void ResetDirtyProperties() } } + /// public void DisableChangeTracking() { // noop } + /// public void EnableChangeTracking() { // noop } + /// public void ResetWereDirtyProperties() { foreach (IRememberBeingDirty dc in this.OfType()) @@ -102,6 +120,7 @@ public void ResetWereDirtyProperties() } } + /// public void ResetDirtyProperties(bool rememberDirty) { foreach (IRememberBeingDirty dc in this.OfType()) diff --git a/src/Umbraco.Core/Collections/EventClearingObservableCollection.cs b/src/Umbraco.Core/Collections/EventClearingObservableCollection.cs index 3b0994c6147d..4d60f7c76c6e 100644 --- a/src/Umbraco.Core/Collections/EventClearingObservableCollection.cs +++ b/src/Umbraco.Core/Collections/EventClearingObservableCollection.cs @@ -16,20 +16,34 @@ public class EventClearingObservableCollection : ObservableCollection + /// Initializes a new instance of the class. + /// public EventClearingObservableCollection() { } + /// + /// Initializes a new instance of the class + /// that contains elements copied from the specified list. + /// + /// The list from which the elements are copied. public EventClearingObservableCollection(List list) : base(list) { } + /// + /// Initializes a new instance of the class + /// that contains elements copied from the specified collection. + /// + /// The collection from which the elements are copied. public EventClearingObservableCollection(IEnumerable collection) : base(collection) { } + /// event NotifyCollectionChangedEventHandler? INotifyCollectionChanged.CollectionChanged { add => _changed += value; @@ -41,6 +55,7 @@ event NotifyCollectionChangedEventHandler? INotifyCollectionChanged.CollectionCh /// public void ClearCollectionChangedEvents() => _changed = null; + /// public object DeepClone() { var clone = new EventClearingObservableCollection(); diff --git a/src/Umbraco.Core/Collections/ListCloneBehavior.cs b/src/Umbraco.Core/Collections/ListCloneBehavior.cs index 4fc9edf3ae03..7ce6d107186c 100644 --- a/src/Umbraco.Core/Collections/ListCloneBehavior.cs +++ b/src/Umbraco.Core/Collections/ListCloneBehavior.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Collections; +/// +/// Specifies the behavior when deep cloning a . +/// public enum ListCloneBehavior { /// diff --git a/src/Umbraco.Core/Collections/ObservableDictionary.cs b/src/Umbraco.Core/Collections/ObservableDictionary.cs index 216b384e5f13..a08b21a30fd8 100644 --- a/src/Umbraco.Core/Collections/ObservableDictionary.cs +++ b/src/Umbraco.Core/Collections/ObservableDictionary.cs @@ -33,10 +33,21 @@ public ObservableDictionary(Func keySelector, IEqualityComparer(equalityComparer); } + /// + /// Gets the dictionary mapping keys to their indices in the collection. + /// protected Dictionary Indecies { get; } + /// + /// Gets the function used to extract a key from a value. + /// protected Func KeySelector { get; } + /// + /// Removes the element with the specified key from the dictionary. + /// + /// The key of the element to remove. + /// true if the element is successfully found and removed; otherwise, false. public bool Remove(TKey key) { if (!Indecies.TryGetValue(key, out int index)) @@ -48,12 +59,14 @@ public bool Remove(TKey key) return true; } + /// event NotifyCollectionChangedEventHandler? INotifyCollectionChanged.CollectionChanged { add => _changed += value; remove => _changed -= value; } + /// public bool ContainsKey(TKey key) => Indecies.ContainsKey(key); /// @@ -112,6 +125,11 @@ public bool Replace(TKey key, TValue value) return true; } + /// + /// Replaces all elements in the dictionary with the specified values. + /// + /// The values to replace the current elements with. + /// Thrown when is null. public void ReplaceAll(IEnumerable values) { if (values == null) @@ -150,6 +168,7 @@ public void ChangeKey(TKey currentKey, TKey newKey) #region Protected Methods + /// protected override void InsertItem(int index, TValue item) { TKey key = KeySelector(item); @@ -170,12 +189,14 @@ protected override void InsertItem(int index, TValue item) Indecies[key] = index; } + /// protected override void ClearItems() { base.ClearItems(); Indecies.Clear(); } + /// protected override void RemoveItem(int index) { TValue item = this[index]; @@ -195,6 +216,7 @@ protected override void RemoveItem(int index) #region IDictionary and IReadOnlyDictionary implementation + /// public bool TryGetValue(TKey key, out TValue val) { if (Indecies.TryGetValue(key, out var index)) @@ -217,13 +239,16 @@ public bool TryGetValue(TKey key, out TValue val) /// public IEnumerable Values => Items; + /// ICollection IDictionary.Keys => Indecies.Keys; - // this will never be used + /// ICollection IDictionary.Values => Values.ToList(); + /// bool ICollection>.IsReadOnly => false; + /// IEnumerator> IEnumerable>.GetEnumerator() { foreach (TValue i in Values) @@ -233,15 +258,20 @@ IEnumerator> IEnumerable>. } } + /// void IDictionary.Add(TKey key, TValue value) => Add(value); + /// void ICollection>.Add(KeyValuePair item) => Add(item.Value); + /// bool ICollection>.Contains(KeyValuePair item) => ContainsKey(item.Key); + /// void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) => throw new NotImplementedException(); + /// bool ICollection>.Remove(KeyValuePair item) => Remove(item.Key); #endregion diff --git a/src/Umbraco.Core/Collections/OrderedHashSet.cs b/src/Umbraco.Core/Collections/OrderedHashSet.cs index d23c81a7b27d..71373d432314 100644 --- a/src/Umbraco.Core/Collections/OrderedHashSet.cs +++ b/src/Umbraco.Core/Collections/OrderedHashSet.cs @@ -13,8 +13,16 @@ public class OrderedHashSet : KeyedCollection { private readonly bool _keepOldest; + /// + /// Initializes a new instance of the class. + /// + /// + /// When true, the oldest item is kept when a duplicate is added; + /// when false, the newest item replaces the oldest. + /// public OrderedHashSet(bool keepOldest = true) => _keepOldest = keepOldest; + /// protected override void InsertItem(int index, T item) { if (Dictionary == null) @@ -42,5 +50,6 @@ protected override void InsertItem(int index, T item) } } + /// protected override T GetKeyForItem(T item) => item; } diff --git a/src/Umbraco.Core/Collections/StackQueue.cs b/src/Umbraco.Core/Collections/StackQueue.cs index 2324eec892ec..2d1982233b2e 100644 --- a/src/Umbraco.Core/Collections/StackQueue.cs +++ b/src/Umbraco.Core/Collections/StackQueue.cs @@ -8,14 +8,32 @@ public class StackQueue { private readonly LinkedList _linkedList = new(); + /// + /// Gets the number of elements contained in the collection. + /// public int Count => _linkedList.Count; + /// + /// Removes all elements from the collection. + /// public void Clear() => _linkedList.Clear(); + /// + /// Pushes an object onto the stack (adds to the front). + /// + /// The object to push onto the stack. public void Push(T? obj) => _linkedList.AddFirst(obj); + /// + /// Adds an object to the queue (adds to the front). + /// + /// The object to add to the queue. public void Enqueue(T? obj) => _linkedList.AddFirst(obj); + /// + /// Removes and returns the object at the top of the stack (from the front). + /// + /// The object removed from the top of the stack. public T Pop() { var obj = default(T); @@ -28,6 +46,10 @@ public T Pop() return obj!; } + /// + /// Removes and returns the object at the beginning of the queue (from the back). + /// + /// The object removed from the beginning of the queue. public T Dequeue() { var obj = default(T); @@ -40,7 +62,15 @@ public T Dequeue() return obj!; } + /// + /// Returns the object at the top of the stack without removing it. + /// + /// The object at the top of the stack, or the default value if the collection is empty. public T? PeekStack() => _linkedList.First is not null ? _linkedList.First.Value : default; + /// + /// Returns the object at the beginning of the queue without removing it. + /// + /// The object at the beginning of the queue, or the default value if the collection is empty. public T? PeekQueue() => _linkedList.Last is not null ? _linkedList.Last.Value : default; } diff --git a/src/Umbraco.Core/Collections/TopoGraph.cs b/src/Umbraco.Core/Collections/TopoGraph.cs index fd2161c6d3a4..be68fff0a1c9 100644 --- a/src/Umbraco.Core/Collections/TopoGraph.cs +++ b/src/Umbraco.Core/Collections/TopoGraph.cs @@ -1,15 +1,45 @@ namespace Umbraco.Cms.Core.Collections; +/// +/// Provides static methods and nested types for creating topologically sortable graph nodes. +/// public class TopoGraph { + /// + /// Error message used when a cyclic dependency is detected. + /// internal const string CycleDependencyError = "Cyclic dependency."; + + /// + /// Error message used when a required dependency is missing. + /// internal const string MissingDependencyError = "Missing dependency."; + /// + /// Creates a new graph node with the specified key, item, and dependencies. + /// + /// The type of the key. + /// The type of the item. + /// The key that uniquely identifies the node. + /// The item stored in the node. + /// The keys of nodes that this node depends on. + /// A new instance. public static Node CreateNode(TKey key, TItem item, IEnumerable dependencies) => new(key, item, dependencies); + /// + /// Represents a node in a topological graph with a key, item, and dependencies. + /// + /// The type of the key. + /// The type of the item. public class Node { + /// + /// Initializes a new instance of the class. + /// + /// The key that uniquely identifies the node. + /// The item stored in the node. + /// The keys of nodes that this node depends on. public Node(TKey key, TItem item, IEnumerable dependencies) { Key = key; @@ -17,10 +47,19 @@ public Node(TKey key, TItem item, IEnumerable dependencies) Dependencies = dependencies; } + /// + /// Gets the key that uniquely identifies this node. + /// public TKey Key { get; } + /// + /// Gets the item stored in this node. + /// public TItem Item { get; } + /// + /// Gets the keys of nodes that this node depends on. + /// public IEnumerable Dependencies { get; } } } @@ -92,9 +131,27 @@ public IEnumerable GetSortedItems(bool throwOnCycle = true, bool throwOnM return sorted; } + /// + /// Determines whether the specified item exists in the array within the given range. + /// + /// The array to search. + /// The item to locate. + /// The starting index of the search range. + /// The number of elements to search. + /// true if the item is found; otherwise, false. private static bool Contains(TItem[] items, TItem item, int start, int count) => Array.IndexOf(items, item, start, count) >= 0; + /// + /// Recursively visits a node and its dependencies to perform topological sorting. + /// + /// The item to visit. + /// The set of already visited items. + /// The array to store sorted items. + /// The current index in the sorted array. + /// The increment direction (+1 for forward, -1 for reverse). + /// Whether to throw an exception on cyclic dependencies. + /// Whether to throw an exception on missing dependencies. private void Visit(TItem item, ISet visited, TItem[] sorted, ref int index, int incr, bool throwOnCycle, bool throwOnMissing) { if (visited.Contains(item)) @@ -127,6 +184,12 @@ private void Visit(TItem item, ISet visited, TItem[] sorted, ref int inde index += incr; } + /// + /// Finds and returns the items corresponding to the specified dependency keys. + /// + /// The keys of the dependencies to find. + /// Whether to throw an exception if a dependency is not found. + /// An enumerable of items corresponding to the keys. private IEnumerable FindDependencies(IEnumerable keys, bool throwOnMissing) { foreach (TKey key in keys) diff --git a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs index 0a3baa1d3da8..b127b2f9a6b1 100644 --- a/src/Umbraco.Core/Composing/CollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/CollectionBuilderBase.cs @@ -128,6 +128,13 @@ protected virtual IEnumerable CreateItems(IServiceProvider factory) protected virtual TItem CreateItem(IServiceProvider factory, Type itemType) => (TItem)factory.GetRequiredService(itemType); + /// + /// Ensures that the specified type is valid for the collection. + /// + /// The type to validate. + /// The action being performed (used in error messages). + /// The validated type. + /// Thrown when the type does not inherit from or implement . protected Type EnsureType(Type type, string action) { if (typeof(TItem).IsAssignableFrom(type) == false) diff --git a/src/Umbraco.Core/Composing/ComponentCollection.cs b/src/Umbraco.Core/Composing/ComponentCollection.cs index 3d1b2c5c2661..8b89af8d8402 100644 --- a/src/Umbraco.Core/Composing/ComponentCollection.cs +++ b/src/Umbraco.Core/Composing/ComponentCollection.cs @@ -14,6 +14,12 @@ public class ComponentCollection : BuilderCollectionBase private readonly IProfilingLogger _profilingLogger; private readonly ILogger _logger; + /// + /// Initializes a new instance of the class. + /// + /// A factory function that provides the component items. + /// The profiling logger for timing component operations. + /// The logger for recording component lifecycle events. public ComponentCollection(Func> items, IProfilingLogger profilingLogger, ILogger logger) : base(items) { @@ -21,6 +27,12 @@ public ComponentCollection(Func> items, IProfilingL _logger = logger; } + /// + /// Initializes all components in the collection. + /// + /// If set to true indicates Umbraco is restarting. + /// The cancellation token. Cancellation indicates that the start process has been aborted. + /// A representing the asynchronous operation. public async Task InitializeAsync(bool isRestarting, CancellationToken cancellationToken) { using (_profilingLogger.IsEnabled(Logging.LogLevel.Debug) is false @@ -41,6 +53,12 @@ public async Task InitializeAsync(bool isRestarting, CancellationToken cancellat } } + /// + /// Terminates all components in the collection in reverse order. + /// + /// If set to true indicates Umbraco is restarting. + /// The cancellation token. Cancellation indicates that the shutdown process should no longer be graceful. + /// A representing the asynchronous operation. public async Task TerminateAsync(bool isRestarting, CancellationToken cancellationToken) { using (!_profilingLogger.IsEnabled(Logging.LogLevel.Debug) diff --git a/src/Umbraco.Core/Composing/ComponentCollectionBuilder.cs b/src/Umbraco.Core/Composing/ComponentCollectionBuilder.cs index f4cdb802387e..847a5e7d30e6 100644 --- a/src/Umbraco.Core/Composing/ComponentCollectionBuilder.cs +++ b/src/Umbraco.Core/Composing/ComponentCollectionBuilder.cs @@ -10,8 +10,10 @@ public class ComponentCollectionBuilder : OrderedCollectionBuilderBase protected override ComponentCollectionBuilder This => this; + /// protected override IEnumerable CreateItems(IServiceProvider factory) { IProfilingLogger logger = factory.GetRequiredService(); @@ -24,6 +26,7 @@ protected override IEnumerable CreateItems(IServiceProvider fac } } + /// protected override IAsyncComponent CreateItem(IServiceProvider factory, Type itemType) { IProfilingLogger logger = factory.GetRequiredService(); diff --git a/src/Umbraco.Core/Composing/ComposerGraph.cs b/src/Umbraco.Core/Composing/ComposerGraph.cs index 0c376befd514..699d4ca466b8 100644 --- a/src/Umbraco.Core/Composing/ComposerGraph.cs +++ b/src/Umbraco.Core/Composing/ComposerGraph.cs @@ -62,6 +62,11 @@ public void Compose() } } + /// + /// Gets a formatted report of composers and their dependencies. + /// + /// A dictionary of types to their required dependencies. + /// A formatted string containing the composers report. internal static string GetComposersReport(Dictionary?> requirements) { var text = new StringBuilder(); @@ -116,6 +121,10 @@ bool HasReq(IEnumerable types, Type type) return text.ToString(); } + /// + /// Prepares and orders the composer types based on their dependencies. + /// + /// An ordered collection of composer types. internal IEnumerable PrepareComposerTypes() { Dictionary?> requirements = GetRequirements(); @@ -134,6 +143,11 @@ internal IEnumerable PrepareComposerTypes() return sortedComposerTypes; } + /// + /// Gets the dependency requirements for all composer types. + /// + /// If set to true, throws an exception when required dependencies are missing. + /// A dictionary mapping each type to its required dependencies. internal Dictionary?> GetRequirements(bool throwOnMissing = true) { // create a list, remove those that cannot be enabled due to runtime level @@ -202,6 +216,11 @@ static void GatherInterfaces(Type type, Func getTy return requirements; } + /// + /// Sorts the composers based on their dependency requirements. + /// + /// A dictionary of types to their required dependencies. + /// A sorted collection of composer types. internal IEnumerable SortComposers(Dictionary?> requirements) { // sort composers @@ -415,10 +434,19 @@ private static IEnumerable InstantiateComposers(IEnumerable typ } } + /// + /// Stores enable/disable information for a composer type. + /// private sealed class EnableInfo { + /// + /// Gets or sets a value indicating whether the composer is enabled. + /// public bool Enabled { get; set; } + /// + /// Gets or sets the weight of the enable/disable declaration. + /// public int Weight { get; set; } = -1; } } diff --git a/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs b/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs index 0f1d0cc571b0..a3a29d27001a 100644 --- a/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs +++ b/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs @@ -19,6 +19,13 @@ public class DefaultUmbracoAssemblyProvider : IAssemblyProvider private readonly ILoggerFactory _loggerFactory; private List? _discovered; + /// + /// Initializes a new instance of the class. + /// + /// The entry point assembly to scan from. + /// The logger factory for creating loggers. + /// Optional additional assembly names to include in scanning. + /// Thrown when is null. public DefaultUmbracoAssemblyProvider( Assembly? entryPointAssembly, ILoggerFactory loggerFactory, @@ -34,6 +41,8 @@ public DefaultUmbracoAssemblyProvider( // that will still only resolve Assemblies that are already loaded but it would also make it possible to // query dynamically generated assemblies once they are added. It would also provide the ability to probe // assembly locations that are not in the same place as the entry point assemblies. + + /// public IEnumerable Assemblies { get diff --git a/src/Umbraco.Core/Composing/DisableAttribute.cs b/src/Umbraco.Core/Composing/DisableAttribute.cs index 09d638188da2..a81c803fb717 100644 --- a/src/Umbraco.Core/Composing/DisableAttribute.cs +++ b/src/Umbraco.Core/Composing/DisableAttribute.cs @@ -29,6 +29,11 @@ public DisableAttribute() { } + /// + /// Initializes a new instance of the class. + /// + /// The full type name of the composer to disable. + /// The assembly name containing the composer type. public DisableAttribute(string fullTypeName, string assemblyName) => DisabledType = Assembly.Load(assemblyName)?.GetType(fullTypeName); diff --git a/src/Umbraco.Core/Composing/FindAssembliesWithReferencesTo.cs b/src/Umbraco.Core/Composing/FindAssembliesWithReferencesTo.cs index a1581ccfcb11..c7a76ab19199 100644 --- a/src/Umbraco.Core/Composing/FindAssembliesWithReferencesTo.cs +++ b/src/Umbraco.Core/Composing/FindAssembliesWithReferencesTo.cs @@ -38,6 +38,10 @@ public FindAssembliesWithReferencesTo(Assembly[] referenceAssemblies, string[] t _logger = _loggerFactory.CreateLogger(); } + /// + /// Finds all assemblies that reference the target assemblies. + /// + /// A collection of assemblies that reference the target assemblies. public IEnumerable Find() { var referenceItems = new List(); diff --git a/src/Umbraco.Core/Composing/HideFromTypeFinderAttribute.cs b/src/Umbraco.Core/Composing/HideFromTypeFinderAttribute.cs index 4478deb5ac85..5744b1ca6e14 100644 --- a/src/Umbraco.Core/Composing/HideFromTypeFinderAttribute.cs +++ b/src/Umbraco.Core/Composing/HideFromTypeFinderAttribute.cs @@ -1,8 +1,11 @@ namespace Umbraco.Cms.Core.Composing; /// -/// Notifies the TypeFinder that it should ignore the class marked with this attribute. +/// Notifies the that it should ignore the class marked with this attribute. /// +/// +/// Apply this attribute to classes that should not be discovered during type scanning operations. +/// [AttributeUsage(AttributeTargets.Class)] public sealed class HideFromTypeFinderAttribute : Attribute { diff --git a/src/Umbraco.Core/Composing/IAssemblyProvider.cs b/src/Umbraco.Core/Composing/IAssemblyProvider.cs index 4148c9ee4788..39629e82ce7e 100644 --- a/src/Umbraco.Core/Composing/IAssemblyProvider.cs +++ b/src/Umbraco.Core/Composing/IAssemblyProvider.cs @@ -3,9 +3,12 @@ namespace Umbraco.Cms.Core.Composing; /// -/// Provides a list of assemblies that can be scanned +/// Provides a list of assemblies that can be scanned. /// public interface IAssemblyProvider { + /// + /// Gets the collection of assemblies available for type scanning. + /// IEnumerable Assemblies { get; } } diff --git a/src/Umbraco.Core/Composing/IDiscoverable.cs b/src/Umbraco.Core/Composing/IDiscoverable.cs index 848c70ddab7c..3e21738e4192 100644 --- a/src/Umbraco.Core/Composing/IDiscoverable.cs +++ b/src/Umbraco.Core/Composing/IDiscoverable.cs @@ -1,5 +1,13 @@ namespace Umbraco.Cms.Core.Composing; +/// +/// Marker interface for types that should be discovered during type scanning. +/// +/// +/// Types implementing this interface are cached during discovery operations, +/// making subsequent lookups faster. Use this interface for plugin types that +/// need to be discovered at runtime. +/// public interface IDiscoverable { } diff --git a/src/Umbraco.Core/Composing/IRuntimeHash.cs b/src/Umbraco.Core/Composing/IRuntimeHash.cs index d641c9053803..dfff8d0c8a8d 100644 --- a/src/Umbraco.Core/Composing/IRuntimeHash.cs +++ b/src/Umbraco.Core/Composing/IRuntimeHash.cs @@ -1,13 +1,17 @@ namespace Umbraco.Cms.Core.Composing; /// -/// Used to create a hash value of the current runtime +/// Used to create a hash value of the current runtime. /// /// -/// This is used to detect if the runtime itself has changed, like a DLL has changed or another dynamically compiled -/// part of the application has changed. This is used to detect if we need to re-type scan. +/// This is used to detect if the runtime itself has changed, like a DLL has changed or another dynamically compiled +/// part of the application has changed. This is used to detect if we need to re-type scan. /// public interface IRuntimeHash { + /// + /// Gets the hash value representing the current runtime state. + /// + /// A string hash value that changes when the runtime changes. string GetHashValue(); } diff --git a/src/Umbraco.Core/Composing/ITypeFinder.cs b/src/Umbraco.Core/Composing/ITypeFinder.cs index 4bebfae33467..221fc934b80a 100644 --- a/src/Umbraco.Core/Composing/ITypeFinder.cs +++ b/src/Umbraco.Core/Composing/ITypeFinder.cs @@ -10,9 +10,14 @@ public interface ITypeFinder /// /// Return a list of found local Assemblies that Umbraco should scan for type finding /// - /// + /// The assemblies to scan. IEnumerable AssembliesToScan { get; } + /// + /// Gets a type by its full name. + /// + /// The full name of the type to find. + /// The type if found; otherwise, null. Type? GetTypeByName(string name); /// diff --git a/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs index 49ada40dfa42..adf05517c27b 100644 --- a/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/LazyCollectionBuilderBase.cs @@ -17,6 +17,9 @@ public abstract class private readonly List _excluded = new(); private readonly List>> _producers = new(); + /// + /// Gets the current builder instance. + /// protected abstract TBuilder This { get; } /// @@ -122,6 +125,7 @@ public TBuilder Exclude(Type type) return This; } + /// protected override IEnumerable GetRegisteringTypes(IEnumerable types) => types .Union(_producers.SelectMany(x => x())) diff --git a/src/Umbraco.Core/Composing/LazyReadOnlyCollection.cs b/src/Umbraco.Core/Composing/LazyReadOnlyCollection.cs index eb6f2ed055af..08bf6f18d4c8 100644 --- a/src/Umbraco.Core/Composing/LazyReadOnlyCollection.cs +++ b/src/Umbraco.Core/Composing/LazyReadOnlyCollection.cs @@ -2,18 +2,34 @@ namespace Umbraco.Cms.Core.Composing; +/// +/// Represents a lazily-initialized read-only collection. +/// +/// The type of elements in the collection. public sealed class LazyReadOnlyCollection : IReadOnlyCollection { private readonly Lazy> _lazyCollection; private int? _count; + /// + /// Initializes a new instance of the class. + /// + /// A lazy wrapper containing the collection factory. public LazyReadOnlyCollection(Lazy> lazyCollection) => _lazyCollection = lazyCollection; + /// + /// Initializes a new instance of the class. + /// + /// A factory function that creates the collection when first accessed. public LazyReadOnlyCollection(Func> lazyCollection) => _lazyCollection = new Lazy>(lazyCollection); + /// + /// Gets the underlying collection value. + /// public IEnumerable Value => EnsureCollection(); + /// public int Count { get @@ -23,8 +39,10 @@ public int Count } } + /// public IEnumerator GetEnumerator() => Value.GetEnumerator(); + /// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); private IEnumerable EnsureCollection() diff --git a/src/Umbraco.Core/Composing/LazyResolve.cs b/src/Umbraco.Core/Composing/LazyResolve.cs index 723d9afe2e35..96b2d278baab 100644 --- a/src/Umbraco.Core/Composing/LazyResolve.cs +++ b/src/Umbraco.Core/Composing/LazyResolve.cs @@ -2,9 +2,21 @@ namespace Umbraco.Cms.Core.Composing; +/// +/// Provides lazy resolution of a service from the dependency injection container. +/// +/// The type of service to resolve. +/// +/// This class defers service resolution until the property is accessed, +/// which can help avoid circular dependency issues during application startup. +/// public class LazyResolve : Lazy where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The service provider used to resolve the service. public LazyResolve(IServiceProvider serviceProvider) : base(serviceProvider.GetRequiredService) { diff --git a/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs index d9c733da7d18..394658808009 100644 --- a/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/OrderedCollectionBuilderBase.cs @@ -10,6 +10,9 @@ public abstract class OrderedCollectionBuilderBase where TBuilder : OrderedCollectionBuilderBase where TCollection : class, IBuilderCollection { + /// + /// Gets the current builder instance. + /// protected abstract TBuilder This { get; } /// diff --git a/src/Umbraco.Core/Composing/ReferenceResolver.cs b/src/Umbraco.Core/Composing/ReferenceResolver.cs index e1068e8c488c..a43e127171bd 100644 --- a/src/Umbraco.Core/Composing/ReferenceResolver.cs +++ b/src/Umbraco.Core/Composing/ReferenceResolver.cs @@ -21,6 +21,12 @@ internal sealed class ReferenceResolver private readonly List _lookup = new(); private readonly HashSet _umbracoAssemblies; + /// + /// Initializes a new instance of the class. + /// + /// The target assembly names to check for references. + /// The entry point assemblies to start resolution from. + /// The logger instance. public ReferenceResolver(IReadOnlyList targetAssemblies, IReadOnlyList entryPointAssemblies, ILogger logger) { _umbracoAssemblies = new HashSet(targetAssemblies, StringComparer.Ordinal); @@ -34,20 +40,38 @@ public ReferenceResolver(IReadOnlyList targetAssemblies, IReadOnlyList + /// Classification states for assembly reference resolution. + /// private enum Classification { + /// + /// The assembly classification is not yet determined. + /// Unknown, + + /// + /// The assembly does not reference Umbraco. + /// DoesNotReferenceUmbraco, + + /// + /// The assembly references Umbraco directly or transitively. + /// ReferencesUmbraco, + + /// + /// The assembly is part of Umbraco core. + /// IsUmbraco, } /// - /// Returns a list of assemblies that directly reference or transitively reference the targetAssemblies + /// Returns a list of assemblies that directly reference or transitively reference the target assemblies. /// - /// + /// A collection of assemblies that reference the target assemblies. /// - /// This includes all assemblies in the same location as the entry point assemblies + /// This includes all assemblies in the same location as the entry point assemblies. /// public IEnumerable ResolveAssemblies() { diff --git a/src/Umbraco.Core/Composing/RuntimeHash.cs b/src/Umbraco.Core/Composing/RuntimeHash.cs index e7a621fe036a..3b64ae537b4a 100644 --- a/src/Umbraco.Core/Composing/RuntimeHash.cs +++ b/src/Umbraco.Core/Composing/RuntimeHash.cs @@ -12,12 +12,18 @@ public class RuntimeHash : IRuntimeHash private readonly RuntimeHashPaths _paths; private string? _calculated; + /// + /// Initializes a new instance of the class. + /// + /// The profiling logger for timing hash calculations. + /// The paths to include in the hash calculation. public RuntimeHash(IProfilingLogger logger, RuntimeHashPaths paths) { _logger = logger; _paths = paths; } + /// public string GetHashValue() { if (_calculated != null) diff --git a/src/Umbraco.Core/Composing/RuntimeHashPaths.cs b/src/Umbraco.Core/Composing/RuntimeHashPaths.cs index 5720fdebe2e6..d1c212566711 100644 --- a/src/Umbraco.Core/Composing/RuntimeHashPaths.cs +++ b/src/Umbraco.Core/Composing/RuntimeHashPaths.cs @@ -10,6 +10,11 @@ public sealed class RuntimeHashPaths private readonly Dictionary _files = new(); private readonly List _paths = new(); + /// + /// Adds a folder to be included in the runtime hash calculation. + /// + /// The directory information for the folder to add. + /// The current instance for method chaining. public RuntimeHashPaths AddFolder(DirectoryInfo pathInfo) { _paths.Add(pathInfo); @@ -35,9 +40,22 @@ public RuntimeHashPaths AddAssemblies(IAssemblyProvider assemblyProvider) return this; } + /// + /// Adds a file to be included in the runtime hash calculation. + /// + /// The file information for the file to add. + /// If set to true, the file content is scanned; otherwise, only file metadata is used. public void AddFile(FileInfo fileInfo, bool scanFileContent = false) => _files.Add(fileInfo, scanFileContent); + /// + /// Gets all folders that have been added for hash calculation. + /// + /// A collection of directory information objects. public IEnumerable GetFolders() => _paths; + /// + /// Gets all files that have been added for hash calculation. + /// + /// A dictionary mapping file information to a boolean indicating whether to scan content. public IReadOnlyDictionary GetFiles() => _files; } diff --git a/src/Umbraco.Core/Composing/SetCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/SetCollectionBuilderBase.cs index b686067d30b8..a5d1adc5f795 100644 --- a/src/Umbraco.Core/Composing/SetCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/SetCollectionBuilderBase.cs @@ -16,6 +16,9 @@ public abstract class SetCollectionBuilderBase : C where TBuilder : SetCollectionBuilderBase where TCollection : class, IBuilderCollection { + /// + /// Gets the current builder instance. + /// protected abstract TBuilder This { get; } /// diff --git a/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs index 072a9d99e300..f60555377358 100644 --- a/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/TypeCollectionBuilderBase.cs @@ -13,20 +13,37 @@ public abstract class { private readonly HashSet _types = new(); + /// + /// Gets the current builder instance. + /// protected abstract TBuilder This { get; } + /// public TCollection CreateCollection(IServiceProvider factory) => factory.CreateInstance(CreateItemsFactory()); + /// public void RegisterWith(IServiceCollection services) => services.Add(new ServiceDescriptor(typeof(TCollection), CreateCollection, ServiceLifetime.Singleton)); + /// + /// Adds a type to the collection. + /// + /// The type to add. + /// The builder. public TBuilder Add(Type type) { _types.Add(Validate(type, "add")); return This; } + /// + /// Validates that the specified type is assignable from the constraint type. + /// + /// The type to validate. + /// The action being performed (used in error messages). + /// The validated type. + /// Thrown when the type does not inherit from or implement . private static Type Validate(Type type, string action) { if (!typeof(TConstraint).IsAssignableFrom(type)) @@ -38,12 +55,22 @@ private static Type Validate(Type type, string action) return type; } + /// + /// Adds a type to the collection. + /// + /// The type to add. + /// The builder. public TBuilder Add() { Add(typeof(T)); return This; } + /// + /// Adds multiple types to the collection. + /// + /// The types to add. + /// The builder. public TBuilder Add(IEnumerable types) { foreach (Type type in types) @@ -54,18 +81,31 @@ public TBuilder Add(IEnumerable types) return This; } + /// + /// Removes a type from the collection. + /// + /// The type to remove. + /// The builder. public TBuilder Remove(Type type) { _types.Remove(Validate(type, "remove")); return This; } + /// + /// Removes a type from the collection. + /// + /// The type to remove. + /// The builder. public TBuilder Remove() { Remove(typeof(T)); return This; } - // used to resolve a Func> parameter + /// + /// Creates a factory function that returns the types in the collection. + /// + /// A function that returns the collection of types. private Func> CreateItemsFactory() => () => _types; } diff --git a/src/Umbraco.Core/Composing/TypeFinder.cs b/src/Umbraco.Core/Composing/TypeFinder.cs index 6a610180b8b5..1dd20a62b14b 100644 --- a/src/Umbraco.Core/Composing/TypeFinder.cs +++ b/src/Umbraco.Core/Composing/TypeFinder.cs @@ -49,6 +49,14 @@ public class TypeFinder : ITypeFinder private string[]? _assembliesAcceptingLoadExceptions; private volatile HashSet? _localFilteredAssemblyCache; + /// + /// Initializes a new instance of the class. + /// + /// The logger instance. + /// The assembly provider for discovering assemblies. + /// Optional additional assembly name prefixes to exclude from scanning. + /// Optional type finder configuration. + /// Thrown when is null. public TypeFinder(ILogger logger, IAssemblyProvider assemblyProvider, string[]? additionalExlusionAssemblies, ITypeFinderConfig? typeFinderConfig = null) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); @@ -79,7 +87,10 @@ public IEnumerable AssembliesToScan } } - // used for benchmark tests + /// + /// Gets or sets a value indicating whether to query with referencing assemblies. + /// + /// Used for benchmark tests. internal bool QueryWithReferencingAssemblies { get; set; } = true; private string[] AssembliesAcceptingLoadExceptions @@ -99,14 +110,7 @@ private string[] AssembliesAcceptingLoadExceptions } } - /// - /// Finds any classes derived from the assignTypeFrom Type that contain the attribute TAttribute - /// - /// - /// - /// - /// - /// + /// public IEnumerable FindClassesOfTypeWithAttribute( Type assignTypeFrom, Type attributeType, @@ -124,13 +128,7 @@ public IEnumerable FindClassesOfTypeWithAttribute( t => t.GetCustomAttributes(attributeType, false).Any()); } - /// - /// Returns all types found of in the assemblies specified of type T - /// - /// - /// - /// - /// + /// public IEnumerable FindClassesOfType(Type assignTypeFrom, IEnumerable? assemblies = null, bool onlyConcreteClasses = true) { IEnumerable assemblyList = assemblies ?? AssembliesToScan; @@ -138,13 +136,7 @@ public IEnumerable FindClassesOfType(Type assignTypeFrom, IEnumerable - /// Finds any classes with the attribute. - /// - /// The attribute type - /// The assemblies. - /// if set to true only concrete classes. - /// + /// public IEnumerable FindClassesWithAttribute( Type attributeType, IEnumerable? assemblies = null, @@ -155,11 +147,7 @@ public IEnumerable FindClassesWithAttribute( return GetClassesWithAttribute(attributeType, assemblyList, onlyConcreteClasses); } - /// - /// Returns a Type for the string type name - /// - /// - /// + /// public virtual Type? GetTypeByName(string name) { // NOTE: This will not find types in dynamic assemblies unless those assemblies are already loaded diff --git a/src/Umbraco.Core/Composing/TypeFinderConfig.cs b/src/Umbraco.Core/Composing/TypeFinderConfig.cs index efba61ccb43d..7664a4e190a5 100644 --- a/src/Umbraco.Core/Composing/TypeFinderConfig.cs +++ b/src/Umbraco.Core/Composing/TypeFinderConfig.cs @@ -12,8 +12,13 @@ public class TypeFinderConfig : ITypeFinderConfig private readonly TypeFinderSettings _settings; private IEnumerable? _assembliesAcceptingLoadExceptions; + /// + /// Initializes a new instance of the class. + /// + /// The type finder settings options. public TypeFinderConfig(IOptions settings) => _settings = settings.Value; + /// public IEnumerable AssembliesAcceptingLoadExceptions { get diff --git a/src/Umbraco.Core/Composing/TypeFinderExtensions.cs b/src/Umbraco.Core/Composing/TypeFinderExtensions.cs index c67d9357164f..434471b7243c 100644 --- a/src/Umbraco.Core/Composing/TypeFinderExtensions.cs +++ b/src/Umbraco.Core/Composing/TypeFinderExtensions.cs @@ -3,6 +3,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for to simplify type discovery operations. +/// public static class TypeFinderExtensions { /// diff --git a/src/Umbraco.Core/Composing/TypeHelper.cs b/src/Umbraco.Core/Composing/TypeHelper.cs index 5fa4b2b57b44..acdba6cf1379 100644 --- a/src/Umbraco.Core/Composing/TypeHelper.cs +++ b/src/Umbraco.Core/Composing/TypeHelper.cs @@ -283,6 +283,12 @@ public static PropertyInfo[] CachedDiscoverableProperties(Type type, bool mustRe && (includeIndexed || y.GetIndexParameters().Any() == false)) .ToArray()); + /// + /// Determines whether an implementation type matches a contract type, supporting generic types and variance. + /// + /// The implementation type to check. + /// The contract type to match against. + /// true if the implementation matches the contract; otherwise, false. public static bool MatchType(Type implementation, Type contract) => MatchType(implementation, contract, new Dictionary()); @@ -337,6 +343,14 @@ private static bool MatchGeneric(Type implementation, Type contract, IDictionary return true; } + /// + /// Determines whether an implementation type matches a contract type, supporting generic types and variance. + /// + /// The implementation type to check. + /// The contract type to match against. + /// A dictionary to track generic parameter bindings during matching. + /// If true, allows variance (inheritance/interface matching); otherwise, requires exact type matching. + /// true if the implementation matches the contract; otherwise, false. public static bool MatchType(Type implementation, Type contract, IDictionary bindings, bool variance = true) { if (contract.IsGenericType) diff --git a/src/Umbraco.Core/Composing/VaryingRuntimeHash.cs b/src/Umbraco.Core/Composing/VaryingRuntimeHash.cs index 740921974db2..de0c9ace2aa2 100644 --- a/src/Umbraco.Core/Composing/VaryingRuntimeHash.cs +++ b/src/Umbraco.Core/Composing/VaryingRuntimeHash.cs @@ -7,7 +7,15 @@ public sealed class VaryingRuntimeHash : IRuntimeHash { private readonly string _hash; + /// + /// Initializes a new instance of the class. + /// + /// + /// The hash value is generated based on the current timestamp, ensuring + /// a unique hash on each application startup. + /// public VaryingRuntimeHash() => _hash = DateTime.Now.Ticks.ToString(); + /// public string GetHashValue() => _hash; } diff --git a/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs b/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs index 60bf73d47876..4efe3566f9d5 100644 --- a/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs +++ b/src/Umbraco.Core/Composing/WeightedCollectionBuilderBase.cs @@ -12,8 +12,14 @@ public abstract class WeightedCollectionBuilderBase _customWeights = new(); + /// + /// Gets or sets the default weight for items that don't have a . + /// public virtual int DefaultWeight { get; set; } = 100; + /// + /// Gets the current builder instance. + /// protected abstract TBuilder This { get; } /// @@ -135,6 +141,7 @@ public TBuilder SetWeight(int weight) return This; } + /// protected override IEnumerable GetRegisteringTypes(IEnumerable types) { var list = types.ToList(); @@ -142,6 +149,11 @@ protected override IEnumerable GetRegisteringTypes(IEnumerable types return list; } + /// + /// Gets the weight of a type. + /// + /// The type to get the weight for. + /// The weight from a custom weight, , or . protected virtual int GetWeight(Type type) { if (_customWeights.TryGetValue(type, out int weight)) diff --git a/src/Umbraco.Core/Configuration/ContentSettingsExtensions.cs b/src/Umbraco.Core/Configuration/ContentSettingsExtensions.cs index 94e2968056c5..2d567c51a3b3 100644 --- a/src/Umbraco.Core/Configuration/ContentSettingsExtensions.cs +++ b/src/Umbraco.Core/Configuration/ContentSettingsExtensions.cs @@ -2,6 +2,9 @@ namespace Umbraco.Extensions; +/// +/// Extension methods for . +/// public static class ContentSettingsExtensions { /// diff --git a/src/Umbraco.Core/Configuration/EntryAssemblyMetadata.cs b/src/Umbraco.Core/Configuration/EntryAssemblyMetadata.cs index 9b0c23d0a7b2..aea3d672e262 100644 --- a/src/Umbraco.Core/Configuration/EntryAssemblyMetadata.cs +++ b/src/Umbraco.Core/Configuration/EntryAssemblyMetadata.cs @@ -2,8 +2,14 @@ namespace Umbraco.Cms.Core.Configuration; +/// +/// Provides metadata about the entry assembly by reading assembly attributes. +/// internal sealed class EntryAssemblyMetadata : IEntryAssemblyMetadata { + /// + /// Initializes a new instance of the class. + /// public EntryAssemblyMetadata() { var entryAssembly = Assembly.GetEntryAssembly(); @@ -17,7 +23,9 @@ public EntryAssemblyMetadata() ?.InformationalVersion ?? string.Empty; } + /// public string Name { get; } + /// public string InformationalVersion { get; } } diff --git a/src/Umbraco.Core/Configuration/IConfigManipulator.cs b/src/Umbraco.Core/Configuration/IConfigManipulator.cs index 3fde58c16e77..5d0b97981f1e 100644 --- a/src/Umbraco.Core/Configuration/IConfigManipulator.cs +++ b/src/Umbraco.Core/Configuration/IConfigManipulator.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Configuration; +/// +/// Defines the contract for manipulating configuration settings. +/// public interface IConfigManipulator { /// diff --git a/src/Umbraco.Core/Configuration/IUmbracoVersion.cs b/src/Umbraco.Core/Configuration/IUmbracoVersion.cs index 99a5cddfdb1b..5cae51bf4561 100644 --- a/src/Umbraco.Core/Configuration/IUmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/IUmbracoVersion.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Configuration; +/// +/// Defines the contract for accessing Umbraco version information. +/// public interface IUmbracoVersion { /// diff --git a/src/Umbraco.Core/Configuration/LocalTempStorage.cs b/src/Umbraco.Core/Configuration/LocalTempStorage.cs index 8be409fc2b8a..1cfa25f7eb1a 100644 --- a/src/Umbraco.Core/Configuration/LocalTempStorage.cs +++ b/src/Umbraco.Core/Configuration/LocalTempStorage.cs @@ -1,8 +1,22 @@ namespace Umbraco.Cms.Core.Configuration; +/// +/// Specifies the local temporary storage location. +/// public enum LocalTempStorage { + /// + /// The storage location is unknown. + /// Unknown = 0, + + /// + /// Use the default storage location within the application directory. + /// Default, + + /// + /// Use the system's environment temporary directory. + /// EnvironmentTemp, } diff --git a/src/Umbraco.Core/Configuration/MemberPasswordConfiguration.cs b/src/Umbraco.Core/Configuration/MemberPasswordConfiguration.cs index 33471ced160f..b4450cbd7db2 100644 --- a/src/Umbraco.Core/Configuration/MemberPasswordConfiguration.cs +++ b/src/Umbraco.Core/Configuration/MemberPasswordConfiguration.cs @@ -1,10 +1,14 @@ namespace Umbraco.Cms.Core.Configuration; /// -/// The password configuration for members +/// The password configuration for members. /// public class MemberPasswordConfiguration : PasswordConfiguration, IMemberPasswordConfiguration { + /// + /// Initializes a new instance of the class. + /// + /// The member password configuration settings. public MemberPasswordConfiguration(IMemberPasswordConfiguration configSettings) : base(configSettings) { diff --git a/src/Umbraco.Core/Configuration/Models/Attributes/UmbracoOptionsAttribute.cs b/src/Umbraco.Core/Configuration/Models/Attributes/UmbracoOptionsAttribute.cs index 5f42aac54523..5290315b96d3 100644 --- a/src/Umbraco.Core/Configuration/Models/Attributes/UmbracoOptionsAttribute.cs +++ b/src/Umbraco.Core/Configuration/Models/Attributes/UmbracoOptionsAttribute.cs @@ -1,11 +1,27 @@ namespace Umbraco.Cms.Core.Configuration.Models; +/// +/// Attribute used to mark a class as an Umbraco configuration options class. +/// +/// +/// This attribute specifies the configuration key used to bind settings from configuration sources. +/// [AttributeUsage(AttributeTargets.Class)] public class UmbracoOptionsAttribute : Attribute { + /// + /// Initializes a new instance of the class. + /// + /// The configuration key used to bind the settings. public UmbracoOptionsAttribute(string configurationKey) => ConfigurationKey = configurationKey; + /// + /// Gets the configuration key used to bind the settings. + /// public string ConfigurationKey { get; } + /// + /// Gets or sets a value indicating whether to bind non-public properties. + /// public bool BindNonPublicProperties { get; set; } } diff --git a/src/Umbraco.Core/Configuration/Models/BasicAuthSettings.cs b/src/Umbraco.Core/Configuration/Models/BasicAuthSettings.cs index 94cab1763f3c..4944a84fae43 100644 --- a/src/Umbraco.Core/Configuration/Models/BasicAuthSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/BasicAuthSettings.cs @@ -19,19 +19,37 @@ public class BasicAuthSettings [DefaultValue(StaticEnabled)] public bool Enabled { get; set; } = StaticEnabled; + /// + /// Gets or sets the collection of allowed IP addresses that bypass basic authentication. + /// public ISet AllowedIPs { get; set; } = new HashSet(); + /// + /// Gets or sets the shared secret configuration for header-based authentication. + /// public SharedSecret SharedSecret { get; set; } = new(); + /// + /// Gets or sets a value indicating whether to redirect to the login page instead of showing basic auth prompt. + /// public bool RedirectToLoginPage { get; set; } = false; } +/// +/// Typed configuration options for shared secret header-based authentication. +/// public class SharedSecret { private const string StaticHeaderName = "X-Authentication-Shared-Secret"; + /// + /// Gets or sets the name of the HTTP header containing the shared secret. + /// [DefaultValue(StaticHeaderName)] public string? HeaderName { get; set; } = StaticHeaderName; + /// + /// Gets or sets the shared secret value. + /// public string? Value { get; set; } } diff --git a/src/Umbraco.Core/Configuration/Models/CharItem.cs b/src/Umbraco.Core/Configuration/Models/CharItem.cs index 625033a82acb..69aaf78cae4c 100644 --- a/src/Umbraco.Core/Configuration/Models/CharItem.cs +++ b/src/Umbraco.Core/Configuration/Models/CharItem.cs @@ -2,15 +2,18 @@ namespace Umbraco.Cms.Core.Configuration.Models; +/// +/// Represents a character replacement mapping for URL slug generation. +/// public class CharItem : IChar { /// - /// The character to replace + /// Gets or sets the character to replace. /// public string Char { get; set; } = null!; /// - /// The replacement character + /// Gets or sets the replacement character. /// public string Replacement { get; set; } = null!; } diff --git a/src/Umbraco.Core/Configuration/Models/ContentErrorPage.cs b/src/Umbraco.Core/Configuration/Models/ContentErrorPage.cs index 5e194ffabb95..c4bd826cf5df 100644 --- a/src/Umbraco.Core/Configuration/Models/ContentErrorPage.cs +++ b/src/Umbraco.Core/Configuration/Models/ContentErrorPage.cs @@ -37,6 +37,10 @@ public class ContentErrorPage : ValidatableEntryBase [Required] public string Culture { get; set; } = null!; + /// + /// Validates the content error page configuration. + /// + /// true if the entry is valid and either or is set; otherwise, false. internal sealed override bool IsValid() => base.IsValid() && (HasContentId ^ HasContentKey); diff --git a/src/Umbraco.Core/Configuration/Models/ContentNotificationSettings.cs b/src/Umbraco.Core/Configuration/Models/ContentNotificationSettings.cs index ce5c3aebf319..3bc4fe6ac030 100644 --- a/src/Umbraco.Core/Configuration/Models/ContentNotificationSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/ContentNotificationSettings.cs @@ -10,6 +10,9 @@ namespace Umbraco.Cms.Core.Configuration.Models; /// public class ContentNotificationSettings { + /// + /// The default value for disabling HTML email notifications. + /// internal const bool StaticDisableHtmlEmail = false; /// diff --git a/src/Umbraco.Core/Configuration/Models/ContentSettings.cs b/src/Umbraco.Core/Configuration/Models/ContentSettings.cs index 645d21c56711..4a12399a9751 100644 --- a/src/Umbraco.Core/Configuration/Models/ContentSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/ContentSettings.cs @@ -11,27 +11,87 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigContent)] public class ContentSettings { + /// + /// The default value for resolving URLs from text strings. + /// internal const bool StaticResolveUrlsFromTextString = false; + /// + /// The default preview badge markup template. + /// internal const string StaticDefaultPreviewBadge = @" "; + /// + /// The default comma-separated list of disallowed file extensions for upload. + /// internal const string StaticDisallowedUploadFiles = "ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,xamlx"; + + /// + /// The default value for showing deprecated property editors. + /// internal const bool StaticShowDeprecatedPropertyEditors = false; + + /// + /// The default path for the login background image. + /// internal const string StaticLoginBackgroundImage = "assets/login.jpg"; + + /// + /// The default path for the login logo image. + /// internal const string StaticLoginLogoImage = "assets/logo_light.svg"; + + /// + /// The default path for the alternative login logo image. + /// internal const string StaticLoginLogoImageAlternative = "assets/logo_dark.svg"; + + /// + /// The default path for the back-office logo. + /// internal const string StaticBackOfficeLogo = "assets/logo.svg"; + + /// + /// The default path for the alternative back-office logo. + /// internal const string StaticBackOfficeLogoAlternative = "assets/logo_blue.svg"; + + /// + /// The default value for hiding the back-office logo. + /// internal const bool StaticHideBackOfficeLogo = false; + + /// + /// The default value for disabling delete when referenced. + /// internal const bool StaticDisableDeleteWhenReferenced = false; + + /// + /// The default value for disabling unpublish when referenced. + /// internal const bool StaticDisableUnpublishWhenReferenced = false; + + /// + /// The default value for allowing edit of invariant properties from non-default language. + /// internal const bool StaticAllowEditInvariantFromNonDefault = false; + + /// + /// The default value for showing domain warnings. + /// internal const bool StaticShowDomainWarnings = true; + + /// + /// The default value for showing unroutable content warnings. + /// internal const bool StaticShowUnroutableContentWarnings = true; // TODO (V18): Consider enabling this by default and documenting as a behavioural breaking change. + /// + /// The default value for enabling media recycle bin protection. + /// private const bool StaticEnableMediaRecycleBinProtection = false; /// diff --git a/src/Umbraco.Core/Configuration/Models/CoreDebugSettings.cs b/src/Umbraco.Core/Configuration/Models/CoreDebugSettings.cs index 052d37c5fe3a..ab0098442cde 100644 --- a/src/Umbraco.Core/Configuration/Models/CoreDebugSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/CoreDebugSettings.cs @@ -11,7 +11,14 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigCoreDebug)] public class CoreDebugSettings { + /// + /// The default value for logging incompleted scopes. + /// internal const bool StaticLogIncompletedScopes = false; + + /// + /// The default value for dumping on timeout thread abort. + /// internal const bool StaticDumpOnTimeoutThreadAbort = false; /// diff --git a/src/Umbraco.Core/Configuration/Models/DataTypeChangeMode.cs b/src/Umbraco.Core/Configuration/Models/DataTypeChangeMode.cs index 870c24568a4c..0198abe69c12 100644 --- a/src/Umbraco.Core/Configuration/Models/DataTypeChangeMode.cs +++ b/src/Umbraco.Core/Configuration/Models/DataTypeChangeMode.cs @@ -1,8 +1,22 @@ -namespace Umbraco.Cms.Core.Configuration.Models; +namespace Umbraco.Cms.Core.Configuration.Models; +/// +/// Specifies the mode for allowing data type changes after they have been used. +/// public enum DataTypeChangeMode { + /// + /// Data types can be changed after being used. + /// True, + + /// + /// Data types cannot be changed after being used. + /// False, + + /// + /// Data types cannot be changed after being used, and help text is displayed to explain this. + /// FalseWithHelpText } diff --git a/src/Umbraco.Core/Configuration/Models/DataTypesSettings.cs b/src/Umbraco.Core/Configuration/Models/DataTypesSettings.cs index 337abc36b43f..804262d17003 100644 --- a/src/Umbraco.Core/Configuration/Models/DataTypesSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/DataTypesSettings.cs @@ -1,10 +1,16 @@ -using System.ComponentModel; +using System.ComponentModel; namespace Umbraco.Cms.Core.Configuration.Models; +/// +/// Typed configuration options for data types settings. +/// [UmbracoOptions(Constants.Configuration.ConfigDataTypes)] public class DataTypesSettings { + /// + /// The default value for the setting. + /// internal const DataTypeChangeMode StaticDataTypeChangeMode = DataTypeChangeMode.True; /// diff --git a/src/Umbraco.Core/Configuration/Models/DatabaseServerMessengerSettings.cs b/src/Umbraco.Core/Configuration/Models/DatabaseServerMessengerSettings.cs index a083b164a8d2..4a147e0688c8 100644 --- a/src/Umbraco.Core/Configuration/Models/DatabaseServerMessengerSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/DatabaseServerMessengerSettings.cs @@ -10,9 +10,24 @@ namespace Umbraco.Cms.Core.Configuration.Models; /// public class DatabaseServerMessengerSettings { + /// + /// The default maximum number of processing instructions. + /// internal const int StaticMaxProcessingInstructionCount = 1000; + + /// + /// The default time to retain instructions in the database. + /// internal const string StaticTimeToRetainInstructions = "2.00:00:00"; // TimeSpan.FromDays(2); + + /// + /// The default time between sync operations. + /// internal const string StaticTimeBetweenSyncOperations = "00:00:05"; // TimeSpan.FromSeconds(5); + + /// + /// The default time between prune operations. + /// internal const string StaticTimeBetweenPruneOperations = "00:01:00"; // TimeSpan.FromMinutes(1); /// diff --git a/src/Umbraco.Core/Configuration/Models/DatabaseServerRegistrarSettings.cs b/src/Umbraco.Core/Configuration/Models/DatabaseServerRegistrarSettings.cs index 80aefeae6eec..76e4780f6f94 100644 --- a/src/Umbraco.Core/Configuration/Models/DatabaseServerRegistrarSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/DatabaseServerRegistrarSettings.cs @@ -10,7 +10,14 @@ namespace Umbraco.Cms.Core.Configuration.Models; /// public class DatabaseServerRegistrarSettings { + /// + /// The default time to wait between database calls. + /// internal const string StaticWaitTimeBetweenCalls = "00:01:00"; + + /// + /// The default timeout for considering a server stale. + /// internal const string StaticStaleServerTimeout = "00:02:00"; /// diff --git a/src/Umbraco.Core/Configuration/Models/DeliveryApiSettings.cs b/src/Umbraco.Core/Configuration/Models/DeliveryApiSettings.cs index 80353edcdd2b..9581cdc6a785 100644 --- a/src/Umbraco.Core/Configuration/Models/DeliveryApiSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/DeliveryApiSettings.cs @@ -1,4 +1,4 @@ -using System.ComponentModel; +using System.ComponentModel; namespace Umbraco.Cms.Core.Configuration.Models; @@ -225,9 +225,15 @@ public class ClientCredentialsFlowSettings [DefaultValue(StaticEnabled)] public bool Enabled { get; set; } = StaticEnabled; + /// + /// Gets or sets the collection of members associated with client credentials for authorization. + /// public IEnumerable AssociatedMembers { get; set; } = []; } + /// + /// Typed configuration options for Client Credentials Flow member association settings. + /// public class ClientCredentialsFlowMemberSettings { /// diff --git a/src/Umbraco.Core/Configuration/Models/DistributedJobSettings.cs b/src/Umbraco.Core/Configuration/Models/DistributedJobSettings.cs index af1417c067ea..90dfc76a7cb5 100644 --- a/src/Umbraco.Core/Configuration/Models/DistributedJobSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/DistributedJobSettings.cs @@ -1,4 +1,4 @@ -using System.ComponentModel; +using System.ComponentModel; namespace Umbraco.Cms.Core.Configuration.Models; @@ -8,8 +8,19 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigDistributedJobs)] public class DistributedJobSettings { + /// + /// The default period for checking if there are runnable distributed jobs. + /// internal const string StaticPeriod = "00:00:05"; + + /// + /// The default delay before starting to check for distributed jobs. + /// internal const string StaticDelay = "00:01:00"; + + /// + /// The default maximum execution time for a distributed job. + /// internal const string StaticMaxExecutionTime = "00:05:00"; /// diff --git a/src/Umbraco.Core/Configuration/Models/ExceptionFilterSettings.cs b/src/Umbraco.Core/Configuration/Models/ExceptionFilterSettings.cs index ebf99c03ddc0..44f7a3a88fd8 100644 --- a/src/Umbraco.Core/Configuration/Models/ExceptionFilterSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/ExceptionFilterSettings.cs @@ -11,6 +11,9 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigExceptionFilter)] public class ExceptionFilterSettings { + /// + /// The default value for whether the exception filter is disabled. + /// internal const bool StaticDisabled = false; /// diff --git a/src/Umbraco.Core/Configuration/Models/GlobalSettings.cs b/src/Umbraco.Core/Configuration/Models/GlobalSettings.cs index 1b71e5677cef..3f40dd3fb5db 100644 --- a/src/Umbraco.Core/Configuration/Models/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/GlobalSettings.cs @@ -11,25 +11,89 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigGlobal)] public class GlobalSettings { - internal const string - StaticReservedPaths = - "~/app_plugins/,~/install/,~/mini-profiler-resources/,~/umbraco/,"; // must end with a comma! + /// + /// The default value for the setting. + /// + /// Must end with a comma. + internal const string StaticReservedPaths = + "~/app_plugins/,~/install/,~/mini-profiler-resources/,~/umbraco/,"; - internal const string StaticReservedUrls = "~/.well-known,"; // must end with a comma! + /// + /// The default value for the setting. + /// + /// Must end with a comma. + internal const string StaticReservedUrls = "~/.well-known,"; + + /// + /// The default value for the setting. + /// internal const string StaticTimeOut = "00:20:00"; + + /// + /// The default value for the setting. + /// internal const string StaticDefaultUILanguage = "en-US"; + + /// + /// The default value for the setting. + /// internal const bool StaticHideTopLevelNodeFromPath = true; + + /// + /// The default value for the setting. + /// internal const bool StaticUseHttps = true; + + /// + /// The default value for the setting. + /// internal const int StaticVersionCheckPeriod = 7; + + /// + /// The default value for the setting. + /// internal const string StaticIconsPath = "umbraco/assets/icons"; + + /// + /// The default value for the setting. + /// internal const string StaticUmbracoCssPath = "~/css"; + + /// + /// The default value for the setting. + /// internal const string StaticUmbracoScriptsPath = "~/scripts"; + + /// + /// The default value for the setting. + /// internal const string StaticUmbracoMediaPath = "~/media"; + + /// + /// The default value for the setting. + /// internal const bool StaticDisableElectionForSingleServer = false; + + /// + /// The default value for the setting. + /// internal const string StaticNoNodesViewPath = "~/umbraco/UmbracoWebsite/NoNodes.cshtml"; + + /// + /// The default value for the setting. + /// internal const string StaticDistributedLockingReadLockDefaultTimeout = "00:01:00"; + + /// + /// The default value for the setting. + /// internal const string StaticDistributedLockingWriteLockDefaultTimeout = "00:00:05"; + + /// + /// The default value for the setting. + /// internal const int StaticMainDomReleaseSignalPollingInterval = 2000; + private const bool StaticForceCombineUrlPathLeftToRight = true; private const bool StaticShowMaintenancePageWhenInUpgradeState = true; @@ -234,6 +298,9 @@ internal const string [DefaultValue(StaticForceCombineUrlPathLeftToRight)] public bool ForceCombineUrlPathLeftToRight { get; set; } = StaticForceCombineUrlPathLeftToRight; + /// + /// Gets or sets a value indicating whether to show the maintenance page when in an upgrade state. + /// [DefaultValue(StaticShowMaintenancePageWhenInUpgradeState)] public bool ShowMaintenancePageWhenInUpgradeState { get; set; } = StaticShowMaintenancePageWhenInUpgradeState; } diff --git a/src/Umbraco.Core/Configuration/Models/HealthChecksNotificationMethodSettings.cs b/src/Umbraco.Core/Configuration/Models/HealthChecksNotificationMethodSettings.cs index 00b3f56583f5..00d509d2efde 100644 --- a/src/Umbraco.Core/Configuration/Models/HealthChecksNotificationMethodSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/HealthChecksNotificationMethodSettings.cs @@ -11,8 +11,19 @@ namespace Umbraco.Cms.Core.Configuration.Models; /// public class HealthChecksNotificationMethodSettings { + /// + /// The default value for whether the notification method is enabled. + /// internal const bool StaticEnabled = false; + + /// + /// The default verbosity level for health check notifications. + /// internal const string StaticVerbosity = "Summary"; // Enum + + /// + /// The default value for sending notifications only on failure. + /// internal const bool StaticFailureOnly = false; /// diff --git a/src/Umbraco.Core/Configuration/Models/HealthChecksNotificationSettings.cs b/src/Umbraco.Core/Configuration/Models/HealthChecksNotificationSettings.cs index e72a6674a4f6..6cfd32df1688 100644 --- a/src/Umbraco.Core/Configuration/Models/HealthChecksNotificationSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/HealthChecksNotificationSettings.cs @@ -10,7 +10,14 @@ namespace Umbraco.Cms.Core.Configuration.Models; /// public class HealthChecksNotificationSettings { + /// + /// The default value for whether health check notifications are enabled. + /// internal const bool StaticEnabled = false; + + /// + /// The default period between health check notifications. + /// internal const string StaticPeriod = "1.00:00:00"; // TimeSpan.FromHours(24); /// diff --git a/src/Umbraco.Core/Configuration/Models/HelpPageSettings.cs b/src/Umbraco.Core/Configuration/Models/HelpPageSettings.cs index 6bad1eb973e5..ca1bc2aa9d41 100644 --- a/src/Umbraco.Core/Configuration/Models/HelpPageSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/HelpPageSettings.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Configuration.Models; +/// +/// Typed configuration options for help page settings. +/// [UmbracoOptions(Constants.Configuration.ConfigHelpPage)] public class HelpPageSettings { diff --git a/src/Umbraco.Core/Configuration/Models/HostingSettings.cs b/src/Umbraco.Core/Configuration/Models/HostingSettings.cs index 99c1aa5649a9..4029446a8b58 100644 --- a/src/Umbraco.Core/Configuration/Models/HostingSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/HostingSettings.cs @@ -11,7 +11,14 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigHosting)] public class HostingSettings { + /// + /// The default local temporary storage location. + /// internal const string StaticLocalTempStorageLocation = "Default"; + + /// + /// The default value for debug mode. + /// internal const bool StaticDebug = false; /// diff --git a/src/Umbraco.Core/Configuration/Models/ImagingCacheSettings.cs b/src/Umbraco.Core/Configuration/Models/ImagingCacheSettings.cs index a433c5d3009d..5a4c485fd8c5 100644 --- a/src/Umbraco.Core/Configuration/Models/ImagingCacheSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/ImagingCacheSettings.cs @@ -10,10 +10,29 @@ namespace Umbraco.Cms.Core.Configuration.Models; /// public class ImagingCacheSettings { + /// + /// The default browser cache maximum age. + /// internal const string StaticBrowserMaxAge = "7.00:00:00"; + + /// + /// The default image cache maximum age. + /// internal const string StaticCacheMaxAge = "365.00:00:00"; + + /// + /// The default image cache hash length. + /// internal const int StaticCacheHashLength = 12; + + /// + /// The default image cache folder depth. + /// internal const int StaticCacheFolderDepth = 8; + + /// + /// The default image cache folder path. + /// internal const string StaticCacheFolder = Constants.SystemDirectories.TempData + "/MediaCache"; /// diff --git a/src/Umbraco.Core/Configuration/Models/ImagingResizeSettings.cs b/src/Umbraco.Core/Configuration/Models/ImagingResizeSettings.cs index 2ae7d855be5b..50e9ce523266 100644 --- a/src/Umbraco.Core/Configuration/Models/ImagingResizeSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/ImagingResizeSettings.cs @@ -10,7 +10,14 @@ namespace Umbraco.Cms.Core.Configuration.Models; /// public class ImagingResizeSettings { + /// + /// The default maximum width for image resizing. + /// internal const int StaticMaxWidth = 5000; + + /// + /// The default maximum height for image resizing. + /// internal const int StaticMaxHeight = 5000; /// diff --git a/src/Umbraco.Core/Configuration/Models/LoggingSettings.cs b/src/Umbraco.Core/Configuration/Models/LoggingSettings.cs index 33e4ed299e6d..a0c188240527 100644 --- a/src/Umbraco.Core/Configuration/Models/LoggingSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/LoggingSettings.cs @@ -12,9 +12,24 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigLogging)] public class LoggingSettings { + /// + /// The default maximum age for log files. + /// internal const string StaticMaxLogAge = "1.00:00:00"; // TimeSpan.FromHours(24); + + /// + /// The default directory for log files. + /// internal const string StaticDirectory = Constants.SystemDirectories.LogFiles; + + /// + /// The default file name format for log files. + /// internal const string StaticFileNameFormat = LoggingConfiguration.DefaultLogFileNameFormat; + + /// + /// The default file name format arguments for log files. + /// internal const string StaticFileNameFormatArguments = "MachineName"; /// diff --git a/src/Umbraco.Core/Configuration/Models/LuceneDirectoryFactory.cs b/src/Umbraco.Core/Configuration/Models/LuceneDirectoryFactory.cs index 3b0e974c089b..3a000c149cd6 100644 --- a/src/Umbraco.Core/Configuration/Models/LuceneDirectoryFactory.cs +++ b/src/Umbraco.Core/Configuration/Models/LuceneDirectoryFactory.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Configuration.Models; +/// +/// Specifies the Lucene directory factory type for Examine indexes. +/// public enum LuceneDirectoryFactory { /// diff --git a/src/Umbraco.Core/Configuration/Models/MemberPasswordConfigurationSettings.cs b/src/Umbraco.Core/Configuration/Models/MemberPasswordConfigurationSettings.cs index 1e884a150f28..ff73fc205602 100644 --- a/src/Umbraco.Core/Configuration/Models/MemberPasswordConfigurationSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/MemberPasswordConfigurationSettings.cs @@ -11,11 +11,34 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigMemberPassword)] public class MemberPasswordConfigurationSettings : IPasswordConfiguration { + /// + /// The default minimum required password length. + /// internal const int StaticRequiredLength = 10; + + /// + /// The default value for requiring non-letter or digit characters. + /// internal const bool StaticRequireNonLetterOrDigit = false; + + /// + /// The default value for requiring digit characters. + /// internal const bool StaticRequireDigit = false; + + /// + /// The default value for requiring lowercase characters. + /// internal const bool StaticRequireLowercase = false; + + /// + /// The default value for requiring uppercase characters. + /// internal const bool StaticRequireUppercase = false; + + /// + /// The default maximum failed access attempts before lockout. + /// internal const int StaticMaxFailedAccessAttemptsBeforeLockout = 5; /// diff --git a/src/Umbraco.Core/Configuration/Models/ModelsBuilderSettings.cs b/src/Umbraco.Core/Configuration/Models/ModelsBuilderSettings.cs index 3db8e4e0cb6d..4c66bef9e575 100644 --- a/src/Umbraco.Core/Configuration/Models/ModelsBuilderSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/ModelsBuilderSettings.cs @@ -12,12 +12,36 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigModelsBuilder, BindNonPublicProperties = true)] public class ModelsBuilderSettings { + /// + /// The default models mode. + /// internal const string StaticModelsMode = "InMemoryAuto"; + + /// + /// The default models directory path. + /// internal const string StaticModelsDirectory = "~/umbraco/models"; + + /// + /// The default value for accepting unsafe models directory. + /// internal const bool StaticAcceptUnsafeModelsDirectory = false; + + /// + /// The default debug level. + /// internal const int StaticDebugLevel = 0; + + /// + /// The default value for including version number in generated models. + /// internal const bool StaticIncludeVersionNumberInGeneratedModels = true; + + /// + /// The default value for generating virtual properties. + /// internal const bool StaticGenerateVirtualProperties = true; + private bool _flagOutOfDateModels = true; /// diff --git a/src/Umbraco.Core/Configuration/Models/NuCacheSettings.cs b/src/Umbraco.Core/Configuration/Models/NuCacheSettings.cs index 9a40e1d08083..3450383d5cff 100644 --- a/src/Umbraco.Core/Configuration/Models/NuCacheSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/NuCacheSettings.cs @@ -11,8 +11,19 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigNuCache)] public class NuCacheSettings { + /// + /// The default serializer type for NuCache. + /// internal const string StaticNuCacheSerializerType = "MessagePack"; + + /// + /// The default SQL page size for NuCache queries. + /// internal const int StaticSqlPageSize = 1000; + + /// + /// The default value for using paged SQL queries. + /// internal const bool StaticUsePagedSqlQuery = true; /// @@ -27,6 +38,9 @@ public class NuCacheSettings [DefaultValue(StaticSqlPageSize)] public int SqlPageSize { get; set; } = StaticSqlPageSize; + /// + /// Gets or sets a value indicating whether to use paged SQL queries for nucache. + /// [DefaultValue(StaticUsePagedSqlQuery)] public bool UsePagedSqlQuery { get; set; } = true; } diff --git a/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs b/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs index 0383f1a87c46..de77a847c2b6 100644 --- a/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs @@ -12,11 +12,29 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigRequestHandler)] public class RequestHandlerSettings { + /// + /// The default value for adding a trailing slash to URLs. + /// internal const bool StaticAddTrailingSlash = true; + + /// + /// The default value for converting URLs to ASCII. + /// internal const string StaticConvertUrlsToAscii = "try"; + + /// + /// The default value for converting file names to ASCII. + /// internal const string StaticConvertFileNamesToAscii = "false"; + + /// + /// The default value for enabling default character replacements. + /// internal const bool StaticEnableDefaultCharReplacements = true; + /// + /// The default collection of character replacements for URL generation. + /// internal static readonly CharItem[] DefaultCharCollection = { new() { Char = " ", Replacement = "-" }, diff --git a/src/Umbraco.Core/Configuration/Models/SecuritySettings.cs b/src/Umbraco.Core/Configuration/Models/SecuritySettings.cs index 0602ab6e8ea3..96af59eab201 100644 --- a/src/Umbraco.Core/Configuration/Models/SecuritySettings.cs +++ b/src/Umbraco.Core/Configuration/Models/SecuritySettings.cs @@ -12,29 +12,105 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigSecurity)] public class SecuritySettings { + /// + /// The default value for bypassing two-factor authentication for external member logins. + /// internal const bool StaticMemberBypassTwoFactorForExternalLogins = true; + + /// + /// The default value for bypassing two-factor authentication for external user logins. + /// internal const bool StaticUserBypassTwoFactorForExternalLogins = true; + + /// + /// The default value for keeping users logged in. + /// internal const bool StaticKeepUserLoggedIn = false; + + /// + /// The default value for hiding disabled users in the back-office. + /// internal const bool StaticHideDisabledUsersInBackOffice = false; + + /// + /// The default value for allowing password reset. + /// internal const bool StaticAllowPasswordReset = true; + + /// + /// The default value for allowing edit of invariant properties from non-default language. + /// internal const bool StaticAllowEditInvariantFromNonDefault = false; + + /// + /// The default value for allowing concurrent logins. + /// internal const bool StaticAllowConcurrentLogins = false; + + /// + /// The default authentication cookie name. + /// internal const string StaticAuthCookieName = "UMB_UCONTEXT"; + + /// + /// The default value for using email as username. + /// internal const bool StaticUsernameIsEmail = true; + + /// + /// The default value for requiring unique email for members. + /// internal const bool StaticMemberRequireUniqueEmail = true; + /// + /// The default set of allowed characters for usernames. + /// internal const string StaticAllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+\\"; + /// + /// The default member lockout time in minutes. + /// internal const int StaticMemberDefaultLockoutTimeInMinutes = 30 * 24 * 60; + + /// + /// The default user lockout time in minutes. + /// internal const int StaticUserDefaultLockoutTimeInMinutes = 30 * 24 * 60; + + /// + /// The default duration in milliseconds for failed login attempts. + /// internal const long StaticUserDefaultFailedLoginDurationInMilliseconds = 1000; + + /// + /// The minimum duration in milliseconds for failed login attempts. + /// internal const long StaticUserMinimumFailedLoginDurationInMilliseconds = 250; + + /// + /// The default path for the authorization callback. + /// internal const string StaticAuthorizeCallbackPathName = "/umbraco/oauth_complete"; + + /// + /// The default path for the authorization callback logout. + /// internal const string StaticAuthorizeCallbackLogoutPathName = "/umbraco/logout"; + + /// + /// The default path for the authorization callback error. + /// internal const string StaticAuthorizeCallbackErrorPathName = "/umbraco/error"; + /// + /// The default expiry time for password reset emails. + /// internal const string StaticPasswordResetEmailExpiry = "01:00:00"; + + /// + /// The default expiry time for user invite emails. + /// internal const string StaticUserInviteEmailExpiry = "3.00:00:00"; /// diff --git a/src/Umbraco.Core/Configuration/Models/SmtpSettings.cs b/src/Umbraco.Core/Configuration/Models/SmtpSettings.cs index ea56445aa28e..4d2a2bb13c98 100644 --- a/src/Umbraco.Core/Configuration/Models/SmtpSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/SmtpSettings.cs @@ -50,7 +50,14 @@ public enum SecureSocketOptions /// public class SmtpSettings : ValidatableEntryBase { + /// + /// The default secure socket options for SMTP. + /// internal const string StaticSecureSocketOptions = "Auto"; + + /// + /// The default SMTP delivery method. + /// internal const string StaticDeliveryMethod = "Network"; /// diff --git a/src/Umbraco.Core/Configuration/Models/TinyMceToTiptapMigrationSettings.cs b/src/Umbraco.Core/Configuration/Models/TinyMceToTiptapMigrationSettings.cs index 002a0ca3a3f0..c38f2d6e81c9 100644 --- a/src/Umbraco.Core/Configuration/Models/TinyMceToTiptapMigrationSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/TinyMceToTiptapMigrationSettings.cs @@ -1,6 +1,12 @@ namespace Umbraco.Cms.Core.Configuration.Models; +/// +/// Typed configuration options for TinyMCE to Tiptap editor migration settings. +/// public class TinyMceToTiptapMigrationSettings { + /// + /// Gets or sets a value indicating whether the migration from TinyMCE to Tiptap is disabled. + /// public bool DisableMigration { get; set; } } diff --git a/src/Umbraco.Core/Configuration/Models/UserPasswordConfigurationSettings.cs b/src/Umbraco.Core/Configuration/Models/UserPasswordConfigurationSettings.cs index d21d5c679dae..dbeb4aee727d 100644 --- a/src/Umbraco.Core/Configuration/Models/UserPasswordConfigurationSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/UserPasswordConfigurationSettings.cs @@ -11,12 +11,39 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigUserPassword)] public class UserPasswordConfigurationSettings : IPasswordConfiguration { + /// + /// The default minimum required password length. + /// internal const int StaticRequiredLength = 10; + + /// + /// The default value for requiring non-letter or digit characters. + /// internal const bool StaticRequireNonLetterOrDigit = false; + + /// + /// The default value for requiring digit characters. + /// internal const bool StaticRequireDigit = false; + + /// + /// The default value for requiring lowercase characters. + /// internal const bool StaticRequireLowercase = false; + + /// + /// The default value for requiring uppercase characters. + /// internal const bool StaticRequireUppercase = false; + + /// + /// The default maximum failed access attempts before lockout. + /// internal const int StaticMaxFailedAccessAttemptsBeforeLockout = 5; + + /// + /// The default minimum response time for forgot password requests. + /// internal const string StaticMinimumResponseTime = "0.00:00:02"; /// diff --git a/src/Umbraco.Core/Configuration/Models/Validation/DeliveryApiSettingsValidator.cs b/src/Umbraco.Core/Configuration/Models/Validation/DeliveryApiSettingsValidator.cs index 05074690c006..d501da5fc19f 100644 --- a/src/Umbraco.Core/Configuration/Models/Validation/DeliveryApiSettingsValidator.cs +++ b/src/Umbraco.Core/Configuration/Models/Validation/DeliveryApiSettingsValidator.cs @@ -14,6 +14,10 @@ public class DeliveryApiSettingsValidator : IValidateOptions _logger; + /// + /// Initializes a new instance of the class. + /// + /// The logger. public DeliveryApiSettingsValidator(ILogger logger) => _logger = logger; diff --git a/src/Umbraco.Core/Configuration/Models/Validation/SecuritySettingsValidator.cs b/src/Umbraco.Core/Configuration/Models/Validation/SecuritySettingsValidator.cs index 3df30bbd03cd..7796c69652a6 100644 --- a/src/Umbraco.Core/Configuration/Models/Validation/SecuritySettingsValidator.cs +++ b/src/Umbraco.Core/Configuration/Models/Validation/SecuritySettingsValidator.cs @@ -1,9 +1,13 @@ -using Microsoft.Extensions.Options; +using Microsoft.Extensions.Options; namespace Umbraco.Cms.Core.Configuration.Models.Validation; +/// +/// Validator for configuration represented as . +/// public class SecuritySettingsValidator : ConfigurationValidatorBase, IValidateOptions { + /// public ValidateOptionsResult Validate(string? name, SecuritySettings options) { if (options.BackOfficeHost != null) diff --git a/src/Umbraco.Core/Configuration/Models/Validation/ValidatableEntryBase.cs b/src/Umbraco.Core/Configuration/Models/Validation/ValidatableEntryBase.cs index ff858943ac49..757145905af2 100644 --- a/src/Umbraco.Core/Configuration/Models/Validation/ValidatableEntryBase.cs +++ b/src/Umbraco.Core/Configuration/Models/Validation/ValidatableEntryBase.cs @@ -10,6 +10,10 @@ namespace Umbraco.Cms.Core.Configuration.Models.Validation; /// public abstract class ValidatableEntryBase { + /// + /// Validates the configuration entry using data annotations. + /// + /// true if the entry is valid; otherwise, false. internal virtual bool IsValid() { var ctx = new ValidationContext(this); diff --git a/src/Umbraco.Core/Configuration/Models/WebRoutingSettings.cs b/src/Umbraco.Core/Configuration/Models/WebRoutingSettings.cs index e91074ee530e..656a27fe9b86 100644 --- a/src/Umbraco.Core/Configuration/Models/WebRoutingSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/WebRoutingSettings.cs @@ -12,15 +12,54 @@ namespace Umbraco.Cms.Core.Configuration.Models; [UmbracoOptions(Constants.Configuration.ConfigWebRouting)] public class WebRoutingSettings { + /// + /// The default value for trying to match endpoints for all pages. + /// internal const bool StaticTryMatchingEndpointsForAllPages = false; + + /// + /// The default value for trying to skip IIS custom errors. + /// internal const bool StaticTrySkipIisCustomErrors = false; + + /// + /// The default value for preserving template on internal redirect. + /// internal const bool StaticInternalRedirectPreservesTemplate = false; + + /// + /// The default value for disabling alternative templates. + /// internal const bool StaticDisableAlternativeTemplates = false; + + /// + /// The default value for validating alternative templates. + /// internal const bool StaticValidateAlternativeTemplates = false; + + /// + /// The default value for disabling find content by ID path. + /// internal const bool StaticDisableFindContentByIdPath = false; + + /// + /// The default value for disabling find content by identifier path. + /// internal const bool StaticDisableFindContentByIdentifierPath = false; + + /// + /// The default value for disabling redirect URL tracking. + /// internal const bool StaticDisableRedirectUrlTracking = false; + + /// + /// The default URL provider mode. + /// internal const string StaticUrlProviderMode = "Auto"; + + /// + /// The default value for using strict domain matching. + /// internal const bool StaticUseStrictDomainMatching = false; /// diff --git a/src/Umbraco.Core/Configuration/Models/WebhookSettings.cs b/src/Umbraco.Core/Configuration/Models/WebhookSettings.cs index caa9f41717b0..c2fea2ade2c3 100644 --- a/src/Umbraco.Core/Configuration/Models/WebhookSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/WebhookSettings.cs @@ -3,12 +3,20 @@ namespace Umbraco.Cms.Core.Configuration.Models; +/// +/// Typed configuration options for webhook settings. +/// [UmbracoOptions(Constants.Configuration.ConfigWebhook)] public class WebhookSettings { private const bool StaticEnabled = true; private const int StaticMaximumRetries = 5; + + /// + /// The default value for the setting. + /// internal const string StaticPeriod = "00:00:10"; + private const bool StaticEnableLoggingCleanup = true; private const int StaticKeepLogsForDays = 30; private const WebhookPayloadType StaticPayloadType = Constants.Webhooks.DefaultPayloadType; diff --git a/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs b/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs index b8ad9f099cc4..333aa52014db 100644 --- a/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs +++ b/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs @@ -5,10 +5,19 @@ namespace Umbraco.Extensions; +/// +/// Extension methods for . +/// public static class ModelsBuilderConfigExtensions { private static string? _modelsDirectoryAbsolute; + /// + /// Gets the absolute path to the models directory. + /// + /// The models builder configuration. + /// The host environment. + /// The absolute path to the models directory. public static string ModelsDirectoryAbsolute( this ModelsBuilderSettings modelsBuilderConfig, IHostEnvironment hostEnvironment) @@ -24,7 +33,14 @@ public static string ModelsDirectoryAbsolute( return _modelsDirectoryAbsolute; } - // internal for tests + /// + /// Gets the models directory from the configuration. + /// + /// The root path. + /// The configured models directory. + /// Whether to accept unsafe directory paths. + /// The absolute path to the models directory. + /// Internal for tests. internal static string GetModelsDirectory(string root, string config, bool acceptUnsafe) { // making sure it is safe, ie under the website root, diff --git a/src/Umbraco.Core/Configuration/PasswordConfiguration.cs b/src/Umbraco.Core/Configuration/PasswordConfiguration.cs index 4c7472086081..ebeada1e1f81 100644 --- a/src/Umbraco.Core/Configuration/PasswordConfiguration.cs +++ b/src/Umbraco.Core/Configuration/PasswordConfiguration.cs @@ -1,7 +1,15 @@ namespace Umbraco.Cms.Core.Configuration; +/// +/// Abstract base class for password configuration. +/// public abstract class PasswordConfiguration : IPasswordConfiguration { + /// + /// Initializes a new instance of the class. + /// + /// The password configuration settings. + /// Thrown when is null. protected PasswordConfiguration(IPasswordConfiguration configSettings) { if (configSettings == null) @@ -18,17 +26,24 @@ protected PasswordConfiguration(IPasswordConfiguration configSettings) MaxFailedAccessAttemptsBeforeLockout = configSettings.MaxFailedAccessAttemptsBeforeLockout; } + /// public int RequiredLength { get; } + /// public bool RequireNonLetterOrDigit { get; } + /// public bool RequireDigit { get; } + /// public bool RequireLowercase { get; } + /// public bool RequireUppercase { get; } + /// public string HashAlgorithmType { get; } + /// public int MaxFailedAccessAttemptsBeforeLockout { get; } } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/CharacterReplacementEqualityComparer.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/CharacterReplacementEqualityComparer.cs index 8740b81cb5b9..c342fd0e80f6 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/CharacterReplacementEqualityComparer.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/CharacterReplacementEqualityComparer.cs @@ -1,7 +1,11 @@ namespace Umbraco.Cms.Core.Configuration.UmbracoSettings; +/// +/// Provides equality comparison for instances based on character and replacement values. +/// public class CharacterReplacementEqualityComparer : IEqualityComparer { + /// public bool Equals(IChar? x, IChar? y) { if (ReferenceEquals(x, y)) @@ -27,6 +31,7 @@ public bool Equals(IChar? x, IChar? y) return x.Char == y.Char && x.Replacement == y.Replacement; } + /// public int GetHashCode(IChar obj) { unchecked diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IChar.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IChar.cs index a2ba30b776bc..2da74625fae6 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IChar.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IChar.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.Configuration.UmbracoSettings; +/// +/// Defines a character replacement mapping for URL slug generation. +/// public interface IChar { + /// + /// Gets the character to be replaced. + /// string Char { get; } + /// + /// Gets the replacement string. + /// string Replacement { get; } } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IImagingAutoFillUploadField.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IImagingAutoFillUploadField.cs index f6431dd77a0e..74df3cad13b4 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IImagingAutoFillUploadField.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IImagingAutoFillUploadField.cs @@ -1,17 +1,35 @@ namespace Umbraco.Cms.Core.Configuration.UmbracoSettings; +/// +/// Defines the configuration for auto-filling image properties on media upload. +/// public interface IImagingAutoFillUploadField { /// - /// Allow setting internally so we can create a default + /// Gets the property alias that triggers the auto-fill behavior. /// + /// + /// Allow setting internally so we can create a default. + /// string Alias { get; } + /// + /// Gets the alias of the property to store the image width. + /// string WidthFieldAlias { get; } + /// + /// Gets the alias of the property to store the image height. + /// string HeightFieldAlias { get; } + /// + /// Gets the alias of the property to store the file size in bytes. + /// string LengthFieldAlias { get; } + /// + /// Gets the alias of the property to store the file extension. + /// string ExtensionFieldAlias { get; } } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IPasswordConfigurationSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IPasswordConfigurationSection.cs index 7a309d6fe34d..a63256b34438 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IPasswordConfigurationSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IPasswordConfigurationSection.cs @@ -1,20 +1,47 @@ namespace Umbraco.Cms.Core.Configuration.UmbracoSettings; +/// +/// Defines the password configuration section settings. +/// public interface IPasswordConfigurationSection : IUmbracoConfigurationSection { + /// + /// Gets the minimum required length for passwords. + /// int RequiredLength { get; } + /// + /// Gets a value indicating whether passwords must contain at least one non-letter or digit character. + /// bool RequireNonLetterOrDigit { get; } + /// + /// Gets a value indicating whether passwords must contain at least one digit. + /// bool RequireDigit { get; } + /// + /// Gets a value indicating whether passwords must contain at least one lowercase character. + /// bool RequireLowercase { get; } + /// + /// Gets a value indicating whether passwords must contain at least one uppercase character. + /// bool RequireUppercase { get; } + /// + /// Gets a value indicating whether to use legacy password encoding. + /// bool UseLegacyEncoding { get; } + /// + /// Gets the hash algorithm type used for password hashing. + /// string HashAlgorithmType { get; } + /// + /// Gets the maximum number of failed access attempts before the account is locked out. + /// int MaxFailedAccessAttemptsBeforeLockout { get; } } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ITypeFinderConfig.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ITypeFinderConfig.cs index 1dfde6414f8b..f4cabdec2b8d 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ITypeFinderConfig.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ITypeFinderConfig.cs @@ -1,6 +1,12 @@ namespace Umbraco.Cms.Core.Configuration.UmbracoSettings; +/// +/// Defines configuration for the type finder used during assembly scanning. +/// public interface ITypeFinderConfig { + /// + /// Gets the collection of assembly names that should accept load exceptions during type scanning. + /// IEnumerable AssembliesAcceptingLoadExceptions { get; } } diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index 9664d7cb7330..a6438fa17514 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -9,6 +9,9 @@ namespace Umbraco.Cms.Core.Configuration; /// public class UmbracoVersion : IUmbracoVersion { + /// + /// Initializes a new instance of the class. + /// public UmbracoVersion() { Assembly umbracoCoreAssembly = typeof(SemVersion).Assembly; diff --git a/src/Umbraco.Core/Configuration/UserPasswordConfiguration.cs b/src/Umbraco.Core/Configuration/UserPasswordConfiguration.cs index 47b950de9cfe..887608ff95ec 100644 --- a/src/Umbraco.Core/Configuration/UserPasswordConfiguration.cs +++ b/src/Umbraco.Core/Configuration/UserPasswordConfiguration.cs @@ -1,10 +1,14 @@ namespace Umbraco.Cms.Core.Configuration; /// -/// The password configuration for back office users +/// The password configuration for back office users. /// public class UserPasswordConfiguration : PasswordConfiguration, IUserPasswordConfiguration { + /// + /// Initializes a new instance of the class. + /// + /// The user password configuration settings. public UserPasswordConfiguration(IUserPasswordConfiguration configSettings) : base(configSettings) { diff --git a/src/Umbraco.Core/Constants-Applications.cs b/src/Umbraco.Core/Constants-Applications.cs index 4a53ff455f54..243eb030b0e7 100644 --- a/src/Umbraco.Core/Constants-Applications.cs +++ b/src/Umbraco.Core/Constants-Applications.cs @@ -88,6 +88,9 @@ public static class Trees /// public const string Dictionary = "dictionary"; + /// + /// Alias for the stylesheets tree. + /// public const string Stylesheets = "stylesheets"; /// @@ -115,8 +118,14 @@ public static class Trees /// public const string Templates = "templates"; + /// + /// Alias for the relation types tree. + /// public const string RelationTypes = "relationTypes"; + /// + /// Alias for the languages tree. + /// public const string Languages = "languages"; /// @@ -134,20 +143,44 @@ public static class Trees /// public const string Users = "users"; + /// + /// Alias for the scripts tree. + /// public const string Scripts = "scripts"; + /// + /// Alias for the partial views tree. + /// public const string PartialViews = "partialViews"; + /// + /// Alias for the log viewer tree. + /// public const string LogViewer = "logViewer"; + /// + /// Alias for the webhooks tree. + /// public const string Webhooks = "webhooks"; + /// + /// Contains tree group aliases. + /// public static class Groups { + /// + /// The settings tree group alias. + /// public const string Settings = "settingsGroup"; + /// + /// The templating tree group alias. + /// public const string Templating = "templatingGroup"; + /// + /// The third party tree group alias. + /// public const string ThirdParty = "thirdPartyGroup"; } diff --git a/src/Umbraco.Core/Constants-Audit.cs b/src/Umbraco.Core/Constants-Audit.cs index f795a259749b..b4a52f3310d9 100644 --- a/src/Umbraco.Core/Constants-Audit.cs +++ b/src/Umbraco.Core/Constants-Audit.cs @@ -2,10 +2,24 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains constants for audit logging. + /// public static class Audit { + /// + /// The maximum length for IP address fields in audit logs. + /// public const int IpLength = 64; + + /// + /// The maximum length for event type fields in audit logs. + /// public const int EventTypeLength = 256; + + /// + /// The maximum length for details fields in audit logs. + /// public const int DetailsLength = 1024; } } diff --git a/src/Umbraco.Core/Constants-Cache.cs b/src/Umbraco.Core/Constants-Cache.cs index 874605c12314..7336ea341b9b 100644 --- a/src/Umbraco.Core/Constants-Cache.cs +++ b/src/Umbraco.Core/Constants-Cache.cs @@ -1,12 +1,25 @@ namespace Umbraco.Cms.Core; + public static partial class Constants { + /// + /// Contains constants for caching. + /// public static class Cache { + /// + /// Contains cache tag constants used for cache invalidation. + /// public static class Tags { + /// + /// The cache tag for content items. + /// public const string Content = "content"; + /// + /// The cache tag for media items. + /// public const string Media = "media"; } diff --git a/src/Umbraco.Core/Constants-Composing.cs b/src/Umbraco.Core/Constants-Composing.cs index f5598c1795cf..91e54e2cdab4 100644 --- a/src/Umbraco.Core/Constants-Composing.cs +++ b/src/Umbraco.Core/Constants-Composing.cs @@ -10,6 +10,9 @@ public static partial class Constants /// public static class Composing { + /// + /// The array of Umbraco core assembly names used for type discovery. + /// public static readonly string[] UmbracoCoreAssemblyNames = { "Umbraco.Core", "Umbraco.Infrastructure", "Umbraco.Examine.Lucene", diff --git a/src/Umbraco.Core/Constants-Configuration.cs b/src/Umbraco.Core/Constants-Configuration.cs index 02236f2cf98c..2ba15cf4a973 100644 --- a/src/Umbraco.Core/Constants-Configuration.cs +++ b/src/Umbraco.Core/Constants-Configuration.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains configuration key constants for Umbraco settings. + /// public static class Configuration { /// @@ -11,74 +14,316 @@ public static class Configuration /// ":" is used as marker for nested objects in JSON, e.g. "Umbraco:CMS:" = {"Umbraco":{"CMS":{...}}. /// public const string ConfigPrefix = "Umbraco:CMS:"; + + /// + /// The configuration key prefix for content settings. + /// public const string ConfigContentPrefix = ConfigPrefix + "Content:"; + + /// + /// The configuration key prefix for content notification settings. + /// public const string ConfigContentNotificationsPrefix = ConfigContentPrefix + "Notifications:"; + + /// + /// The configuration key prefix for core settings. + /// public const string ConfigCorePrefix = ConfigPrefix + "Core:"; + + /// + /// The configuration key prefix for custom error settings. + /// public const string ConfigCustomErrorsPrefix = ConfigPrefix + "CustomErrors:"; + + /// + /// The configuration key prefix for global settings. + /// public const string ConfigGlobalPrefix = ConfigPrefix + "Global:"; + + /// + /// The configuration key for the global ID setting. + /// public const string ConfigGlobalId = ConfigGlobalPrefix + "Id"; + + /// + /// The configuration key for the distributed locking mechanism setting. + /// public const string ConfigGlobalDistributedLockingMechanism = ConfigGlobalPrefix + "DistributedLockingMechanism"; + + /// + /// The configuration key prefix for hosting settings. + /// public const string ConfigHostingPrefix = ConfigPrefix + "Hosting:"; + + /// + /// The configuration key prefix for ModelsBuilder settings. + /// public const string ConfigModelsBuilderPrefix = ConfigPrefix + "ModelsBuilder:"; + + /// + /// The configuration key prefix for security settings. + /// public const string ConfigSecurityPrefix = ConfigPrefix + "Security:"; + + /// + /// The configuration key for content notification email settings. + /// public const string ConfigContentNotificationsEmail = ConfigContentNotificationsPrefix + "Email"; + + /// + /// The configuration key for the global HTTPS setting. + /// public const string ConfigGlobalUseHttps = ConfigGlobalPrefix + "UseHttps"; + + /// + /// The configuration key for the hosting debug setting. + /// public const string ConfigHostingDebug = ConfigHostingPrefix + "Debug"; + + /// + /// The configuration key for the custom errors mode setting. + /// public const string ConfigCustomErrorsMode = ConfigCustomErrorsPrefix + "Mode"; + + /// + /// The configuration key for Active Directory settings. + /// public const string ConfigActiveDirectory = ConfigPrefix + "ActiveDirectory"; + + /// + /// The configuration key for Marketplace settings. + /// public const string ConfigMarketplace = ConfigPrefix + "Marketplace"; + + /// + /// The configuration key for legacy password migration settings. + /// public const string ConfigLegacyPasswordMigration = ConfigPrefix + "LegacyPasswordMigration"; + + /// + /// The configuration key for system date migration settings. + /// public const string ConfigSystemDateMigration = ConfigPrefix + "SystemDateMigration"; + + /// + /// The configuration key for content settings. + /// public const string ConfigContent = ConfigPrefix + "Content"; + + /// + /// The configuration key for Delivery API settings. + /// public const string ConfigDeliveryApi = ConfigPrefix + "DeliveryApi"; + + /// + /// The configuration key for core debug settings. + /// public const string ConfigCoreDebug = ConfigCorePrefix + "Debug"; + + /// + /// The configuration key for exception filter settings. + /// public const string ConfigExceptionFilter = ConfigPrefix + "ExceptionFilter"; + + /// + /// The configuration key for global settings. + /// public const string ConfigGlobal = ConfigPrefix + "Global"; + + /// + /// The configuration key for unattended installation settings. + /// public const string ConfigUnattended = ConfigPrefix + "Unattended"; + + /// + /// The configuration key for health check settings. + /// public const string ConfigHealthChecks = ConfigPrefix + "HealthChecks"; + + /// + /// The configuration key for hosting settings. + /// public const string ConfigHosting = ConfigPrefix + "Hosting"; + + /// + /// The configuration key for imaging settings. + /// public const string ConfigImaging = ConfigPrefix + "Imaging"; + + /// + /// The configuration key for Examine search settings. + /// public const string ConfigExamine = ConfigPrefix + "Examine"; + + /// + /// The configuration key for indexing settings. + /// public const string ConfigIndexing = ConfigPrefix + "Indexing"; + + /// + /// The configuration key for logging settings. + /// public const string ConfigLogging = ConfigPrefix + "Logging"; + + /// + /// The configuration key for long running operations settings. + /// public const string ConfigLongRunningOperations = ConfigPrefix + "LongRunningOperations"; + + /// + /// The configuration key for member password settings. + /// public const string ConfigMemberPassword = ConfigPrefix + "Security:MemberPassword"; + + /// + /// The configuration key for ModelsBuilder settings. + /// public const string ConfigModelsBuilder = ConfigPrefix + "ModelsBuilder"; + + /// + /// The configuration key for the ModelsBuilder mode setting. + /// public const string ConfigModelsMode = ConfigModelsBuilder + ":ModelsMode"; + + /// + /// The configuration key for NuCache settings. + /// public const string ConfigNuCache = ConfigPrefix + "NuCache"; + + /// + /// The configuration key for plugins settings. + /// public const string ConfigPlugins = ConfigPrefix + "Plugins"; + + /// + /// The configuration key for request handler settings. + /// public const string ConfigRequestHandler = ConfigPrefix + "RequestHandler"; + + /// + /// The configuration key for runtime settings. + /// public const string ConfigRuntime = ConfigPrefix + "Runtime"; + + /// + /// The configuration key for the runtime mode setting. + /// public const string ConfigRuntimeMode = ConfigRuntime + ":Mode"; + + /// + /// The configuration key for security settings. + /// public const string ConfigSecurity = ConfigPrefix + "Security"; + + /// + /// The configuration key for basic authentication settings. + /// public const string ConfigBasicAuth = ConfigPrefix + "BasicAuth"; + + /// + /// The configuration key for type finder settings. + /// public const string ConfigTypeFinder = ConfigPrefix + "TypeFinder"; + + /// + /// The configuration key for web routing settings. + /// public const string ConfigWebRouting = ConfigPrefix + "WebRouting"; + + /// + /// The configuration key for user password settings. + /// public const string ConfigUserPassword = ConfigPrefix + "Security:UserPassword"; + + /// + /// The configuration key for rich text editor settings. + /// public const string ConfigRichTextEditor = ConfigPrefix + "RichTextEditor"; + + /// + /// The configuration key for package migration settings. + /// public const string ConfigPackageMigration = ConfigPrefix + "PackageMigration"; + + /// + /// The configuration key for content dashboard settings. + /// [Obsolete("No longer used in Umbraco. Scheduled to be removed in Umbraco 19.")] public const string ConfigContentDashboard = ConfigPrefix + "ContentDashboard"; + + /// + /// The configuration key for help page settings. + /// public const string ConfigHelpPage = ConfigPrefix + "HelpPage"; + + /// + /// The configuration key for install default data settings. + /// public const string ConfigInstallDefaultData = ConfigPrefix + "InstallDefaultData"; + + /// + /// The configuration key for data types settings. + /// public const string ConfigDataTypes = ConfigPrefix + "DataTypes"; + + /// + /// The configuration key for package manifests settings. + /// public const string ConfigPackageManifests = ConfigPrefix + "PackageManifests"; + + /// + /// The configuration key for webhook settings. + /// public const string ConfigWebhook = ConfigPrefix + "Webhook"; + + /// + /// The configuration key for webhook payload type settings. + /// public const string ConfigWebhookPayloadType = ConfigWebhook + ":PayloadType"; + + /// + /// The configuration key for cache settings. + /// public const string ConfigCache = ConfigPrefix + "Cache"; + + /// + /// The configuration key for distributed jobs settings. + /// public const string ConfigDistributedJobs = ConfigPrefix + "DistributedJobs"; + + /// + /// The configuration key for backoffice token cookie settings. + /// public const string ConfigBackOfficeTokenCookie = ConfigSecurity + ":BackOfficeTokenCookie"; + /// + /// Contains constants for named options used in configuration. + /// public static class NamedOptions { + /// + /// Contains named option constants for install default data configuration. + /// public static class InstallDefaultData { + /// + /// The named option for languages default data. + /// public const string Languages = "Languages"; + /// + /// The named option for data types default data. + /// public const string DataTypes = "DataTypes"; + /// + /// The named option for media types default data. + /// public const string MediaTypes = "MediaTypes"; + /// + /// The named option for member types default data. + /// public const string MemberTypes = "MemberTypes"; } } diff --git a/src/Umbraco.Core/Constants-Conventions.cs b/src/Umbraco.Core/Constants-Conventions.cs index e117b42189ae..865aaed3cdd4 100644 --- a/src/Umbraco.Core/Constants-Conventions.cs +++ b/src/Umbraco.Core/Constants-Conventions.cs @@ -7,31 +7,87 @@ public static partial class Constants /// public static class Conventions { + /// + /// Contains constants related to database migrations. + /// public static class Migrations { + /// + /// The name of the Umbraco core upgrade plan. + /// public const string UmbracoUpgradePlanName = "Umbraco.Core"; + + /// + /// The name of the Umbraco core pre-migrations upgrade plan. + /// public const string UmbracoUpgradePlanPremigrationsName = "Umbraco.Core.Premigrations"; + + /// + /// The prefix used for key-value storage of upgrade state. + /// public const string KeyValuePrefix = "Umbraco.Core.Upgrader.State+"; + + /// + /// The key used to store the Umbraco upgrade plan state. + /// public const string UmbracoUpgradePlanKey = KeyValuePrefix + UmbracoUpgradePlanName; + + /// + /// The key used to store the Umbraco pre-migrations upgrade plan state. + /// public const string UmbracoUpgradePlanPremigrationsKey = KeyValuePrefix + UmbracoUpgradePlanPremigrationsName; } + /// + /// Contains constants for permission category identifiers. + /// public static class PermissionCategories { + /// + /// The content permission category. + /// public const string ContentCategory = "content"; + + /// + /// The administration permission category. + /// public const string AdministrationCategory = "administration"; + + /// + /// The structure permission category. + /// public const string StructureCategory = "structure"; + + /// + /// The other permission category. + /// public const string OtherCategory = "other"; } + /// + /// Contains constants for public access rule types. + /// public static class PublicAccess { + /// + /// The rule type for member username-based access. + /// public const string MemberUsernameRuleType = "MemberUsername"; + + /// + /// The rule type for member role-based access. + /// public const string MemberRoleRuleType = "MemberRole"; } + /// + /// Contains constants for data type naming conventions. + /// public static class DataTypes { + /// + /// The prefix used for list view data type names. + /// public const string ListViewPrefix = "List View - "; } @@ -183,6 +239,9 @@ public static class Member /// public const string Comments = "umbracoMemberComments"; + /// + /// The label for the Comments property. + /// public const string CommentsLabel = "Comments"; /// @@ -211,8 +270,14 @@ public static class MemberTypes /// public const string DefaultAlias = "Member"; + /// + /// The system default protect type alias. + /// public const string SystemDefaultProtectType = "_umbracoSystemDefaultProtectType"; + /// + /// The identifier for the all members list. + /// public const string AllMembersListId = "all-members"; } @@ -304,8 +369,14 @@ public static class RelationTypes // TODO: return a list of built in types so we can use that to prevent deletion in the UI } + /// + /// Contains constants for UDI (Umbraco Data Identifier) conventions. + /// public static class Udi { + /// + /// The prefix for all Umbraco Data Identifiers. + /// public const string Prefix = "umb://"; } diff --git a/src/Umbraco.Core/Constants-DataTypes.cs b/src/Umbraco.Core/Constants-DataTypes.cs index 654c884dbff6..df0fd46f39bd 100644 --- a/src/Umbraco.Core/Constants-DataTypes.cs +++ b/src/Umbraco.Core/Constants-DataTypes.cs @@ -2,42 +2,148 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains constants for built-in Umbraco data types. + /// public static class DataTypes { // NOTE: unfortunately due to backwards compat we can't move/rename these, with the addition of the GUID // constants, it would make more sense to have these suffixed with "ID" or in a Subclass called "INT", for // now all we can do is make a subclass called Guids to put the GUID IDs. + + /// + /// The integer ID for the Label (string) data type. + /// public const int LabelString = System.DefaultLabelDataTypeId; + + /// + /// The integer ID for the Label (integer) data type. + /// public const int LabelInt = -91; + + /// + /// The integer ID for the Label (big integer) data type. + /// public const int LabelBigint = -93; + + /// + /// The integer ID for the Label (date/time) data type. + /// public const int LabelDateTime = -94; + + /// + /// The integer ID for the Label (time) data type. + /// public const int LabelTime = -98; + + /// + /// The integer ID for the Label (decimal) data type. + /// public const int LabelDecimal = -99; + + /// + /// The integer ID for the Label (bytes) data type. + /// public const int LabelBytes = -104; + + /// + /// The integer ID for the Label (pixels) data type. + /// public const int LabelPixels = -105; + /// + /// The integer ID for the Textarea data type. + /// public const int Textarea = -89; + + /// + /// The integer ID for the Textbox data type. + /// public const int Textbox = -88; + + /// + /// The integer ID for the Rich Text Editor data type. + /// public const int RichtextEditor = -87; + + /// + /// The integer ID for the Boolean (True/False) data type. + /// public const int Boolean = -49; + + /// + /// The integer ID for the Date/Time data type. + /// public const int DateTime = -36; + + /// + /// The integer ID for the Dropdown (single select) data type. + /// public const int DropDownSingle = -39; + + /// + /// The integer ID for the Dropdown (multiple select) data type. + /// public const int DropDownMultiple = -42; + + /// + /// The integer ID for the Upload (file) data type. + /// public const int Upload = -90; + + /// + /// The integer ID for the Upload (video) data type. + /// public const int UploadVideo = -100; + + /// + /// The integer ID for the Upload (audio) data type. + /// public const int UploadAudio = -101; + + /// + /// The integer ID for the Upload (article) data type. + /// public const int UploadArticle = -102; + + /// + /// The integer ID for the Upload (vector graphics) data type. + /// public const int UploadVectorGraphics = -103; + /// + /// The integer ID for the default content list view data type. + /// public const int DefaultContentListView = -95; + + /// + /// The integer ID for the default media list view data type. + /// public const int DefaultMediaListView = -96; + + /// + /// The integer ID for the default members list view data type. + /// public const int DefaultMembersListView = -97; + /// + /// The integer ID for the Image Cropper data type. + /// public const int ImageCropper = 1043; + + /// + /// The integer ID for the Tags data type. + /// public const int Tags = 1041; + /// + /// Contains reserved pre-value keys used by data types. + /// public static class ReservedPreValueKeys { + /// + /// The pre-value key for ignoring user start nodes. + /// public const string IgnoreUserStartNodes = "ignoreUserStartNodes"; } diff --git a/src/Umbraco.Core/Constants-DeploySelector.cs b/src/Umbraco.Core/Constants-DeploySelector.cs index 771380a3da8e..1e463f8145d3 100644 --- a/src/Umbraco.Core/Constants-DeploySelector.cs +++ b/src/Umbraco.Core/Constants-DeploySelector.cs @@ -7,11 +7,34 @@ public static partial class Constants /// public static class DeploySelector { + /// + /// Selector value for selecting only the current item. + /// public const string This = "this"; + + /// + /// Selector value for selecting the current item and its direct children. + /// public const string ThisAndChildren = "this-and-children"; + + /// + /// Selector value for selecting the current item and all its descendants. + /// public const string ThisAndDescendants = "this-and-descendants"; + + /// + /// Selector value for selecting only the direct children of the current item. + /// public const string ChildrenOfThis = "children"; + + /// + /// Selector value for selecting only the descendants of the current item. + /// public const string DescendantsOfThis = "descendants"; + + /// + /// Selector value for selecting all entities of a specific type. + /// public const string EntitiesOfType = "entities-of-type"; } } diff --git a/src/Umbraco.Core/Constants-Headers.cs b/src/Umbraco.Core/Constants-Headers.cs index 3fb0df9c7738..190378900ab6 100644 --- a/src/Umbraco.Core/Constants-Headers.cs +++ b/src/Umbraco.Core/Constants-Headers.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains HTTP header name constants used by Umbraco. + /// public static class Headers { /// diff --git a/src/Umbraco.Core/Constants-HealthChecks.cs b/src/Umbraco.Core/Constants-HealthChecks.cs index 703b5017cf79..118738bd9e9c 100644 --- a/src/Umbraco.Core/Constants-HealthChecks.cs +++ b/src/Umbraco.Core/Constants-HealthChecks.cs @@ -6,56 +6,144 @@ namespace Umbraco.Cms.Core; public static partial class Constants { /// - /// Defines constants for ModelsBuilder. + /// Defines constants for health checks. /// public static class HealthChecks { + /// + /// Contains route path constants for health checks. + /// public static class RoutePath { + /// + /// The route path segment for health check endpoints. + /// public const string HealthCheck = "health-check"; } + /// + /// Contains documentation link constants for health checks. + /// public static class DocumentationLinks { + /// + /// The documentation link for SMTP health check. + /// public const string SmtpCheck = "https://umbra.co/healthchecks-smtp"; + /// + /// Contains documentation links for live environment health checks. + /// public static class LiveEnvironment { + /// + /// The documentation link for compilation debug check. + /// public const string CompilationDebugCheck = "https://umbra.co/healthchecks-compilation-debug"; + + /// + /// The documentation link for runtime mode check. + /// public const string RuntimeModeCheck = "https://docs.umbraco.com/umbraco-cms/fundamentals/setup/server-setup/runtime-modes"; } + /// + /// Contains documentation links for configuration health checks. + /// public static class Configuration { + /// + /// The documentation link for IIS custom errors check. + /// public const string TrySkipIisCustomErrorsCheck = "https://umbra.co/healthchecks-skip-iis-custom-errors"; + /// + /// The documentation link for notification email check. + /// public const string NotificationEmailCheck = "https://umbra.co/healthchecks-notification-email"; } + /// + /// Contains documentation links for folder and file permission health checks. + /// public static class FolderAndFilePermissionsCheck { + /// + /// The documentation link for file writing check. + /// public const string FileWriting = "https://umbra.co/healthchecks-file-writing"; + + /// + /// The documentation link for folder creation check. + /// public const string FolderCreation = "https://umbra.co/healthchecks-folder-creation"; + + /// + /// The documentation link for file writing for packages check. + /// public const string FileWritingForPackages = "https://umbra.co/healthchecks-file-writing-for-packages"; + + /// + /// The documentation link for media folder creation check. + /// public const string MediaFolderCreation = "https://umbra.co/healthchecks-media-folder-creation"; } + /// + /// Contains documentation links for security health checks. + /// public static class Security { + /// + /// The documentation link for Umbraco application URL check. + /// public const string UmbracoApplicationUrlCheck = "https://umbra.co/healthchecks-umbraco-application-url"; + /// + /// The documentation link for click jacking check. + /// public const string ClickJackingCheck = "https://umbra.co/healthchecks-click-jacking"; + + /// + /// The documentation link for HSTS check. + /// public const string HstsCheck = "https://umbra.co/healthchecks-hsts"; + + /// + /// The documentation link for no-sniff check. + /// public const string NoSniffCheck = "https://umbra.co/healthchecks-no-sniff"; + + /// + /// The documentation link for excessive headers check. + /// public const string ExcessiveHeadersCheck = "https://umbra.co/healthchecks-excessive-headers"; + + /// + /// The documentation link for CSP header check. + /// public const string CspHeaderCheck = "https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP"; + /// + /// Contains documentation links for HTTPS health checks. + /// public static class HttpsCheck { + /// + /// The documentation link for HTTPS request scheme check. + /// public const string CheckIfCurrentSchemeIsHttps = "https://umbra.co/healthchecks-https-request"; + + /// + /// The documentation link for HTTPS configuration setting check. + /// public const string CheckHttpsConfigurationSetting = "https://umbra.co/healthchecks-https-config"; + + /// + /// The documentation link for valid certificate check. + /// public const string CheckForValidCertificate = "https://umbra.co/healthchecks-valid-certificate"; } } diff --git a/src/Umbraco.Core/Constants-HttpClients.cs b/src/Umbraco.Core/Constants-HttpClients.cs index a9c693f39d33..8bed4d214bbb 100644 --- a/src/Umbraco.Core/Constants-HttpClients.cs +++ b/src/Umbraco.Core/Constants-HttpClients.cs @@ -20,6 +20,9 @@ public static class HttpClients /// public const string WebhookFiring = "Umbraco:HttpClients:WebhookFiring"; + /// + /// Contains HTTP header constants for Umbraco HTTP clients. + /// public static class Headers { /// diff --git a/src/Umbraco.Core/Constants-HttpContextItemsKeys.cs b/src/Umbraco.Core/Constants-HttpContextItemsKeys.cs index a89bfc2553fc..75b3c9b24b90 100644 --- a/src/Umbraco.Core/Constants-HttpContextItemsKeys.cs +++ b/src/Umbraco.Core/Constants-HttpContextItemsKeys.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains constants related to HttpContext usage. + /// public static class HttpContext { /// diff --git a/src/Umbraco.Core/Constants-Icons.cs b/src/Umbraco.Core/Constants-Icons.cs index 249abfadd24b..cbe6cbe1fd62 100644 --- a/src/Umbraco.Core/Constants-Icons.cs +++ b/src/Umbraco.Core/Constants-Icons.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains icon name constants used throughout the Umbraco backoffice. + /// public static class Icons { /// diff --git a/src/Umbraco.Core/Constants-Indexes.cs b/src/Umbraco.Core/Constants-Indexes.cs index a3c358676a6e..a51f38727851 100644 --- a/src/Umbraco.Core/Constants-Indexes.cs +++ b/src/Umbraco.Core/Constants-Indexes.cs @@ -2,11 +2,29 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains constants for Umbraco Examine search index names. + /// public static class UmbracoIndexes { + /// + /// The name of the internal content index (includes unpublished content). + /// public const string InternalIndexName = "InternalIndex"; + + /// + /// The name of the external content index (published content only). + /// public const string ExternalIndexName = "ExternalIndex"; + + /// + /// The name of the members index. + /// public const string MembersIndexName = "MembersIndex"; + + /// + /// The name of the Delivery API content index. + /// public const string DeliveryApiContentIndexName = "DeliveryApiContentIndex"; } } diff --git a/src/Umbraco.Core/Constants-JsonOptionsNames.cs b/src/Umbraco.Core/Constants-JsonOptionsNames.cs index b29f4e9169d6..44822182415c 100644 --- a/src/Umbraco.Core/Constants-JsonOptionsNames.cs +++ b/src/Umbraco.Core/Constants-JsonOptionsNames.cs @@ -1,8 +1,12 @@ -namespace Umbraco.Cms.Core; +namespace Umbraco.Cms.Core; public static partial class Constants { // TODO: move this class to Umbraco.Cms.Core as a partial class + + /// + /// Contains named JSON serialization options constants. + /// public static partial class JsonOptionsNames { /// @@ -10,6 +14,9 @@ public static partial class JsonOptionsNames /// public const string BackOffice = "BackOffice"; + /// + /// The JSON options name for Delivery API serialization. + /// public const string DeliveryApi = "Delivery"; } } diff --git a/src/Umbraco.Core/Constants-Marketplace.cs b/src/Umbraco.Core/Constants-Marketplace.cs index 38cf282b74f2..404ce31c8367 100644 --- a/src/Umbraco.Core/Constants-Marketplace.cs +++ b/src/Umbraco.Core/Constants-Marketplace.cs @@ -7,6 +7,9 @@ public static partial class Constants /// public static class Marketplace { + /// + /// The URL for the Umbraco Marketplace. + /// public const string Url = "https://marketplace.umbraco.com"; } } diff --git a/src/Umbraco.Core/Constants-ModelStateErrorKeys.cs b/src/Umbraco.Core/Constants-ModelStateErrorKeys.cs index c5bee395aa1d..b7c09bf4b363 100644 --- a/src/Umbraco.Core/Constants-ModelStateErrorKeys.cs +++ b/src/Umbraco.Core/Constants-ModelStateErrorKeys.cs @@ -1,9 +1,15 @@ -namespace Umbraco.Cms.Core; +namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains model state error key constants. + /// public class ModelStateErrorKeys { + /// + /// The model state error key for permission errors. + /// public const string PermissionError = "PermissionError"; } } diff --git a/src/Umbraco.Core/Constants-ModelsBuilder.cs b/src/Umbraco.Core/Constants-ModelsBuilder.cs index 60fca474e57b..d68b6a763faf 100644 --- a/src/Umbraco.Core/Constants-ModelsBuilder.cs +++ b/src/Umbraco.Core/Constants-ModelsBuilder.cs @@ -10,14 +10,29 @@ public static partial class Constants /// public static class ModelsBuilder { + /// + /// The default namespace used for generated models. + /// public const string DefaultModelsNamespace = "Umbraco.Cms.Web.Common.PublishedModels"; + /// + /// Defines the available ModelsBuilder modes. + /// public static class ModelsModes { + /// + /// Mode where source code is automatically generated and compiled at runtime. + /// public const string SourceCodeAuto = "SourceCodeAuto"; + /// + /// Mode where source code is generated but requires manual compilation. + /// public const string SourceCodeManual = "SourceCodeManual"; + /// + /// Mode where no models are generated. + /// public const string Nothing = "Nothing"; } } diff --git a/src/Umbraco.Core/Constants-OAuthClaims.cs b/src/Umbraco.Core/Constants-OAuthClaims.cs index 5a777236cdab..4089a0b5a577 100644 --- a/src/Umbraco.Core/Constants-OAuthClaims.cs +++ b/src/Umbraco.Core/Constants-OAuthClaims.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains OAuth claim type constants. + /// public static class OAuthClaims { /// diff --git a/src/Umbraco.Core/Constants-OAuthClientIds.cs b/src/Umbraco.Core/Constants-OAuthClientIds.cs index 8d5ef7610fab..267891599121 100644 --- a/src/Umbraco.Core/Constants-OAuthClientIds.cs +++ b/src/Umbraco.Core/Constants-OAuthClientIds.cs @@ -1,7 +1,10 @@ -namespace Umbraco.Cms.Core; +namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains OAuth client ID constants for different API clients. + /// public static class OAuthClientIds { /// diff --git a/src/Umbraco.Core/Constants-ObjectTypes.cs b/src/Umbraco.Core/Constants-ObjectTypes.cs index a6b3b2966bd8..d31a08523a82 100644 --- a/src/Umbraco.Core/Constants-ObjectTypes.cs +++ b/src/Umbraco.Core/Constants-ObjectTypes.cs @@ -7,58 +7,139 @@ public static partial class Constants /// public static class ObjectTypes { + /// + /// The GUID identifier for the system root object type. + /// public static readonly Guid SystemRoot = new(Strings.SystemRoot); + /// + /// The GUID identifier for the content recycle bin object type. + /// public static readonly Guid ContentRecycleBin = new(Strings.ContentRecycleBin); + /// + /// The GUID identifier for the media recycle bin object type. + /// public static readonly Guid MediaRecycleBin = new(Strings.MediaRecycleBin); + /// + /// The GUID identifier for the data type container object type. + /// public static readonly Guid DataTypeContainer = new(Strings.DataTypeContainer); + /// + /// The GUID identifier for the document type container object type. + /// public static readonly Guid DocumentTypeContainer = new(Strings.DocumentTypeContainer); + /// + /// The GUID identifier for the media type container object type. + /// public static readonly Guid MediaTypeContainer = new(Strings.MediaTypeContainer); + /// + /// The GUID identifier for the member type container object type. + /// public static readonly Guid MemberTypeContainer = new(Strings.MemberTypeContainer); + /// + /// The GUID identifier for the document blueprint container object type. + /// public static readonly Guid DocumentBlueprintContainer = new(Strings.DocumentBlueprintContainer); + /// + /// The GUID identifier for the data type object type. + /// public static readonly Guid DataType = new(Strings.DataType); + /// + /// The GUID identifier for the document (content) object type. + /// public static readonly Guid Document = new(Strings.Document); + /// + /// The GUID identifier for the document blueprint object type. + /// public static readonly Guid DocumentBlueprint = new(Strings.DocumentBlueprint); + /// + /// The GUID identifier for the document type (content type) object type. + /// public static readonly Guid DocumentType = new(Strings.DocumentType); + /// + /// The GUID identifier for the media object type. + /// public static readonly Guid Media = new(Strings.Media); + /// + /// The GUID identifier for the media type object type. + /// public static readonly Guid MediaType = new(Strings.MediaType); + /// + /// The GUID identifier for the member object type. + /// public static readonly Guid Member = new(Strings.Member); + /// + /// The GUID identifier for the member group object type. + /// public static readonly Guid MemberGroup = new(Strings.MemberGroup); + /// + /// The GUID identifier for the member type object type. + /// public static readonly Guid MemberType = new(Strings.MemberType); + /// + /// The GUID identifier for the template type object type. + /// public static readonly Guid TemplateType = new(Strings.Template); + /// + /// The GUID identifier for the lock object type. + /// public static readonly Guid LockObject = new(Strings.LockObject); + /// + /// The GUID identifier for the relation type object type. + /// public static readonly Guid RelationType = new(Strings.RelationType); + /// + /// The GUID identifier for the Umbraco Forms form object type. + /// public static readonly Guid FormsForm = new(Strings.FormsForm); + /// + /// The GUID identifier for the Umbraco Forms pre-value object type. + /// public static readonly Guid FormsPreValue = new(Strings.FormsPreValue); + /// + /// The GUID identifier for the Umbraco Forms data source object type. + /// public static readonly Guid FormsDataSource = new(Strings.FormsDataSource); + /// + /// The GUID identifier for the language object type. + /// public static readonly Guid Language = new(Strings.Language); + /// + /// The GUID identifier for the ID reservation object type. + /// public static readonly Guid IdReservation = new(Strings.IdReservation); + /// + /// The GUID identifier for the template object type. + /// public static readonly Guid Template = new(Strings.Template); + /// + /// The GUID identifier for the content item object type. + /// public static readonly Guid ContentItem = new(Strings.ContentItem); /// @@ -71,58 +152,140 @@ public static class ObjectTypes public static class Strings { // ReSharper disable MemberHidesStaticFromOuterClass + + /// + /// The string GUID for the data type container object type. + /// public const string DataTypeContainer = "521231E3-8B37-469C-9F9D-51AFC91FEB7B"; + /// + /// The string GUID for the document type container object type. + /// public const string DocumentTypeContainer = "2F7A2769-6B0B-4468-90DD-AF42D64F7F16"; + /// + /// The string GUID for the media type container object type. + /// public const string MediaTypeContainer = "42AEF799-B288-4744-9B10-BE144B73CDC4"; + /// + /// The string GUID for the member type container object type. + /// public const string MemberTypeContainer = "59EF5767-7223-4ABC-B229-72821DC711B9"; + /// + /// The string GUID for the document blueprint container object type. + /// public const string DocumentBlueprintContainer = "A7EFF71B-FA69-4552-93FC-038F7DEEE453"; + /// + /// The string GUID for the content item object type. + /// public const string ContentItem = "10E2B09F-C28B-476D-B77A-AA686435E44A"; + /// + /// The string GUID for the content item type object type. + /// public const string ContentItemType = "7A333C54-6F43-40A4-86A2-18688DC7E532"; + /// + /// The string GUID for the content recycle bin object type. + /// public const string ContentRecycleBin = "01BB7FF2-24DC-4C0C-95A2-C24EF72BBAC8"; + /// + /// The string GUID for the data type object type. + /// public const string DataType = "30A2A501-1978-4DDB-A57B-F7EFED43BA3C"; + /// + /// The string GUID for the document (content) object type. + /// public const string Document = "C66BA18E-EAF3-4CFF-8A22-41B16D66A972"; + /// + /// The string GUID for the document blueprint object type. + /// public const string DocumentBlueprint = "6EBEF410-03AA-48CF-A792-E1C1CB087ACA"; + /// + /// The string GUID for the document type (content type) object type. + /// public const string DocumentType = "A2CB7800-F571-4787-9638-BC48539A0EFB"; + /// + /// The string GUID for the media object type. + /// public const string Media = "B796F64C-1F99-4FFB-B886-4BF4BC011A9C"; + /// + /// The string GUID for the media recycle bin object type. + /// public const string MediaRecycleBin = "CF3D8E34-1C1C-41e9-AE56-878B57B32113"; + /// + /// The string GUID for the media type object type. + /// public const string MediaType = "4EA4382B-2F5A-4C2B-9587-AE9B3CF3602E"; + /// + /// The string GUID for the member object type. + /// public const string Member = "39EB0F98-B348-42A1-8662-E7EB18487560"; + /// + /// The string GUID for the member group object type. + /// public const string MemberGroup = "366E63B9-880F-4E13-A61C-98069B029728"; + /// + /// The string GUID for the member type object type. + /// public const string MemberType = "9B5416FB-E72F-45A9-A07B-5A9A2709CE43"; + /// + /// The string GUID for the system root object type. + /// public const string SystemRoot = "EA7D8624-4CFE-4578-A871-24AA946BF34D"; + /// + /// The string GUID for the template object type. + /// public const string Template = "6FBDE604-4178-42CE-A10B-8A2600A2F07D"; + /// + /// The string GUID for the lock object type. + /// public const string LockObject = "87A9F1FF-B1E4-4A25-BABB-465A4A47EC41"; + /// + /// The string GUID for the relation type object type. + /// public const string RelationType = "B1988FAD-8675-4F47-915A-B3A602BC5D8D"; + /// + /// The string GUID for the Umbraco Forms form object type. + /// public const string FormsForm = "F5A9F787-6593-46F0-B8FF-BFD9BCA9F6BB"; + /// + /// The string GUID for the Umbraco Forms pre-value object type. + /// public const string FormsPreValue = "42D7BF9B-A362-4FEE-B45A-674D5C064B70"; + /// + /// The string GUID for the Umbraco Forms data source object type. + /// public const string FormsDataSource = "CFED6CE4-9359-443E-9977-9956FEB1D867"; + /// + /// The string GUID for the language object type. + /// public const string Language = "6B05D05B-EC78-49BE-A4E4-79E274F07A77"; + /// + /// The string GUID for the ID reservation object type. + /// public const string IdReservation = "92849B1E-3904-4713-9356-F646F87C25F4"; // ReSharper restore MemberHidesStaticFromOuterClass diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs index ab1715cf1766..bbe5a09f05a5 100644 --- a/src/Umbraco.Core/Constants-PropertyEditors.cs +++ b/src/Umbraco.Core/Constants-PropertyEditors.cs @@ -14,18 +14,59 @@ public static class PropertyEditors /// public const string InternalGenericPropertiesPrefix = "_umb_"; + /// + /// Contains legacy property editor aliases from previous Umbraco versions. + /// public static class Legacy { + /// + /// Defines legacy property editor aliases. + /// public static class Aliases { + /// + /// Legacy alias for the Textbox property editor. + /// public const string Textbox = "Umbraco.Textbox"; + + /// + /// Legacy alias for the Date property editor. + /// public const string Date = "Umbraco.Date"; + + /// + /// Legacy alias for the Content Picker 2 property editor. + /// public const string ContentPicker2 = "Umbraco.ContentPicker2"; + + /// + /// Legacy alias for the Media Picker 2 property editor. + /// public const string MediaPicker2 = "Umbraco.MediaPicker2"; + + /// + /// Legacy alias for the Member Picker 2 property editor. + /// public const string MemberPicker2 = "Umbraco.MemberPicker2"; + + /// + /// Legacy alias for the Multi Node Tree Picker 2 property editor. + /// public const string MultiNodeTreePicker2 = "Umbraco.MultiNodeTreePicker2"; + + /// + /// Legacy alias for the Textbox Multiple property editor. + /// public const string TextboxMultiple = "Umbraco.TextboxMultiple"; + + /// + /// Legacy alias for the Related Links 2 property editor. + /// public const string RelatedLinks2 = "Umbraco.RelatedLinks2"; + + /// + /// Legacy alias for the Related Links property editor. + /// public const string RelatedLinks = "Umbraco.RelatedLinks"; } } @@ -283,16 +324,34 @@ public static class ConfigurationKeys /// public static class Groups { + /// + /// The Common property editor group. + /// public const string Common = "Common"; + /// + /// The Lists property editor group. + /// public const string Lists = "Lists"; + /// + /// The Media property editor group. + /// public const string Media = "Media"; + /// + /// The People property editor group. + /// public const string People = "People"; + /// + /// The Pickers property editor group. + /// public const string Pickers = "Pickers"; + /// + /// The Rich Content property editor group. + /// public const string RichContent = "Rich Content"; } } diff --git a/src/Umbraco.Core/Constants-ProviderNames.cs b/src/Umbraco.Core/Constants-ProviderNames.cs index 67f376612c5f..1357450e438e 100644 --- a/src/Umbraco.Core/Constants-ProviderNames.cs +++ b/src/Umbraco.Core/Constants-ProviderNames.cs @@ -2,10 +2,19 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains database provider name constants. + /// public static class ProviderNames { + /// + /// The provider name for SQLite databases. + /// public const string SQLLite = "Microsoft.Data.Sqlite"; + /// + /// The provider name for SQL Server databases. + /// public const string SQLServer = "Microsoft.Data.SqlClient"; } } diff --git a/src/Umbraco.Core/Constants-ReferenceTypes.cs b/src/Umbraco.Core/Constants-ReferenceTypes.cs index b006a0d59007..3de5cb1e1955 100644 --- a/src/Umbraco.Core/Constants-ReferenceTypes.cs +++ b/src/Umbraco.Core/Constants-ReferenceTypes.cs @@ -15,11 +15,34 @@ public static partial class Constants /// public static class ReferenceType { + /// + /// The reference type for document entities. + /// public const string Document = UdiEntityType.Document; + + /// + /// The reference type for media entities. + /// public const string Media = UdiEntityType.Media; + + /// + /// The reference type for member entities. + /// public const string Member = UdiEntityType.Member; + + /// + /// The reference type for document type property type references. + /// public const string DocumentTypePropertyType = "document-type-property-type"; + + /// + /// The reference type for media type property type references. + /// public const string MediaTypePropertyType = "media-type-property-type"; + + /// + /// The reference type for member type property type references. + /// public const string MemberTypePropertyType = "member-type-property-type"; } } diff --git a/src/Umbraco.Core/Constants-Security.cs b/src/Umbraco.Core/Constants-Security.cs index 6567fc99b33e..3fbbc1b92117 100644 --- a/src/Umbraco.Core/Constants-Security.cs +++ b/src/Umbraco.Core/Constants-Security.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Security-related constants including user identifiers, authentication types, and claim types. + /// public static class Security { /// @@ -15,6 +18,9 @@ public static class Security /// public static readonly Guid SuperUserKey = new("1E70F841-C261-413B-ABB2-2D68CDB96094"); + /// + /// Gets the identifier of the 'super' user as a string. + /// [Obsolete("Use SuperUserKey instead. Scheduled for removal in V15.")] public const string SuperUserIdAsString = "-1"; @@ -32,12 +38,19 @@ public static class Security /// public const string UnknownUserName = "SYSTEM"; + /// + /// The alias of the admin user group. + /// public const string AdminGroupAlias = "admin"; /// /// The key of the admin group /// public static readonly Guid AdminGroupKey = new(AdminGroupKeyString); + + /// + /// The key of the admin group as a string. + /// internal const string AdminGroupKeyString = "E5E7F6C8-7F9C-4B5B-8D5D-9E1E5A4F7E4D"; @@ -45,6 +58,10 @@ public static class Security /// The key of the editor group /// public static readonly Guid EditorGroupKey = new(EditorGroupKeyString); + + /// + /// The key of the editor group as a string. + /// internal const string EditorGroupKeyString = "44DC260E-B4D4-4DD9-9081-EEC5598F1641"; @@ -52,26 +69,61 @@ public static class Security /// The key of the sensitive data group /// public static readonly Guid SensitiveDataGroupKey = new(SensitiveDataGroupKeyString); + + /// + /// The key of the sensitive data group as a string. + /// internal const string SensitiveDataGroupKeyString = "8C6AD70F-D307-4E4A-AF58-72C2E4E9439D"; /// /// The key of the translator group /// public static readonly Guid TranslatorGroupKey = new(TranslatorGroupString); + + /// + /// The key of the translator group as a string. + /// internal const string TranslatorGroupString = "F2012E4C-D232-4BD1-8EAE-4384032D97D8"; /// /// The key of the writer group /// public static readonly Guid WriterGroupKey = new(WriterGroupKeyString); + + /// + /// The key of the writer group as a string. + /// internal const string WriterGroupKeyString = "9FC2A16F-528C-46D6-A014-75BF4EC2480C"; + /// + /// The authentication type for backoffice authentication. + /// public const string BackOfficeAuthenticationType = "UmbracoBackOffice"; + + /// + /// The authentication type for backoffice external login providers. + /// public const string BackOfficeExternalAuthenticationType = "UmbracoExternalCookie"; + + /// + /// The cookie name for backoffice external login authentication. + /// public const string BackOfficeExternalCookieName = "UMB_EXTLOGIN"; + + /// + /// The authentication type for backoffice token-based authentication. + /// public const string BackOfficeTokenAuthenticationType = "UmbracoBackOfficeToken"; + + /// + /// The authentication type for backoffice two-factor authentication. + /// public const string BackOfficeTwoFactorAuthenticationType = "UmbracoTwoFactorCookie"; + + /// + /// The authentication type for backoffice two-factor "remember me" functionality. + /// public const string BackOfficeTwoFactorRememberMeAuthenticationType = "UmbracoTwoFactorRememberMeCookie"; /// @@ -84,8 +136,14 @@ public static class Security /// public const string BackOfficeExposedCookieName = "UMB_UCONTEXT_EXPOSED"; + /// + /// The prefix used to identify empty password placeholders. + /// public const string EmptyPasswordPrefix = "___UIDEMPTYPWORD__"; + /// + /// The default member type alias used when no specific member type is specified. + /// public const string DefaultMemberTypeAlias = "Member"; /// @@ -98,22 +156,40 @@ public static class Security /// public const string BackOfficeExternalAuthenticationTypePrefix = "Umbraco."; + /// + /// The prefix used for member external authentication types. + /// public const string MemberExternalAuthenticationTypePrefix = "UmbracoMembers."; + /// + /// The claim type for the user's start content node ID. + /// [Obsolete("Please use the UserExtensions class to access user start node info. Will be removed in V15.")] public const string StartContentNodeIdClaimType = "http://umbraco.org/2015/02/identity/claims/backoffice/startcontentnode"; + /// + /// The claim type for the user's start media node ID. + /// [Obsolete("Please use the UserExtensions class to access user start node info. Will be removed in V15.")] public const string StartMediaNodeIdClaimType = "http://umbraco.org/2015/02/identity/claims/backoffice/startmedianode"; + /// + /// The claim type for the user's allowed applications. + /// [Obsolete("Please use IUser.AllowedSections instead. Will be removed in V15.")] public const string AllowedApplicationsClaimType = "http://umbraco.org/2015/02/identity/claims/backoffice/allowedapp"; + /// + /// The claim type for the backoffice session ID. + /// public const string SessionIdClaimType = "http://umbraco.org/2015/02/identity/claims/backoffice/sessionid"; + /// + /// The claim type for the authentication ticket expiration time. + /// public const string TicketExpiresClaimType = "http://umbraco.org/2020/06/identity/claims/backoffice/ticketexpires"; @@ -127,10 +203,29 @@ public static class Security /// public const string OpenIdDictSubClaimType = "sub"; + /// + /// The algorithm name for ASP.NET Core v3 PBKDF2 password hashing. + /// public const string AspNetCoreV3PasswordHashAlgorithmName = "PBKDF2.ASPNETCORE.V3"; + + /// + /// The algorithm name for ASP.NET Core v2 PBKDF2 password hashing. + /// public const string AspNetCoreV2PasswordHashAlgorithmName = "PBKDF2.ASPNETCORE.V2"; + + /// + /// The algorithm name for Umbraco 8 HMACSHA256 password hashing. + /// public const string AspNetUmbraco8PasswordHashAlgorithmName = "HMACSHA256"; + + /// + /// The algorithm name for Umbraco 4 HMACSHA1 password hashing. + /// public const string AspNetUmbraco4PasswordHashAlgorithmName = "HMACSHA1"; + + /// + /// The JSON configuration string for unknown password hash algorithms. + /// public const string UnknownPasswordConfigJson = "{\"hashAlgorithm\":\"Unknown\"}"; } } diff --git a/src/Umbraco.Core/Constants-ServerEvents.cs b/src/Umbraco.Core/Constants-ServerEvents.cs index 49c4c981fd82..c685403e8137 100644 --- a/src/Umbraco.Core/Constants-ServerEvents.cs +++ b/src/Umbraco.Core/Constants-ServerEvents.cs @@ -2,66 +2,157 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains constants for server-sent events (SSE) used for real-time notifications. + /// public static class ServerEvents { + /// + /// Contains event source identifiers for different entity types. + /// public static class EventSource { + /// + /// The event source identifier for document events. + /// public const string Document = "Umbraco:CMS:Document"; + /// + /// The event source identifier for document blueprint events. + /// public const string DocumentBlueprint = "Umbraco:CMS:DocumentBlueprint"; + /// + /// The event source identifier for document type events. + /// public const string DocumentType = "Umbraco:CMS:DocumentType"; + /// + /// The event source identifier for media events. + /// public const string Media = "Umbraco:CMS:Media"; + /// + /// The event source identifier for media type events. + /// public const string MediaType = "Umbraco:CMS:MediaType"; + /// + /// The event source identifier for member events. + /// public const string Member = "Umbraco:CMS:Member"; + /// + /// The event source identifier for member type events. + /// public const string MemberType = "Umbraco:CMS:MemberType"; + /// + /// The event source identifier for member group events. + /// public const string MemberGroup = "Umbraco:CMS:MemberGroup"; + /// + /// The event source identifier for data type events. + /// public const string DataType = "Umbraco:CMS:DataType"; + /// + /// The event source identifier for language events. + /// public const string Language = "Umbraco:CMS:Language"; + /// + /// The event source identifier for script events. + /// public const string Script = "Umbraco:CMS:Script"; + /// + /// The event source identifier for stylesheet events. + /// public const string Stylesheet = "Umbraco:CMS:Stylesheet"; + /// + /// The event source identifier for template events. + /// public const string Template = "Umbraco:CMS:Template"; + /// + /// The event source identifier for dictionary item events. + /// public const string DictionaryItem = "Umbraco:CMS:DictionaryItem"; + /// + /// The event source identifier for domain events. + /// public const string Domain = "Umbraco:CMS:Domain"; + /// + /// The event source identifier for partial view events. + /// public const string PartialView = "Umbraco:CMS:PartialView"; + /// + /// The event source identifier for public access entry events. + /// public const string PublicAccessEntry = "Umbraco:CMS:PublicAccessEntry"; + /// + /// The event source identifier for relation events. + /// public const string Relation = "Umbraco:CMS:Relation"; + /// + /// The event source identifier for relation type events. + /// public const string RelationType = "Umbraco:CMS:RelationType"; + /// + /// The event source identifier for user group events. + /// public const string UserGroup = "Umbraco:CMS:UserGroup"; + /// + /// The event source identifier for user events. + /// public const string User = "Umbraco:CMS:User"; + /// + /// The event source identifier for current user events. + /// public const string CurrentUser = "Umbraco:CMS:CurrentUser"; + /// + /// The event source identifier for webhook events. + /// public const string Webhook = "Umbraco:CMS:Webhook"; } + /// + /// Contains event type identifiers for entity lifecycle events. + /// public static class EventType { // TODO (V18): Convert these statics to consts to comply with SA1401. + + /// + /// The event type for entity creation events. + /// public static string Created = "Created"; + /// + /// The event type for entity update events. + /// public static string Updated = "Updated"; + /// + /// The event type for entity deletion events. + /// public static string Deleted = "Deleted"; + /// + /// The event type for entity trashed events. + /// public static string Trashed = "Trashed"; } } diff --git a/src/Umbraco.Core/Constants-Sql.cs b/src/Umbraco.Core/Constants-Sql.cs index f89368046564..665c34302e86 100644 --- a/src/Umbraco.Core/Constants-Sql.cs +++ b/src/Umbraco.Core/Constants-Sql.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains SQL-related constants. + /// public static class Sql { /// diff --git a/src/Umbraco.Core/Constants-SqlTemplates.cs b/src/Umbraco.Core/Constants-SqlTemplates.cs index 3641510fd63c..8c1dfffae5be 100644 --- a/src/Umbraco.Core/Constants-SqlTemplates.cs +++ b/src/Umbraco.Core/Constants-SqlTemplates.cs @@ -2,52 +2,141 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains SQL template name constants used for parameterized queries. + /// public static class SqlTemplates { + /// + /// Contains SQL template names for versionable repository operations. + /// public static class VersionableRepository { + /// + /// The SQL template name for getting version IDs. + /// public const string GetVersionIds = "Umbraco.Core.VersionableRepository.GetVersionIds"; + + /// + /// The SQL template name for getting a single version. + /// public const string GetVersion = "Umbraco.Core.VersionableRepository.GetVersion"; + + /// + /// The SQL template name for getting multiple versions. + /// public const string GetVersions = "Umbraco.Core.VersionableRepository.GetVersions"; + + /// + /// The SQL template name for ensuring unique node names. + /// public const string EnsureUniqueNodeName = "Umbraco.Core.VersionableRepository.EnsureUniqueNodeName"; + + /// + /// The SQL template name for checking if a sort order exists. + /// public const string SortOrderExists = "Umbraco.Core.VersionableRepository.SortOrderExists"; + + /// + /// The SQL template name for getting the sort order. + /// public const string GetSortOrder = "Umbraco.Core.VersionableRepository.GetSortOrder"; + + /// + /// The SQL template name for getting the parent node. + /// public const string GetParentNode = "Umbraco.Core.VersionableRepository.GetParentNode"; + + /// + /// The SQL template name for getting a reserved ID. + /// public const string GetReservedId = "Umbraco.Core.VersionableRepository.GetReservedId"; } + /// + /// Contains SQL template names for relation repository operations. + /// public static class RelationRepository { + /// + /// The SQL template name for deleting all relations by parent. + /// public const string DeleteByParentAll = "Umbraco.Core.RelationRepository.DeleteByParent"; + + /// + /// The SQL template name for deleting relations by parent using an IN clause. + /// public const string DeleteByParentIn = "Umbraco.Core.RelationRepository.DeleteByParentIn"; } + /// + /// Contains SQL template names for data type repository operations. + /// public static class DataTypeRepository { + /// + /// The SQL template name for ensuring unique data type node names. + /// public const string EnsureUniqueNodeName = "Umbraco.Core.DataTypeDefinitionRepository.EnsureUniqueNodeName"; } + /// + /// Contains SQL template names for NuCache database data source operations. + /// public static class NuCacheDatabaseDataSource { + /// + /// The SQL template name for filtering by node ID. + /// public const string WhereNodeId = "Umbraco.Web.PublishedCache.NuCache.DataSource.WhereNodeId"; + + /// + /// The SQL template name for filtering by node key. + /// public const string WhereNodeKey = "Umbraco.Web.PublishedCache.NuCache.DataSource.WhereNodeKey"; + + /// + /// The SQL template name for extended node ID filtering. + /// public const string WhereNodeIdX = "Umbraco.Web.PublishedCache.NuCache.DataSource.WhereNodeIdX"; + /// + /// The SQL template name for selecting sources with an Umbraco node join. + /// public const string SourcesSelectUmbracoNodeJoin = "Umbraco.Web.PublishedCache.NuCache.DataSource.SourcesSelectUmbracoNodeJoin"; + /// + /// The SQL template name for selecting content sources. + /// public const string ContentSourcesSelect = "Umbraco.Web.PublishedCache.NuCache.DataSource.ContentSourcesSelect"; + /// + /// The SQL template name for counting content sources. + /// public const string ContentSourcesCount = "Umbraco.Web.PublishedCache.NuCache.DataSource.ContentSourcesCount"; + /// + /// The SQL template name for selecting media sources. + /// public const string MediaSourcesSelect = "Umbraco.Web.PublishedCache.NuCache.DataSource.MediaSourcesSelect"; + + /// + /// The SQL template name for counting media sources. + /// public const string MediaSourcesCount = "Umbraco.Web.PublishedCache.NuCache.DataSource.MediaSourcesCount"; + /// + /// The SQL template name for filtering by object type excluding trashed items. + /// public const string ObjectTypeNotTrashedFilter = "Umbraco.Web.PublishedCache.NuCache.DataSource.ObjectTypeNotTrashedFilter"; + /// + /// The SQL template name for ordering by level, ID, and sort order. + /// public const string OrderByLevelIdSortOrder = "Umbraco.Web.PublishedCache.NuCache.DataSource.OrderByLevelIdSortOrder"; } diff --git a/src/Umbraco.Core/Constants-System.cs b/src/Umbraco.Core/Constants-System.cs index e0ce203052de..0473931a1d54 100644 --- a/src/Umbraco.Core/Constants-System.cs +++ b/src/Umbraco.Core/Constants-System.cs @@ -119,6 +119,9 @@ public static class System /// public const string DataDirectoryPlaceholder = "|DataDirectory|"; + /// + /// The wildcard character used to represent the invariant culture. + /// public const string InvariantCulture = "*"; } } diff --git a/src/Umbraco.Core/Constants-SystemDirectories.cs b/src/Umbraco.Core/Constants-SystemDirectories.cs index a3231dcbe977..dc065021f4a0 100644 --- a/src/Umbraco.Core/Constants-SystemDirectories.cs +++ b/src/Umbraco.Core/Constants-SystemDirectories.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains constants for Umbraco system directory paths. + /// public static class SystemDirectories { /// @@ -10,6 +13,10 @@ public static class SystemDirectories public const string Bin = "~/bin"; // TODO: Shouldn't this exist underneath /Umbraco in the content root? + + /// + /// The configuration folder path. + /// public const string Config = "~/config"; /// @@ -35,22 +42,49 @@ public static class SystemDirectories /// public const string TempData = Data + "/TEMP"; + /// + /// The temporary file uploads folder path. + /// public const string TempFileUploads = TempData + "/FileUploads"; + /// + /// The install folder path. + /// public const string Install = "~/install"; + /// + /// The App_Plugins folder path for custom packages. + /// public const string AppPlugins = "/App_Plugins"; + /// + /// The backoffice path. + /// public const string BackOfficePath = "/umbraco/backoffice"; + /// + /// The MVC Views folder path. + /// public const string MvcViews = "~/Views"; + /// + /// The partial views folder path. + /// public const string PartialViews = MvcViews + "/Partials/"; + /// + /// The packages folder path for installed packages. + /// public const string Packages = Data + "/packages"; + /// + /// The created packages folder path for exported packages. + /// public const string CreatedPackages = Data + "/CreatedPackages"; + /// + /// The preview folder path for content preview data. + /// public const string Preview = Data + "/preview"; /// diff --git a/src/Umbraco.Core/Constants-Telemetry.cs b/src/Umbraco.Core/Constants-Telemetry.cs index 25845260021a..9743c8c22c98 100644 --- a/src/Umbraco.Core/Constants-Telemetry.cs +++ b/src/Umbraco.Core/Constants-Telemetry.cs @@ -2,42 +2,181 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains constants for telemetry data keys used in system analytics and reporting. + /// public static class Telemetry { // TODO (V18): Convert these static fields to const to comply with SA1401 (fields should be private) + + /// + /// The telemetry key for the count of root content nodes. + /// public static string RootCount = "RootCount"; + + /// + /// The telemetry key for the count of domains configured. + /// public static string DomainCount = "DomainCount"; + + /// + /// The telemetry key for the count of Examine search indexes. + /// public static string ExamineIndexCount = "ExamineIndexCount"; + + /// + /// The telemetry key for the count of languages configured. + /// public static string LanguageCount = "LanguageCount"; + + /// + /// The telemetry key for the count of media items. + /// public static string MediaCount = "MediaCount"; + + /// + /// The telemetry key for the count of members. + /// public static string MemberCount = "MemberCount"; + + /// + /// The telemetry key for the count of templates. + /// public static string TemplateCount = "TemplateCount"; + + /// + /// The telemetry key for the count of content items. + /// public static string ContentCount = "ContentCount"; + + /// + /// The telemetry key for the count of document types. + /// public static string DocumentTypeCount = "DocumentTypeCount"; + + /// + /// The telemetry key for property information. + /// public static string Properties = "Properties"; + + /// + /// The telemetry key for the count of users. + /// public static string UserCount = "UserCount"; + + /// + /// The telemetry key for the count of user groups. + /// public static string UserGroupCount = "UserGroupCount"; + + /// + /// The telemetry key for the server operating system. + /// public static string ServerOs = "ServerOs"; + + /// + /// The telemetry key for the server framework version. + /// public static string ServerFramework = "ServerFramework"; + + /// + /// The telemetry key for the operating system language. + /// public static string OsLanguage = "OsLanguage"; + + /// + /// The telemetry key for the web server type. + /// public static string WebServer = "WebServer"; + + /// + /// The telemetry key for the Models Builder mode. + /// public static string ModelsBuilderMode = "ModelBuilderMode"; + + /// + /// The telemetry key for the ASP.NET Core environment name. + /// public static string AspEnvironment = "AspEnvironment"; + + /// + /// The telemetry key indicating whether debug mode is enabled. + /// public static string IsDebug = "IsDebug"; + + /// + /// The telemetry key for the database provider type. + /// public static string DatabaseProvider = "DatabaseProvider"; + + /// + /// The telemetry key for the current server role in a load-balanced environment. + /// public static string CurrentServerRole = "CurrentServerRole"; + + /// + /// The telemetry key for the runtime mode. + /// public static string RuntimeMode = "RuntimeMode"; + + /// + /// The telemetry key for the count of backoffice external login providers. + /// public static string BackofficeExternalLoginProviderCount = "BackofficeExternalLoginProviderCount"; + + /// + /// The telemetry key indicating whether the Delivery API is enabled. + /// public static string DeliverApiEnabled = "DeliverApiEnabled"; + + /// + /// The telemetry key for Delivery API public access configuration. + /// public static string DeliveryApiPublicAccess = "DeliveryApiPublicAccess"; + + /// + /// The prefix used for webhook-related telemetry keys. + /// public static string WebhookPrefix = "WebhookCount_"; + + /// + /// The telemetry key for the total count of webhooks. + /// public static string WebhookTotal = $"{WebhookPrefix}Total"; + + /// + /// The telemetry key for the count of webhooks with custom headers. + /// public static string WebhookCustomHeaders = $"{WebhookPrefix}CustomHeaders"; + + /// + /// The telemetry key for the count of webhooks with custom events. + /// public static string WebhookCustomEvent = $"{WebhookPrefix}CustomEvent"; + + /// + /// The telemetry key for the count of rich text editors. + /// public static string RichTextEditorCount = "RichTextEditorCount"; + + /// + /// The telemetry key for the count of rich text blocks. + /// public static string RichTextBlockCount = "RichTextBlockCount"; + + /// + /// The telemetry key for the total count of properties across all content types. + /// public static string TotalPropertyCount = "TotalPropertyCount"; + + /// + /// The telemetry key for the highest property count on a single content type. + /// public static string HighestPropertyCount = "HighestPropertyCount"; + + /// + /// The telemetry key for the total count of compositions used. + /// public static string TotalCompositions = "TotalCompositions"; } } diff --git a/src/Umbraco.Core/Constants-UdiEntityType.cs b/src/Umbraco.Core/Constants-UdiEntityType.cs index c5191b8c25c1..9f2a176a5610 100644 --- a/src/Umbraco.Core/Constants-UdiEntityType.cs +++ b/src/Umbraco.Core/Constants-UdiEntityType.cs @@ -15,49 +15,181 @@ public static class UdiEntityType // this is validated by UdiTests.ValidateUdiEntityType // also, this is used exclusively in Udi static ctor, only once, so there is no // need to keep it around in a field nor to make it readonly + + /// + /// The entity type for unknown entities. + /// public const string Unknown = "unknown"; // GUID entity types + + /// + /// The entity type for any GUID-based entity (used for tests). + /// public const string AnyGuid = "any-guid"; // that one is for tests + + /// + /// The entity type for dictionary items. + /// public const string DictionaryItem = "dictionary-item"; + + /// + /// The entity type for documents (content items). + /// public const string Document = "document"; + + /// + /// The entity type for document blueprints (content templates). + /// public const string DocumentBlueprint = "document-blueprint"; + + /// + /// The entity type for document blueprint containers (folders). + /// public const string DocumentBlueprintContainer = "document-blueprint-container"; + + /// + /// The entity type for document types (content types). + /// public const string DocumentType = "document-type"; + + /// + /// The entity type for document type containers (folders). + /// public const string DocumentTypeContainer = "document-type-container"; + /// + /// The entity type for member types. + /// public const string MemberType = "member-type"; + + /// + /// The entity type for member type containers (folders). + /// public const string MemberTypeContainer = "member-type-container"; + + /// + /// The entity type for member groups. + /// public const string MemberGroup = "member-group"; + + /// + /// The entity type for members. + /// public const string Member = "member"; + /// + /// The entity type for data types. + /// public const string DataType = "data-type"; + + /// + /// The entity type for data type containers (folders). + /// public const string DataTypeContainer = "data-type-container"; + /// + /// The entity type for elements (element type instances). + /// public const string Element = "element"; + + /// + /// The entity type for media items. + /// public const string Media = "media"; + + /// + /// The entity type for media types. + /// public const string MediaType = "media-type"; + + /// + /// The entity type for media type containers (folders). + /// public const string MediaTypeContainer = "media-type-container"; + + /// + /// The entity type for relations. + /// public const string Relation = "relation"; + /// + /// The entity type for relation types. + /// public const string RelationType = "relation-type"; + + /// + /// The entity type for templates. + /// public const string Template = "template"; + + /// + /// The entity type for users. + /// public const string User = "user"; + + /// + /// The entity type for user groups. + /// public const string UserGroup = "user-group"; + + /// + /// The entity type for webhooks. + /// public const string Webhook = "webhook"; // String entity types + + /// + /// The entity type for any string-based entity (used for tests). + /// public const string AnyString = "any-string"; // that one is for tests + + /// + /// The entity type for languages. + /// public const string Language = "language"; + + /// + /// The entity type for media files. + /// public const string MediaFile = "media-file"; + + /// + /// The entity type for partial views. + /// public const string PartialView = "partial-view"; + + /// + /// The entity type for scripts. + /// public const string Script = "script"; + + /// + /// The entity type for stylesheets. + /// public const string Stylesheet = "stylesheet"; + + /// + /// The entity type for template files. + /// public const string TemplateFile = "template-file"; // Forms entity types + + /// + /// The entity type for Umbraco Forms data sources. + /// public const string FormsDataSource = "forms-datasource"; + + /// + /// The entity type for Umbraco Forms forms. + /// public const string FormsForm = "forms-form"; + + /// + /// The entity type for Umbraco Forms pre-values. + /// public const string FormsPreValue = "forms-prevalue"; } } diff --git a/src/Umbraco.Core/Constants-UrlProviders.cs b/src/Umbraco.Core/Constants-UrlProviders.cs index 47524d6d3d6c..8be5e2c7eac9 100644 --- a/src/Umbraco.Core/Constants-UrlProviders.cs +++ b/src/Umbraco.Core/Constants-UrlProviders.cs @@ -2,10 +2,19 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains constants for URL provider names. + /// public static class UrlProviders { + /// + /// The name of the content URL provider. + /// public const string Content = "umbDocumentUrlProvider"; + /// + /// The name of the media URL provider. + /// public const string Media = "umbMediaUrlProvider"; } } diff --git a/src/Umbraco.Core/Constants-Validation.cs b/src/Umbraco.Core/Constants-Validation.cs index 98aa2fc67eba..bb82f75b2bb3 100644 --- a/src/Umbraco.Core/Constants-Validation.cs +++ b/src/Umbraco.Core/Constants-Validation.cs @@ -1,17 +1,35 @@ -namespace Umbraco.Cms.Core; +namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains constants for validation. + /// public static class Validation { + /// + /// Contains validation error message constants. + /// public static class ErrorMessages { + /// + /// Contains property validation error message constants. + /// public static class Properties { + /// + /// The localization key for missing/null value validation error. + /// public const string Missing = "#validation_invalidNull"; + /// + /// The localization key for empty value validation error. + /// public const string Empty = "#validation_invalidEmpty"; + /// + /// The localization key for pattern mismatch validation error. + /// public const string PatternMismatch = "#validation_invalidPattern"; } } diff --git a/src/Umbraco.Core/Constants-Web.cs b/src/Umbraco.Core/Constants-Web.cs index 3ad4095a7cd0..18f9499a6019 100644 --- a/src/Umbraco.Core/Constants-Web.cs +++ b/src/Umbraco.Core/Constants-Web.cs @@ -17,6 +17,9 @@ public static class Web /// public const string AcceptPreviewCookieName = "UMB-WEBSITE-PREVIEW-ACCEPT"; + /// + /// The installer cookie name (obsolete). + /// [Obsolete("InstallerCookieName is no longer used and will be removed in Umbraco 19.")] public const string InstallerCookieName = "umb_installId"; @@ -40,16 +43,40 @@ public static class Web /// public const string CacheBusterToken = "%CACHE_BUSTER%"; + /// + /// Contains MVC area and path constants for Umbraco routing. + /// public static class Mvc { + /// + /// The MVC area name for the Umbraco installer. + /// public const string InstallArea = "UmbracoInstall"; + /// + /// The path segment prefix for all backoffice controllers. + /// public const string BackOfficePathSegment = "BackOffice"; // The path segment prefix for all back office controllers + /// + /// The MVC area name for backoffice non-API controllers. + /// public const string BackOfficeArea = "UmbracoBackOffice"; // Used for area routes of non-api controllers + + /// + /// The MVC area name for backoffice API controllers. + /// public const string BackOfficeApiArea = "UmbracoApi"; // Same name as v8 so all routing remains the same + + /// + /// The MVC area name for backoffice tree controllers. + /// public const string BackOfficeTreeArea = "UmbracoTrees"; // Same name as v8 so all routing remains the same + + /// + /// The MVC area name for backoffice login controllers. + /// public const string BackOfficeLoginArea = "UmbracoLogin"; // Used for area routes of non-api controllers for login } @@ -57,37 +84,113 @@ public const string /// The "base" path to the Management API /// public const string ManagementApiPath = "/management/api/"; + + /// + /// The SignalR hub path for backoffice real-time communication. + /// public const string BackofficeSignalRHub = "/backofficeHub"; + + /// + /// The SignalR hub path for server-sent events. + /// public const string ServerEventSignalRHub = "/serverEventHub"; + /// + /// Contains routing token constants used in MVC routing. + /// public static class Routing { + /// + /// The route token name for the controller. + /// public const string ControllerToken = "controller"; + + /// + /// The route token name for the action. + /// public const string ActionToken = "action"; + + /// + /// The route token name for the area. + /// public const string AreaToken = "area"; + + /// + /// The dynamic route pattern used for Umbraco content routing. + /// public const string DynamicRoutePattern = "/{**umbracoSlug}"; } + /// + /// Contains route path segment constants used in API routing. + /// public static class RoutePath { + /// + /// The route path segment for tree endpoints. + /// public const string Tree = "tree"; + + /// + /// The route path segment for recycle bin endpoints. + /// public const string RecycleBin = "recycle-bin"; + + /// + /// The route path segment for item endpoints. + /// public const string Item = "item"; + + /// + /// The route path segment for collection endpoints. + /// public const string Collection = "collection"; + + /// + /// The route path segment for filter endpoints. + /// public const string Filter = "filter"; } + /// + /// Contains attribute routing constants. + /// public static class AttributeRouting { + /// + /// The backoffice route token used in attribute routing. + /// public const string BackOfficeToken = "umbracoBackOffice"; } + /// + /// Contains email type constants used for categorizing outgoing emails. + /// public static class EmailTypes { + /// + /// The email type for health check notifications. + /// public const string HealthCheck = "HealthCheck"; + + /// + /// The email type for general notifications. + /// public const string Notification = "Notification"; + + /// + /// The email type for password reset emails. + /// public const string PasswordReset = "PasswordReset"; + + /// + /// The email type for two-factor authentication emails. + /// public const string TwoFactorAuth = "2FA"; + + /// + /// The email type for user invitation emails. + /// public const string UserInvite = "UserInvite"; } } diff --git a/src/Umbraco.Core/Constants-WebhookEvents.cs b/src/Umbraco.Core/Constants-WebhookEvents.cs index 6c8e012bf8b5..fa03cc3f1710 100644 --- a/src/Umbraco.Core/Constants-WebhookEvents.cs +++ b/src/Umbraco.Core/Constants-WebhookEvents.cs @@ -2,8 +2,14 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains constants for webhook events. + /// public static class WebhookEvents { + /// + /// Contains HTTP header name constants for webhook requests. + /// public static class HeaderNames { /// @@ -17,6 +23,9 @@ public static class HeaderNames public const string RetryCount = "Umb-Webhook-RetryCount"; } + /// + /// Contains webhook event alias constants. + /// public static class Aliases { /// @@ -405,6 +414,9 @@ public static class Aliases public const string UserUnlocked = "userUnlocked"; } + /// + /// Contains webhook event type category constants. + /// public static class Types { /// diff --git a/src/Umbraco.Core/Constants-Webhooks.cs b/src/Umbraco.Core/Constants-Webhooks.cs index 0a9cb9514672..b2f73e4d9472 100644 --- a/src/Umbraco.Core/Constants-Webhooks.cs +++ b/src/Umbraco.Core/Constants-Webhooks.cs @@ -4,6 +4,9 @@ namespace Umbraco.Cms.Core; public static partial class Constants { + /// + /// Contains constants for webhook configuration. + /// public static class Webhooks { /// diff --git a/src/Umbraco.Core/ConventionsHelper.cs b/src/Umbraco.Core/ConventionsHelper.cs index 697b3904f5c2..de665337c2ed 100644 --- a/src/Umbraco.Core/ConventionsHelper.cs +++ b/src/Umbraco.Core/ConventionsHelper.cs @@ -3,8 +3,16 @@ namespace Umbraco.Cms.Core; +/// +/// Provides helper methods for working with Umbraco conventions. +/// public static class ConventionsHelper { + /// + /// Gets the standard property type stubs used by the system. + /// + /// The short string helper for string operations. + /// A dictionary of standard property types, currently empty. public static Dictionary GetStandardPropertyTypeStubs(IShortStringHelper shortStringHelper) => new(); } diff --git a/src/Umbraco.Core/CustomBooleanTypeConverter.cs b/src/Umbraco.Core/CustomBooleanTypeConverter.cs index bacfec7ef9aa..48db2a221ccd 100644 --- a/src/Umbraco.Core/CustomBooleanTypeConverter.cs +++ b/src/Umbraco.Core/CustomBooleanTypeConverter.cs @@ -8,6 +8,7 @@ namespace Umbraco.Cms.Core; /// public class CustomBooleanTypeConverter : BooleanConverter { + /// public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) { if (sourceType == typeof(string)) @@ -18,6 +19,7 @@ public override bool CanConvertFrom(ITypeDescriptorContext? context, Type source return base.CanConvertFrom(context, sourceType); } + /// public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) { if (value is string str) diff --git a/src/Umbraco.Core/DefaultEventMessagesFactory.cs b/src/Umbraco.Core/DefaultEventMessagesFactory.cs index 9648e76fcabf..600d989459d2 100644 --- a/src/Umbraco.Core/DefaultEventMessagesFactory.cs +++ b/src/Umbraco.Core/DefaultEventMessagesFactory.cs @@ -2,15 +2,24 @@ namespace Umbraco.Cms.Core; +/// +/// Default implementation of that creates and manages event messages. +/// public class DefaultEventMessagesFactory : IEventMessagesFactory { private readonly IEventMessagesAccessor _eventMessagesAccessor; + /// + /// Initializes a new instance of the class. + /// + /// The accessor for getting and setting event messages. + /// The event messages accessor is null. public DefaultEventMessagesFactory(IEventMessagesAccessor eventMessagesAccessor) { _eventMessagesAccessor = eventMessagesAccessor ?? throw new ArgumentNullException(nameof(eventMessagesAccessor)); } + /// public EventMessages Get() { EventMessages? eventMessages = _eventMessagesAccessor.EventMessages; @@ -22,5 +31,6 @@ public EventMessages Get() return eventMessages; } + /// public EventMessages? GetOrDefault() => _eventMessagesAccessor.EventMessages; } diff --git a/src/Umbraco.Core/DelegateEqualityComparer.cs b/src/Umbraco.Core/DelegateEqualityComparer.cs index 44d12364cbdb..6e38fa34c263 100644 --- a/src/Umbraco.Core/DelegateEqualityComparer.cs +++ b/src/Umbraco.Core/DelegateEqualityComparer.cs @@ -11,12 +11,23 @@ public class DelegateEqualityComparer : IEqualityComparer #region Implementation of IEqualityComparer + /// + /// Initializes a new instance of the class. + /// + /// A delegate that determines if two objects are equal. + /// A delegate that returns the hash code for an object. public DelegateEqualityComparer(Func equals, Func getHashcode) { _getHashcode = getHashcode; _equals = equals; } + /// + /// Creates a that compares objects based on a specific member. + /// + /// The type of the member to compare. + /// A function that extracts the member to compare. + /// A new instance. public static DelegateEqualityComparer CompareMember(Func memberExpression) where TMember : IEquatable => new DelegateEqualityComparer( diff --git a/src/Umbraco.Core/DeliveryApi/Accessors/NoopOutputExpansionStrategyAccessor.cs b/src/Umbraco.Core/DeliveryApi/Accessors/NoopOutputExpansionStrategyAccessor.cs index 4b4aad50c055..cb60f9b9d2b5 100644 --- a/src/Umbraco.Core/DeliveryApi/Accessors/NoopOutputExpansionStrategyAccessor.cs +++ b/src/Umbraco.Core/DeliveryApi/Accessors/NoopOutputExpansionStrategyAccessor.cs @@ -1,9 +1,13 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; namespace Umbraco.Cms.Core.DeliveryApi.Accessors; +/// +/// A no-operation implementation of that always returns a . +/// public sealed class NoopOutputExpansionStrategyAccessor : IOutputExpansionStrategyAccessor { + /// public bool TryGetValue([NotNullWhen(true)] out IOutputExpansionStrategy? outputExpansionStrategy) { outputExpansionStrategy = new NoopOutputExpansionStrategy(); diff --git a/src/Umbraco.Core/DeliveryApi/Accessors/NoopRequestStartItemProviderAccessor.cs b/src/Umbraco.Core/DeliveryApi/Accessors/NoopRequestStartItemProviderAccessor.cs index 37754db47279..d492f9e43fa6 100644 --- a/src/Umbraco.Core/DeliveryApi/Accessors/NoopRequestStartItemProviderAccessor.cs +++ b/src/Umbraco.Core/DeliveryApi/Accessors/NoopRequestStartItemProviderAccessor.cs @@ -1,9 +1,13 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; namespace Umbraco.Cms.Core.DeliveryApi.Accessors; +/// +/// A no-operation implementation of that always returns a . +/// public sealed class NoopRequestStartItemProviderAccessor : IRequestStartItemProviderAccessor { + /// public bool TryGetValue([NotNullWhen(true)] out IRequestStartItemProvider? requestStartItemProvider) { requestStartItemProvider = new NoopRequestStartItemProvider(); diff --git a/src/Umbraco.Core/DeliveryApi/ApiContentBuilder.cs b/src/Umbraco.Core/DeliveryApi/ApiContentBuilder.cs index 1fcdf24da24a..6f517e7bcdc0 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiContentBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiContentBuilder.cs @@ -5,8 +5,18 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Default implementation of that builds API content objects for the Delivery API. +/// public sealed class ApiContentBuilder : ApiContentBuilderBase, IApiContentBuilder { + /// + /// Initializes a new instance of the class. + /// + /// The API content name provider. + /// The API content route builder. + /// The output expansion strategy accessor. + /// The variation context accessor. public ApiContentBuilder( IApiContentNameProvider apiContentNameProvider, IApiContentRouteBuilder apiContentRouteBuilder, @@ -16,6 +26,7 @@ public ApiContentBuilder( { } + /// protected override IApiContent Create(IPublishedContent content, string name, IApiContentRoute route, IDictionary properties) => new ApiContent(content.Key, name, content.ContentType.Alias, content.CreateDate, content.CultureDate(VariationContextAccessor), route, properties); } diff --git a/src/Umbraco.Core/DeliveryApi/ApiContentBuilderBase.cs b/src/Umbraco.Core/DeliveryApi/ApiContentBuilderBase.cs index 93d5ece42248..0051d0ac55ff 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiContentBuilderBase.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiContentBuilderBase.cs @@ -1,15 +1,26 @@ -using Umbraco.Cms.Core.Models.DeliveryApi; +using Umbraco.Cms.Core.Models.DeliveryApi; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Extensions; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Base class for building instances from published content. +/// +/// The type of API content to build. public abstract class ApiContentBuilderBase where T : IApiContent { private readonly IApiContentNameProvider _apiContentNameProvider; private readonly IOutputExpansionStrategyAccessor _outputExpansionStrategyAccessor; + /// + /// Initializes a new instance of the class. + /// + /// The API content name provider. + /// The API content route builder. + /// The output expansion strategy accessor. + /// The variation context accessor. protected ApiContentBuilderBase( IApiContentNameProvider apiContentNameProvider, IApiContentRouteBuilder apiContentRouteBuilder, @@ -22,12 +33,31 @@ protected ApiContentBuilderBase( VariationContextAccessor = variationContextAccessor; } + /// + /// Gets the API content route builder. + /// protected IApiContentRouteBuilder ApiContentRouteBuilder { get; } + /// + /// Gets the variation context accessor. + /// protected IVariationContextAccessor VariationContextAccessor { get; } + /// + /// Creates an API content instance from the specified parameters. + /// + /// The published content. + /// The name of the content. + /// The route of the content. + /// The properties of the content. + /// An API content instance. protected abstract T Create(IPublishedContent content, string name, IApiContentRoute route, IDictionary properties); + /// + /// Builds an API content instance from the specified published content. + /// + /// The published content to build from. + /// An API content instance, or null if the content cannot be built. public virtual T? Build(IPublishedContent content) { IApiContentRoute? route = ApiContentRouteBuilder.Build(content, VariationContextAccessor.VariationContext?.Culture); diff --git a/src/Umbraco.Core/DeliveryApi/ApiContentNameProvider.cs b/src/Umbraco.Core/DeliveryApi/ApiContentNameProvider.cs index ec4d37ad1eca..1404f4a4f752 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiContentNameProvider.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiContentNameProvider.cs @@ -2,7 +2,11 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Default implementation of that provides content names for the Delivery API. +/// public sealed class ApiContentNameProvider : IApiContentNameProvider { + /// public string GetName(IPublishedContent content) => content.Name; } diff --git a/src/Umbraco.Core/DeliveryApi/ApiContentPathProvider.cs b/src/Umbraco.Core/DeliveryApi/ApiContentPathProvider.cs index 231bd496f259..339b60df471a 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiContentPathProvider.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiContentPathProvider.cs @@ -3,14 +3,24 @@ namespace Umbraco.Cms.Core.DeliveryApi; -// NOTE: left unsealed on purpose so it is extendable. +/// +/// Default implementation of that provides content paths for the Delivery API. +/// +/// +/// This class is left unsealed on purpose so it is extendable. +/// public class ApiContentPathProvider : IApiContentPathProvider { private readonly IPublishedUrlProvider _publishedUrlProvider; + /// + /// Initializes a new instance of the class. + /// + /// The published URL provider. public ApiContentPathProvider(IPublishedUrlProvider publishedUrlProvider) => _publishedUrlProvider = publishedUrlProvider; + /// public virtual string GetContentPath(IPublishedContent content, string? culture) => _publishedUrlProvider.GetUrl(content, UrlMode.Relative, culture); } diff --git a/src/Umbraco.Core/DeliveryApi/ApiContentPathResolver.cs b/src/Umbraco.Core/DeliveryApi/ApiContentPathResolver.cs index 4ca6be3932aa..cf4b1f319bc1 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiContentPathResolver.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiContentPathResolver.cs @@ -3,18 +3,29 @@ namespace Umbraco.Cms.Core.DeliveryApi; -// NOTE: left unsealed on purpose so it is extendable. +/// +/// Default implementation of that resolves content by URL path for the Delivery API. +/// +/// +/// This class is left unsealed on purpose so it is extendable. +/// public class ApiContentPathResolver : IApiContentPathResolver { private readonly IRequestRoutingService _requestRoutingService; private readonly IApiPublishedContentCache _apiPublishedContentCache; + /// + /// Initializes a new instance of the class. + /// + /// The request routing service. + /// The API published content cache. public ApiContentPathResolver(IRequestRoutingService requestRoutingService, IApiPublishedContentCache apiPublishedContentCache) { _requestRoutingService = requestRoutingService; _apiPublishedContentCache = apiPublishedContentCache; } + /// public virtual IPublishedContent? ResolveContentPath(string path) { path = path.EnsureStartsWith("/"); diff --git a/src/Umbraco.Core/DeliveryApi/ApiContentResponseBuilder.cs b/src/Umbraco.Core/DeliveryApi/ApiContentResponseBuilder.cs index 9d37da11f000..788d95617487 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiContentResponseBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiContentResponseBuilder.cs @@ -4,8 +4,18 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Default implementation of that builds content response objects for the Delivery API. +/// public class ApiContentResponseBuilder : ApiContentBuilderBase, IApiContentResponseBuilder { + /// + /// Initializes a new instance of the class. + /// + /// The API content name provider. + /// The API content route builder. + /// The output expansion strategy accessor. + /// The variation context accessor. public ApiContentResponseBuilder( IApiContentNameProvider apiContentNameProvider, IApiContentRouteBuilder apiContentRouteBuilder, @@ -15,12 +25,18 @@ public ApiContentResponseBuilder( { } + /// protected override IApiContentResponse Create(IPublishedContent content, string name, IApiContentRoute route, IDictionary properties) { IDictionary cultures = GetCultures(content); return new ApiContentResponse(content.Key, name, content.ContentType.Alias, content.CreateDate, content.CultureDate(VariationContextAccessor), route, properties, cultures); } + /// + /// Gets the available culture routes for the specified content. + /// + /// The published content to get culture routes for. + /// A dictionary of culture codes to their corresponding routes. protected virtual IDictionary GetCultures(IPublishedContent content) { var routesByCulture = new Dictionary(); diff --git a/src/Umbraco.Core/DeliveryApi/ApiContentRouteBuilder.cs b/src/Umbraco.Core/DeliveryApi/ApiContentRouteBuilder.cs index 93481887f77b..5324d6f5b4e6 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiContentRouteBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiContentRouteBuilder.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DependencyInjection; @@ -11,6 +11,9 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Default implementation of that builds content routes for the Delivery API. +/// public sealed class ApiContentRouteBuilder : IApiContentRouteBuilder { private readonly IApiContentPathProvider _apiContentPathProvider; @@ -23,6 +26,18 @@ public sealed class ApiContentRouteBuilder : IApiContentRouteBuilder private readonly IDocumentUrlService _documentUrlService; private RequestHandlerSettings _requestSettings; + /// + /// Initializes a new instance of the class. + /// + /// The API content path provider. + /// The global settings. + /// The variation context accessor. + /// The request preview service. + /// The request handler settings. + /// The published content cache. + /// The document navigation query service. + /// The publish status query service. + /// The document URL service. public ApiContentRouteBuilder( IApiContentPathProvider apiContentPathProvider, IOptions globalSettings, @@ -46,6 +61,7 @@ public ApiContentRouteBuilder( requestSettings.OnChange(settings => _requestSettings = settings); } + /// public IApiContentRoute? Build(IPublishedContent content, string? culture = null) { if (content.ItemType != PublishedItemType.Content) diff --git a/src/Umbraco.Core/DeliveryApi/ApiDocumentUrlService.cs b/src/Umbraco.Core/DeliveryApi/ApiDocumentUrlService.cs index f17eba49d0cc..b1175f6ca85f 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiDocumentUrlService.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiDocumentUrlService.cs @@ -1,15 +1,23 @@ -using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Services; using Umbraco.Extensions; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Default implementation of that retrieves document information by URL route. +/// public sealed class ApiDocumentUrlService : IApiDocumentUrlService { private readonly IDocumentUrlService _documentUrlService; + /// + /// Initializes a new instance of the class. + /// + /// The document URL service. public ApiDocumentUrlService(IDocumentUrlService documentUrlService) => _documentUrlService = documentUrlService; + /// public Guid? GetDocumentKeyByRoute(string route, string? culture, bool preview) { // Handle the nasty logic with domain document ids in front of paths. diff --git a/src/Umbraco.Core/DeliveryApi/ApiElementBuilder.cs b/src/Umbraco.Core/DeliveryApi/ApiElementBuilder.cs index c24dde469a8b..3d7a8a401393 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiElementBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiElementBuilder.cs @@ -3,15 +3,23 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Default implementation of that builds API element objects for the Delivery API. +/// public sealed class ApiElementBuilder : IApiElementBuilder { private readonly IOutputExpansionStrategyAccessor _outputExpansionStrategyAccessor; + /// + /// Initializes a new instance of the class. + /// + /// The output expansion strategy accessor. public ApiElementBuilder(IOutputExpansionStrategyAccessor outputExpansionStrategyAccessor) { _outputExpansionStrategyAccessor = outputExpansionStrategyAccessor; } + /// public IApiElement Build(IPublishedElement element) { IDictionary properties = diff --git a/src/Umbraco.Core/DeliveryApi/ApiMediaBuilder.cs b/src/Umbraco.Core/DeliveryApi/ApiMediaBuilder.cs index fa74aee7b212..6e47d1eb3742 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiMediaBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiMediaBuilder.cs @@ -1,9 +1,12 @@ -using Umbraco.Cms.Core.Models.DeliveryApi; +using Umbraco.Cms.Core.Models.DeliveryApi; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Extensions; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Default implementation of that builds API media objects for the Delivery API. +/// public sealed class ApiMediaBuilder : IApiMediaBuilder { private readonly IApiContentNameProvider _apiContentNameProvider; @@ -11,6 +14,13 @@ public sealed class ApiMediaBuilder : IApiMediaBuilder private readonly IPublishedValueFallback _publishedValueFallback; private readonly IOutputExpansionStrategyAccessor _outputExpansionStrategyAccessor; + /// + /// Initializes a new instance of the class. + /// + /// The API content name provider. + /// The API media URL provider. + /// The published value fallback service. + /// The output expansion strategy accessor. public ApiMediaBuilder( IApiContentNameProvider apiContentNameProvider, IApiMediaUrlProvider apiMediaUrlProvider, @@ -23,6 +33,7 @@ public ApiMediaBuilder( _outputExpansionStrategyAccessor = outputExpansionStrategyAccessor; } + /// public IApiMedia Build(IPublishedContent media) => new ApiMedia( media.Key, diff --git a/src/Umbraco.Core/DeliveryApi/ApiMediaUrlProvider.cs b/src/Umbraco.Core/DeliveryApi/ApiMediaUrlProvider.cs index f8ebee826b63..411ec69612ad 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiMediaUrlProvider.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiMediaUrlProvider.cs @@ -1,15 +1,23 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Routing; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Default implementation of that provides media URLs for the Delivery API. +/// public sealed class ApiMediaUrlProvider : IApiMediaUrlProvider { private readonly IPublishedUrlProvider _publishedUrlProvider; + /// + /// Initializes a new instance of the class. + /// + /// The published URL provider. public ApiMediaUrlProvider(IPublishedUrlProvider publishedUrlProvider) => _publishedUrlProvider = publishedUrlProvider; + /// public string GetUrl(IPublishedContent media) { if (media.ItemType != PublishedItemType.Media) diff --git a/src/Umbraco.Core/DeliveryApi/ApiPropertyRenderer.cs b/src/Umbraco.Core/DeliveryApi/ApiPropertyRenderer.cs index 82d92148bdc5..5a144934e0b8 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiPropertyRenderer.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiPropertyRenderer.cs @@ -1,14 +1,22 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Default implementation of that renders property values for the Delivery API. +/// public class ApiPropertyRenderer : IApiPropertyRenderer { private readonly IPublishedValueFallback _publishedValueFallback; + /// + /// Initializes a new instance of the class. + /// + /// The published value fallback service. public ApiPropertyRenderer(IPublishedValueFallback publishedValueFallback) => _publishedValueFallback = publishedValueFallback; + /// public object? GetPropertyValue(IPublishedProperty property, bool expanding) { if (property.HasValue()) diff --git a/src/Umbraco.Core/DeliveryApi/ApiPublishedContentCache.cs b/src/Umbraco.Core/DeliveryApi/ApiPublishedContentCache.cs index 0e48262e733e..11a94403e402 100644 --- a/src/Umbraco.Core/DeliveryApi/ApiPublishedContentCache.cs +++ b/src/Umbraco.Core/DeliveryApi/ApiPublishedContentCache.cs @@ -6,6 +6,9 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Default implementation of that provides access to published content for the Delivery API. +/// public sealed class ApiPublishedContentCache : IApiPublishedContentCache { private readonly IRequestPreviewService _requestPreviewService; @@ -14,6 +17,14 @@ public sealed class ApiPublishedContentCache : IApiPublishedContentCache private readonly IVariationContextAccessor _variationContextAccessor; private DeliveryApiSettings _deliveryApiSettings; + /// + /// Initializes a new instance of the class. + /// + /// The request preview service. + /// The Delivery API settings. + /// The API document URL service. + /// The published content cache. + /// The variation context accessor. public ApiPublishedContentCache( IRequestPreviewService requestPreviewService, IOptionsMonitor deliveryApiSettings, @@ -29,6 +40,7 @@ public ApiPublishedContentCache( deliveryApiSettings.OnChange(settings => _deliveryApiSettings = settings); } + /// public async Task GetByRouteAsync(string route) { var isPreviewMode = _requestPreviewService.IsPreview(); @@ -45,6 +57,7 @@ public ApiPublishedContentCache( return ContentOrNullIfDisallowed(content); } + /// public IPublishedContent? GetByRoute(string route) { var isPreviewMode = _requestPreviewService.IsPreview(); @@ -86,18 +99,21 @@ public ApiPublishedContentCache( return ContentOrNullIfDisallowed(content); } + /// public async Task GetByIdAsync(Guid contentId) { IPublishedContent? content = await _publishedContentCache.GetByIdAsync(contentId, _requestPreviewService.IsPreview()).ConfigureAwait(false); return ContentOrNullIfDisallowed(content); } + /// public IPublishedContent? GetById(Guid contentId) { IPublishedContent? content = _publishedContentCache.GetById(_requestPreviewService.IsPreview(), contentId); return ContentOrNullIfDisallowed(content); } + /// public async Task> GetByIdsAsync(IEnumerable contentIds) { var isPreviewMode = _requestPreviewService.IsPreview(); @@ -113,6 +129,7 @@ public async Task> GetByIdsAsync(IEnumerable public IEnumerable GetByIds(IEnumerable contentIds) { var isPreviewMode = _requestPreviewService.IsPreview(); diff --git a/src/Umbraco.Core/DeliveryApi/ContentIndexHandlerCollection.cs b/src/Umbraco.Core/DeliveryApi/ContentIndexHandlerCollection.cs index 55326102f416..d5bb15c6ac19 100644 --- a/src/Umbraco.Core/DeliveryApi/ContentIndexHandlerCollection.cs +++ b/src/Umbraco.Core/DeliveryApi/ContentIndexHandlerCollection.cs @@ -1,9 +1,16 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A collection of implementations for the Delivery API. +/// public sealed class ContentIndexHandlerCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the content index handlers. public ContentIndexHandlerCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/DeliveryApi/ContentIndexHandlerCollectionBuilder.cs b/src/Umbraco.Core/DeliveryApi/ContentIndexHandlerCollectionBuilder.cs index 95744d9a230f..4b0e7174bf04 100644 --- a/src/Umbraco.Core/DeliveryApi/ContentIndexHandlerCollectionBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/ContentIndexHandlerCollectionBuilder.cs @@ -1,9 +1,13 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A collection builder for implementations. +/// public sealed class ContentIndexHandlerCollectionBuilder : LazyCollectionBuilderBase { + /// protected override ContentIndexHandlerCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/DeliveryApi/DeliveryApiCompositeIdHandler.cs b/src/Umbraco.Core/DeliveryApi/DeliveryApiCompositeIdHandler.cs index a3c1f0fceb77..de4408e078fe 100644 --- a/src/Umbraco.Core/DeliveryApi/DeliveryApiCompositeIdHandler.cs +++ b/src/Umbraco.Core/DeliveryApi/DeliveryApiCompositeIdHandler.cs @@ -1,9 +1,14 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Default implementation of that handles composite ID creation and decomposition. +/// public class DeliveryApiCompositeIdHandler : IDeliveryApiCompositeIdHandler { + /// public string IndexId(int id, string culture) => $"{id}|{culture}"; + /// public DeliveryApiIndexCompositeIdModel Decompose(string indexId) { var parts = indexId.Split(Constants.CharArrays.VerticalTab); diff --git a/src/Umbraco.Core/DeliveryApi/DeliveryApiIndexCompositeIdModel.cs b/src/Umbraco.Core/DeliveryApi/DeliveryApiIndexCompositeIdModel.cs index d3b876b5aac8..8c7a7691ec15 100644 --- a/src/Umbraco.Core/DeliveryApi/DeliveryApiIndexCompositeIdModel.cs +++ b/src/Umbraco.Core/DeliveryApi/DeliveryApiIndexCompositeIdModel.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Represents the decomposed components of a composite ID used in the Delivery API index. +/// public class DeliveryApiIndexCompositeIdModel { + /// + /// Gets or sets the content ID component of the composite ID. + /// public int? Id { get; set; } + /// + /// Gets or sets the culture component of the composite ID. + /// public string? Culture { get; set; } } diff --git a/src/Umbraco.Core/DeliveryApi/FieldType.cs b/src/Umbraco.Core/DeliveryApi/FieldType.cs index 5bd7df8298c8..35e61956ee10 100644 --- a/src/Umbraco.Core/DeliveryApi/FieldType.cs +++ b/src/Umbraco.Core/DeliveryApi/FieldType.cs @@ -1,10 +1,32 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Specifies the type of a field in the Delivery API content index. +/// public enum FieldType { + /// + /// A raw string field that is not analyzed. + /// StringRaw, + + /// + /// A string field that is analyzed for full-text search. + /// StringAnalyzed, + + /// + /// A string field that is optimized for sorting. + /// StringSortable, + + /// + /// A numeric field. + /// Number, + + /// + /// A date/time field. + /// Date } diff --git a/src/Umbraco.Core/DeliveryApi/FilterHandlerCollection.cs b/src/Umbraco.Core/DeliveryApi/FilterHandlerCollection.cs index 97bdae961988..40c8e32e01bf 100644 --- a/src/Umbraco.Core/DeliveryApi/FilterHandlerCollection.cs +++ b/src/Umbraco.Core/DeliveryApi/FilterHandlerCollection.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A collection of implementations for the Delivery API. +/// public sealed class FilterHandlerCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the filter handlers. public FilterHandlerCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/DeliveryApi/FilterHandlerCollectionBuilder.cs b/src/Umbraco.Core/DeliveryApi/FilterHandlerCollectionBuilder.cs index 76adbfa21e4d..5eb7082ba6b0 100644 --- a/src/Umbraco.Core/DeliveryApi/FilterHandlerCollectionBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/FilterHandlerCollectionBuilder.cs @@ -2,8 +2,12 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A collection builder for implementations. +/// public sealed class FilterHandlerCollectionBuilder : LazyCollectionBuilderBase { + /// protected override FilterHandlerCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/DeliveryApi/FilterOperation.cs b/src/Umbraco.Core/DeliveryApi/FilterOperation.cs index 6b897fd27d13..9b487b13dafa 100644 --- a/src/Umbraco.Core/DeliveryApi/FilterOperation.cs +++ b/src/Umbraco.Core/DeliveryApi/FilterOperation.cs @@ -1,13 +1,47 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Specifies the type of filter operation to apply in Delivery API queries. +/// public enum FilterOperation { + /// + /// Exact equality match. + /// Is, + + /// + /// Not equal to the specified value. + /// IsNot, + + /// + /// Contains the specified value. + /// Contains, + + /// + /// Does not contain the specified value. + /// DoesNotContain, + + /// + /// Less than the specified value. + /// LessThan, + + /// + /// Less than or equal to the specified value. + /// LessThanOrEqual, + + /// + /// Greater than the specified value. + /// GreaterThan, + + /// + /// Greater than or equal to the specified value. + /// GreaterThanOrEqual } diff --git a/src/Umbraco.Core/DeliveryApi/FilterOption.cs b/src/Umbraco.Core/DeliveryApi/FilterOption.cs index 037a3a52eb78..4ddc80030fcc 100644 --- a/src/Umbraco.Core/DeliveryApi/FilterOption.cs +++ b/src/Umbraco.Core/DeliveryApi/FilterOption.cs @@ -1,10 +1,22 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Represents a filter option used for filtering query results in the Delivery API. +/// public sealed class FilterOption { + /// + /// Gets or sets the name of the field to filter on. + /// public required string FieldName { get; set; } + /// + /// Gets or sets the values to filter against. + /// public required string[] Values { get; set; } + /// + /// Gets or sets the filter operation to apply. + /// public required FilterOperation Operator { get; set; } } diff --git a/src/Umbraco.Core/DeliveryApi/IApiAccessService.cs b/src/Umbraco.Core/DeliveryApi/IApiAccessService.cs index e890386a3a33..55c567d2a8d4 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiAccessService.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiAccessService.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a service that determines access permissions for the Delivery API. +/// public interface IApiAccessService { /// diff --git a/src/Umbraco.Core/DeliveryApi/IApiContentBuilder.cs b/src/Umbraco.Core/DeliveryApi/IApiContentBuilder.cs index 946a75cda7d3..6861653697f7 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiContentBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiContentBuilder.cs @@ -3,7 +3,15 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a builder that creates instances from published content. +/// public interface IApiContentBuilder { + /// + /// Builds an instance from the specified published content. + /// + /// The published content to build from. + /// An instance, or null if the content cannot be built. IApiContent? Build(IPublishedContent content); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiContentNameProvider.cs b/src/Umbraco.Core/DeliveryApi/IApiContentNameProvider.cs index ace5a0095ee5..abe40cd2a178 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiContentNameProvider.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiContentNameProvider.cs @@ -2,7 +2,15 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a provider that retrieves the name of content items for the Delivery API. +/// public interface IApiContentNameProvider { + /// + /// Gets the name of the specified published content. + /// + /// The published content to get the name for. + /// The name of the content. string GetName(IPublishedContent content); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiContentPathProvider.cs b/src/Umbraco.Core/DeliveryApi/IApiContentPathProvider.cs index 11a676873bec..c438d4791ce1 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiContentPathProvider.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiContentPathProvider.cs @@ -2,7 +2,16 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a provider that retrieves the URL path of content items for the Delivery API. +/// public interface IApiContentPathProvider { + /// + /// Gets the URL path for the specified published content and culture. + /// + /// The published content to get the path for. + /// The culture to use for the path, or null for the default culture. + /// The URL path of the content, or null if no path is available. string? GetContentPath(IPublishedContent content, string? culture); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiContentPathResolver.cs b/src/Umbraco.Core/DeliveryApi/IApiContentPathResolver.cs index 391f18998e58..7911eeaaff21 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiContentPathResolver.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiContentPathResolver.cs @@ -2,7 +2,15 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a resolver that finds published content by its URL path. +/// public interface IApiContentPathResolver { + /// + /// Resolves published content from the specified URL path. + /// + /// The URL path to resolve. + /// The published content at the specified path, or null if not found. IPublishedContent? ResolveContentPath(string path); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiContentResponseBuilder.cs b/src/Umbraco.Core/DeliveryApi/IApiContentResponseBuilder.cs index 1d025ecadfc7..4cd7e1f07754 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiContentResponseBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiContentResponseBuilder.cs @@ -1,9 +1,17 @@ -using Umbraco.Cms.Core.Models.DeliveryApi; +using Umbraco.Cms.Core.Models.DeliveryApi; using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a builder that creates instances from published content. +/// public interface IApiContentResponseBuilder { + /// + /// Builds an instance from the specified published content. + /// + /// The published content to build from. + /// An instance, or null if the content cannot be built. IApiContentResponse? Build(IPublishedContent content); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiContentRouteBuilder.cs b/src/Umbraco.Core/DeliveryApi/IApiContentRouteBuilder.cs index dbd110335399..54ca699cfe72 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiContentRouteBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiContentRouteBuilder.cs @@ -1,9 +1,18 @@ -using Umbraco.Cms.Core.Models.DeliveryApi; +using Umbraco.Cms.Core.Models.DeliveryApi; using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a builder that creates instances from published content. +/// public interface IApiContentRouteBuilder { + /// + /// Builds an instance from the specified published content. + /// + /// The published content to build from. + /// The culture to use for the route, or null for the default culture. + /// An instance, or null if the route cannot be built. IApiContentRoute? Build(IPublishedContent content, string? culture = null); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiDocumentUrlService.cs b/src/Umbraco.Core/DeliveryApi/IApiDocumentUrlService.cs index 7792fa8a472e..64d2f76d25ab 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiDocumentUrlService.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiDocumentUrlService.cs @@ -1,6 +1,16 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a service that retrieves document information by URL route for the Delivery API. +/// public interface IApiDocumentUrlService { + /// + /// Gets the document key (unique identifier) for the specified route. + /// + /// The URL route to look up. + /// The culture to use for the lookup, or null for the default culture. + /// Whether to include unpublished preview content in the lookup. + /// The document key if found, or null if no document exists at the specified route. Guid? GetDocumentKeyByRoute(string route, string? culture, bool preview); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiElementBuilder.cs b/src/Umbraco.Core/DeliveryApi/IApiElementBuilder.cs index 09fe845f8844..20c16c6b3598 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiElementBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiElementBuilder.cs @@ -3,7 +3,15 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a builder that creates instances from published elements. +/// public interface IApiElementBuilder { + /// + /// Builds an instance from the specified published element. + /// + /// The published element to build from. + /// An instance. IApiElement Build(IPublishedElement element); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiMediaBuilder.cs b/src/Umbraco.Core/DeliveryApi/IApiMediaBuilder.cs index 68bcb83a51be..be08143c248f 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiMediaBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiMediaBuilder.cs @@ -1,9 +1,17 @@ -using Umbraco.Cms.Core.Models.DeliveryApi; +using Umbraco.Cms.Core.Models.DeliveryApi; using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a builder that creates instances from published media. +/// public interface IApiMediaBuilder { + /// + /// Builds an instance from the specified published media. + /// + /// The published media to build from. + /// An instance. IApiMedia Build(IPublishedContent media); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiMediaUrlProvider.cs b/src/Umbraco.Core/DeliveryApi/IApiMediaUrlProvider.cs index 71c44653f03f..2c99524a727a 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiMediaUrlProvider.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiMediaUrlProvider.cs @@ -1,8 +1,16 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a provider that retrieves URLs for media items in the Delivery API. +/// public interface IApiMediaUrlProvider { + /// + /// Gets the URL for the specified media item. + /// + /// The published media to get the URL for. + /// The URL of the media item. string GetUrl(IPublishedContent media); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiPropertyRenderer.cs b/src/Umbraco.Core/DeliveryApi/IApiPropertyRenderer.cs index 0ba90a6d918d..cb0a4d389d60 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiPropertyRenderer.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiPropertyRenderer.cs @@ -1,8 +1,17 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a renderer that converts published property values for Delivery API responses. +/// public interface IApiPropertyRenderer { + /// + /// Gets the rendered value of a property for the Delivery API response. + /// + /// The published property to render. + /// Whether the property value should be expanded. + /// The rendered property value. object? GetPropertyValue(IPublishedProperty property, bool expanding); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiPublishedContentCache.cs b/src/Umbraco.Core/DeliveryApi/IApiPublishedContentCache.cs index d72eacd1c1cf..d25293d07647 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiPublishedContentCache.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiPublishedContentCache.cs @@ -1,16 +1,51 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a cache for accessing published content through the Delivery API. +/// public interface IApiPublishedContentCache { + /// + /// Gets published content by its route. + /// + /// The content route. + /// The published content, or null if not found. IPublishedContent? GetByRoute(string route); + /// + /// Gets published content by its unique identifier. + /// + /// The content's unique identifier. + /// The published content, or null if not found. IPublishedContent? GetById(Guid contentId); + /// + /// Gets multiple published content items by their unique identifiers. + /// + /// The content unique identifiers. + /// The published content items that were found. IEnumerable GetByIds(IEnumerable contentIds); + /// + /// Asynchronously gets published content by its unique identifier. + /// + /// The content's unique identifier. + /// A task containing the published content, or null if not found. Task GetByIdAsync(Guid contentId) => Task.FromResult(GetById(contentId)); + + /// + /// Asynchronously gets published content by its route. + /// + /// The content route. + /// A task containing the published content, or null if not found. Task GetByRouteAsync(string route) => Task.FromResult(GetByRoute(route)); + + /// + /// Asynchronously gets multiple published content items by their unique identifiers. + /// + /// The content unique identifiers. + /// A task containing the published content items that were found. Task> GetByIdsAsync(IEnumerable contentIds) => Task.FromResult(GetByIds(contentIds)); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiRichTextElementParser.cs b/src/Umbraco.Core/DeliveryApi/IApiRichTextElementParser.cs index a43fcd0a605a..b1b0a6b3c987 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiRichTextElementParser.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiRichTextElementParser.cs @@ -3,7 +3,16 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a parser that processes rich text content into structured elements for the Delivery API. +/// public interface IApiRichTextElementParser { + /// + /// Parses HTML markup and optional block model into a rich text element. + /// + /// The HTML markup to parse. + /// The optional rich text block model containing embedded blocks. + /// A rich text element, or null if parsing fails. IRichTextElement? Parse(string html, RichTextBlockModel? richTextBlockModel); } diff --git a/src/Umbraco.Core/DeliveryApi/IApiRichTextMarkupParser.cs b/src/Umbraco.Core/DeliveryApi/IApiRichTextMarkupParser.cs index 4a6c41be290b..0ee9995b8ff9 100644 --- a/src/Umbraco.Core/DeliveryApi/IApiRichTextMarkupParser.cs +++ b/src/Umbraco.Core/DeliveryApi/IApiRichTextMarkupParser.cs @@ -1,6 +1,14 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a parser that processes rich text HTML markup for the Delivery API. +/// public interface IApiRichTextMarkupParser { + /// + /// Parses the specified HTML markup for Delivery API output. + /// + /// The HTML markup to parse. + /// The parsed HTML markup. string Parse(string html); } diff --git a/src/Umbraco.Core/DeliveryApi/ICurrentMemberClaimsProvider.cs b/src/Umbraco.Core/DeliveryApi/ICurrentMemberClaimsProvider.cs index cd636cb06e09..d8017beefff5 100644 --- a/src/Umbraco.Core/DeliveryApi/ICurrentMemberClaimsProvider.cs +++ b/src/Umbraco.Core/DeliveryApi/ICurrentMemberClaimsProvider.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a provider that retrieves claims for the currently logged in member. +/// public interface ICurrentMemberClaimsProvider { /// diff --git a/src/Umbraco.Core/DeliveryApi/IDeliveryApiCompositeIdHandler.cs b/src/Umbraco.Core/DeliveryApi/IDeliveryApiCompositeIdHandler.cs index a472d0f9ffc2..4736c6bbd4fe 100644 --- a/src/Umbraco.Core/DeliveryApi/IDeliveryApiCompositeIdHandler.cs +++ b/src/Umbraco.Core/DeliveryApi/IDeliveryApiCompositeIdHandler.cs @@ -1,8 +1,22 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a handler for creating and decomposing composite IDs used in the Delivery API index. +/// public interface IDeliveryApiCompositeIdHandler { + /// + /// Creates a composite index ID from the specified content ID and culture. + /// + /// The content ID. + /// The culture code. + /// A composite index ID string. string IndexId(int id, string culture); + /// + /// Decomposes a composite index ID into its component parts. + /// + /// The composite index ID to decompose. + /// A containing the decomposed ID and culture. DeliveryApiIndexCompositeIdModel Decompose(string indexId); } diff --git a/src/Umbraco.Core/DeliveryApi/IOutputExpansionStrategy.cs b/src/Umbraco.Core/DeliveryApi/IOutputExpansionStrategy.cs index 97d0cf598b20..5bd6abe28da3 100644 --- a/src/Umbraco.Core/DeliveryApi/IOutputExpansionStrategy.cs +++ b/src/Umbraco.Core/DeliveryApi/IOutputExpansionStrategy.cs @@ -1,12 +1,31 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a strategy for mapping and expanding properties in Delivery API responses. +/// public interface IOutputExpansionStrategy { + /// + /// Maps the properties of an element for the API response. + /// + /// The published element to map properties for. + /// A dictionary of property aliases to their values. IDictionary MapElementProperties(IPublishedElement element); + /// + /// Maps the properties of content for the API response. + /// + /// The published content to map properties for. + /// A dictionary of property aliases to their values. IDictionary MapContentProperties(IPublishedContent content); + /// + /// Maps the properties of media for the API response. + /// + /// The published media to map properties for. + /// Whether to skip built-in Umbraco properties that start with "umbraco". + /// A dictionary of property aliases to their values. IDictionary MapMediaProperties(IPublishedContent media, bool skipUmbracoProperties = true); } diff --git a/src/Umbraco.Core/DeliveryApi/IOutputExpansionStrategyAccessor.cs b/src/Umbraco.Core/DeliveryApi/IOutputExpansionStrategyAccessor.cs index ea7188d0ce5b..8e501ad9dda4 100644 --- a/src/Umbraco.Core/DeliveryApi/IOutputExpansionStrategyAccessor.cs +++ b/src/Umbraco.Core/DeliveryApi/IOutputExpansionStrategyAccessor.cs @@ -1,8 +1,16 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines an accessor for retrieving the current . +/// public interface IOutputExpansionStrategyAccessor { + /// + /// Attempts to get the current output expansion strategy. + /// + /// When this method returns, contains the output expansion strategy if available; otherwise, null. + /// true if the output expansion strategy was retrieved; otherwise, false. bool TryGetValue([NotNullWhen(true)] out IOutputExpansionStrategy? outputExpansionStrategy); } diff --git a/src/Umbraco.Core/DeliveryApi/IQueryHandler.cs b/src/Umbraco.Core/DeliveryApi/IQueryHandler.cs index 0c1a7c72b481..a3e75d4b6fff 100644 --- a/src/Umbraco.Core/DeliveryApi/IQueryHandler.cs +++ b/src/Umbraco.Core/DeliveryApi/IQueryHandler.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Base interface for query handlers in the Delivery API. +/// public interface IQueryHandler : IDiscoverable { /// diff --git a/src/Umbraco.Core/DeliveryApi/IRequestCultureService.cs b/src/Umbraco.Core/DeliveryApi/IRequestCultureService.cs index 7295d865b6bc..9fd02ce7267a 100644 --- a/src/Umbraco.Core/DeliveryApi/IRequestCultureService.cs +++ b/src/Umbraco.Core/DeliveryApi/IRequestCultureService.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a service that retrieves the requested culture from the current HTTP request. +/// public interface IRequestCultureService { /// diff --git a/src/Umbraco.Core/DeliveryApi/IRequestMemberAccessService.cs b/src/Umbraco.Core/DeliveryApi/IRequestMemberAccessService.cs index 9d43a15a7a53..9581b49c040a 100644 --- a/src/Umbraco.Core/DeliveryApi/IRequestMemberAccessService.cs +++ b/src/Umbraco.Core/DeliveryApi/IRequestMemberAccessService.cs @@ -4,9 +4,21 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a service that handles member access checks for the Delivery API. +/// public interface IRequestMemberAccessService { + /// + /// Determines whether the current member has access to the specified content. + /// + /// The published content to check access for. + /// The access status indicating whether the member can access the content. Task MemberHasAccessToAsync(IPublishedContent content); + /// + /// Gets the protected access information for the current member. + /// + /// The protected access information. Task MemberAccessAsync(); } diff --git a/src/Umbraco.Core/DeliveryApi/IRequestPreviewService.cs b/src/Umbraco.Core/DeliveryApi/IRequestPreviewService.cs index c605c417300d..da2ad5188ef5 100644 --- a/src/Umbraco.Core/DeliveryApi/IRequestPreviewService.cs +++ b/src/Umbraco.Core/DeliveryApi/IRequestPreviewService.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a service that determines whether the current request is in preview mode. +/// public interface IRequestPreviewService { /// diff --git a/src/Umbraco.Core/DeliveryApi/IRequestRedirectService.cs b/src/Umbraco.Core/DeliveryApi/IRequestRedirectService.cs index c2a8312d8e4f..ee5588d7fc27 100644 --- a/src/Umbraco.Core/DeliveryApi/IRequestRedirectService.cs +++ b/src/Umbraco.Core/DeliveryApi/IRequestRedirectService.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a service that handles redirects for Delivery API requests. +/// public interface IRequestRedirectService { /// diff --git a/src/Umbraco.Core/DeliveryApi/IRequestRoutingService.cs b/src/Umbraco.Core/DeliveryApi/IRequestRoutingService.cs index 10d8203676da..85257a87a42c 100644 --- a/src/Umbraco.Core/DeliveryApi/IRequestRoutingService.cs +++ b/src/Umbraco.Core/DeliveryApi/IRequestRoutingService.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a service that handles routing for Delivery API requests. +/// public interface IRequestRoutingService { /// diff --git a/src/Umbraco.Core/DeliveryApi/IRequestSegmentService.cs b/src/Umbraco.Core/DeliveryApi/IRequestSegmentService.cs index 7eb11c358344..a96ab9ee108a 100644 --- a/src/Umbraco.Core/DeliveryApi/IRequestSegmentService.cs +++ b/src/Umbraco.Core/DeliveryApi/IRequestSegmentService.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a service that retrieves the requested segment from the current HTTP request. +/// public interface IRequestSegmentService { /// @@ -8,6 +11,12 @@ public interface IRequestSegmentService string? GetRequestedSegment(); } +/// +/// Defines a service that retrieves the requested segment from the current HTTP request. +/// +/// +/// This interface is misspelled and will be removed in Umbraco 18. Please use the correct one . +/// [Obsolete("This interface is misspelled and will be removed in Umbraco 18. Please use the correct one IRequestSegmentService")] public interface IRequestSegmmentService { diff --git a/src/Umbraco.Core/DeliveryApi/IRequestStartItemProvider.cs b/src/Umbraco.Core/DeliveryApi/IRequestStartItemProvider.cs index 6276b59cd9e3..acc37c617b2b 100644 --- a/src/Umbraco.Core/DeliveryApi/IRequestStartItemProvider.cs +++ b/src/Umbraco.Core/DeliveryApi/IRequestStartItemProvider.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines a provider that retrieves the start item for Delivery API requests. +/// public interface IRequestStartItemProvider { /// diff --git a/src/Umbraco.Core/DeliveryApi/IRequestStartItemProviderAccessor.cs b/src/Umbraco.Core/DeliveryApi/IRequestStartItemProviderAccessor.cs index f913c97b7766..fb170ba5bd4c 100644 --- a/src/Umbraco.Core/DeliveryApi/IRequestStartItemProviderAccessor.cs +++ b/src/Umbraco.Core/DeliveryApi/IRequestStartItemProviderAccessor.cs @@ -1,8 +1,16 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Defines an accessor for retrieving the current . +/// public interface IRequestStartItemProviderAccessor { + /// + /// Attempts to get the current request start item provider. + /// + /// When this method returns, contains the request start item provider if available; otherwise, null. + /// true if the request start item provider was retrieved; otherwise, false. bool TryGetValue([NotNullWhen(true)] out IRequestStartItemProvider? requestStartItemProvider); } diff --git a/src/Umbraco.Core/DeliveryApi/IncludeInApiVersionAttribute.cs b/src/Umbraco.Core/DeliveryApi/IncludeInApiVersionAttribute.cs index f336126b8237..8d1de672c251 100644 --- a/src/Umbraco.Core/DeliveryApi/IncludeInApiVersionAttribute.cs +++ b/src/Umbraco.Core/DeliveryApi/IncludeInApiVersionAttribute.cs @@ -1,10 +1,19 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Specifies that the property should be included in the Delivery API response based on API version constraints. +/// [AttributeUsage(AttributeTargets.Property)] public class IncludeInApiVersionAttribute : Attribute { + /// + /// Gets the minimum API version (inclusive) for which the property should be included, or null if no minimum is specified. + /// public int? MinVersion { get; } + /// + /// Gets the maximum API version (inclusive) for which the property should be included, or null if no maximum is specified. + /// public int? MaxVersion { get; } /// diff --git a/src/Umbraco.Core/DeliveryApi/IndexField.cs b/src/Umbraco.Core/DeliveryApi/IndexField.cs index 61092500c69a..f2337052bb2e 100644 --- a/src/Umbraco.Core/DeliveryApi/IndexField.cs +++ b/src/Umbraco.Core/DeliveryApi/IndexField.cs @@ -1,10 +1,22 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Represents a field definition for the Delivery API content index. +/// public sealed class IndexField { + /// + /// Gets or sets the name of the index field. + /// public required string FieldName { get; set; } + /// + /// Gets or sets the type of the index field. + /// public required FieldType FieldType { get; set; } + /// + /// Gets or sets a value indicating whether this field varies by culture. + /// public required bool VariesByCulture { get; set; } } diff --git a/src/Umbraco.Core/DeliveryApi/IndexFieldValue.cs b/src/Umbraco.Core/DeliveryApi/IndexFieldValue.cs index 7bec3444db05..785241538fd9 100644 --- a/src/Umbraco.Core/DeliveryApi/IndexFieldValue.cs +++ b/src/Umbraco.Core/DeliveryApi/IndexFieldValue.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Represents a field value for the Delivery API content index. +/// public sealed class IndexFieldValue { + /// + /// Gets or sets the name of the index field. + /// public required string FieldName { get; set; } + /// + /// Gets or sets the values for this index field. + /// public required IEnumerable Values { get; set; } } diff --git a/src/Umbraco.Core/DeliveryApi/NoopApiAccessService.cs b/src/Umbraco.Core/DeliveryApi/NoopApiAccessService.cs index 3559b1046425..7eed3018ba6b 100644 --- a/src/Umbraco.Core/DeliveryApi/NoopApiAccessService.cs +++ b/src/Umbraco.Core/DeliveryApi/NoopApiAccessService.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A no-operation implementation of that denies all access. +/// public sealed class NoopApiAccessService : IApiAccessService { /// diff --git a/src/Umbraco.Core/DeliveryApi/NoopApiContentQueryService.cs b/src/Umbraco.Core/DeliveryApi/NoopApiContentQueryService.cs index d88384ab58ba..d08429cc215e 100644 --- a/src/Umbraco.Core/DeliveryApi/NoopApiContentQueryService.cs +++ b/src/Umbraco.Core/DeliveryApi/NoopApiContentQueryService.cs @@ -4,6 +4,9 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A no-operation implementation of that always returns an empty result. +/// public sealed class NoopApiContentQueryService : IApiContentQueryService { /// diff --git a/src/Umbraco.Core/DeliveryApi/NoopApiMediaQueryService.cs b/src/Umbraco.Core/DeliveryApi/NoopApiMediaQueryService.cs index c7f6bc8797a4..1f7edb8c0bd4 100644 --- a/src/Umbraco.Core/DeliveryApi/NoopApiMediaQueryService.cs +++ b/src/Umbraco.Core/DeliveryApi/NoopApiMediaQueryService.cs @@ -1,9 +1,12 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A no-operation implementation of that always returns empty results. +/// public sealed class NoopApiMediaQueryService : IApiMediaQueryService { /// diff --git a/src/Umbraco.Core/DeliveryApi/NoopCurrentMemberClaimsProvider.cs b/src/Umbraco.Core/DeliveryApi/NoopCurrentMemberClaimsProvider.cs index 8080c27562e2..e5cff5c3a59e 100644 --- a/src/Umbraco.Core/DeliveryApi/NoopCurrentMemberClaimsProvider.cs +++ b/src/Umbraco.Core/DeliveryApi/NoopCurrentMemberClaimsProvider.cs @@ -1,6 +1,10 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A no-operation implementation of that returns empty claims. +/// public class NoopCurrentMemberClaimsProvider : ICurrentMemberClaimsProvider { + /// public Task> GetClaimsAsync() => Task.FromResult(new Dictionary()); } diff --git a/src/Umbraco.Core/DeliveryApi/NoopOutputExpansionStrategy.cs b/src/Umbraco.Core/DeliveryApi/NoopOutputExpansionStrategy.cs index 8a2f29763451..65e1c83391e8 100644 --- a/src/Umbraco.Core/DeliveryApi/NoopOutputExpansionStrategy.cs +++ b/src/Umbraco.Core/DeliveryApi/NoopOutputExpansionStrategy.cs @@ -1,15 +1,21 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A no-operation implementation of that maps all properties without expansion. +/// internal sealed class NoopOutputExpansionStrategy : IOutputExpansionStrategy { + /// public IDictionary MapElementProperties(IPublishedElement element) => MapProperties(element.Properties); + /// public IDictionary MapContentProperties(IPublishedContent content) => MapProperties(content.Properties); + /// public IDictionary MapMediaProperties(IPublishedContent media, bool skipUmbracoProperties = true) => MapProperties(media.Properties.Where(p => skipUmbracoProperties is false || p.Alias.StartsWith("umbraco") is false)); diff --git a/src/Umbraco.Core/DeliveryApi/NoopRequestCultureService.cs b/src/Umbraco.Core/DeliveryApi/NoopRequestCultureService.cs index 8b9cec3aa954..3ef1eee17359 100644 --- a/src/Umbraco.Core/DeliveryApi/NoopRequestCultureService.cs +++ b/src/Umbraco.Core/DeliveryApi/NoopRequestCultureService.cs @@ -1,11 +1,17 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A no-operation implementation of that does not track or return cultures. +/// public sealed class NoopRequestCultureService : IRequestCultureService { /// public string? GetRequestedCulture() => null; - /// + /// + /// Sets the request culture. This implementation does nothing. + /// + /// The culture to set. public void SetRequestCulture(string culture) { } diff --git a/src/Umbraco.Core/DeliveryApi/NoopRequestMemberAccessService.cs b/src/Umbraco.Core/DeliveryApi/NoopRequestMemberAccessService.cs index ce282bb45528..bbab819e5111 100644 --- a/src/Umbraco.Core/DeliveryApi/NoopRequestMemberAccessService.cs +++ b/src/Umbraco.Core/DeliveryApi/NoopRequestMemberAccessService.cs @@ -4,9 +4,14 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A no-operation implementation of that always grants access. +/// public sealed class NoopRequestMemberAccessService : IRequestMemberAccessService { + /// public Task MemberHasAccessToAsync(IPublishedContent content) => Task.FromResult(PublicAccessStatus.AccessAccepted); + /// public Task MemberAccessAsync() => Task.FromResult(ProtectedAccess.None); } diff --git a/src/Umbraco.Core/DeliveryApi/NoopRequestPreviewService.cs b/src/Umbraco.Core/DeliveryApi/NoopRequestPreviewService.cs index c7adf31ee122..09f30cb3fa62 100644 --- a/src/Umbraco.Core/DeliveryApi/NoopRequestPreviewService.cs +++ b/src/Umbraco.Core/DeliveryApi/NoopRequestPreviewService.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A no-operation implementation of that always returns false for preview mode. +/// public sealed class NoopRequestPreviewService : IRequestPreviewService { /// diff --git a/src/Umbraco.Core/DeliveryApi/NoopRequestRedirectService.cs b/src/Umbraco.Core/DeliveryApi/NoopRequestRedirectService.cs index 51437bb68324..fc7328438895 100644 --- a/src/Umbraco.Core/DeliveryApi/NoopRequestRedirectService.cs +++ b/src/Umbraco.Core/DeliveryApi/NoopRequestRedirectService.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A no-operation implementation of that never returns redirects. +/// public sealed class NoopRequestRedirectService : IRequestRedirectService { /// diff --git a/src/Umbraco.Core/DeliveryApi/NoopRequestRoutingService.cs b/src/Umbraco.Core/DeliveryApi/NoopRequestRoutingService.cs index 50451a713cca..ee802a95fbba 100644 --- a/src/Umbraco.Core/DeliveryApi/NoopRequestRoutingService.cs +++ b/src/Umbraco.Core/DeliveryApi/NoopRequestRoutingService.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.DeliveryApi; +namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A no-operation implementation of that returns the requested path as-is. +/// public sealed class NoopRequestRoutingService : IRequestRoutingService { /// diff --git a/src/Umbraco.Core/DeliveryApi/NoopRequestStartItemProvider.cs b/src/Umbraco.Core/DeliveryApi/NoopRequestStartItemProvider.cs index 46da70cbcf2b..f4410fe21c68 100644 --- a/src/Umbraco.Core/DeliveryApi/NoopRequestStartItemProvider.cs +++ b/src/Umbraco.Core/DeliveryApi/NoopRequestStartItemProvider.cs @@ -1,7 +1,10 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A no-operation implementation of that never returns a start item. +/// internal sealed class NoopRequestStartItemProvider : IRequestStartItemProvider { /// diff --git a/src/Umbraco.Core/DeliveryApi/SelectorHandlerCollection.cs b/src/Umbraco.Core/DeliveryApi/SelectorHandlerCollection.cs index 06943c3a35ab..02b305857579 100644 --- a/src/Umbraco.Core/DeliveryApi/SelectorHandlerCollection.cs +++ b/src/Umbraco.Core/DeliveryApi/SelectorHandlerCollection.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A collection of implementations for the Delivery API. +/// public sealed class SelectorHandlerCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the selector handlers. public SelectorHandlerCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/DeliveryApi/SelectorHandlerCollectionBuilder.cs b/src/Umbraco.Core/DeliveryApi/SelectorHandlerCollectionBuilder.cs index 164da2696674..574157989677 100644 --- a/src/Umbraco.Core/DeliveryApi/SelectorHandlerCollectionBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/SelectorHandlerCollectionBuilder.cs @@ -2,8 +2,12 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A collection builder for implementations. +/// public sealed class SelectorHandlerCollectionBuilder : LazyCollectionBuilderBase { + /// protected override SelectorHandlerCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/DeliveryApi/SelectorOption.cs b/src/Umbraco.Core/DeliveryApi/SelectorOption.cs index 1626bc7b5152..d0eeb02efe21 100644 --- a/src/Umbraco.Core/DeliveryApi/SelectorOption.cs +++ b/src/Umbraco.Core/DeliveryApi/SelectorOption.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Represents a selector option used for content querying in the Delivery API. +/// public sealed class SelectorOption { + /// + /// Gets or sets the name of the field to select on. + /// public required string FieldName { get; set; } + /// + /// Gets or sets the values to match against the field. + /// public required string[] Values { get; set; } } diff --git a/src/Umbraco.Core/DeliveryApi/SortHandlerCollection.cs b/src/Umbraco.Core/DeliveryApi/SortHandlerCollection.cs index 77b649d38716..69243de54826 100644 --- a/src/Umbraco.Core/DeliveryApi/SortHandlerCollection.cs +++ b/src/Umbraco.Core/DeliveryApi/SortHandlerCollection.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A collection of implementations for the Delivery API. +/// public sealed class SortHandlerCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the sort handlers. public SortHandlerCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/DeliveryApi/SortHandlerCollectionBuilder.cs b/src/Umbraco.Core/DeliveryApi/SortHandlerCollectionBuilder.cs index be4189989af5..0ddab9e97848 100644 --- a/src/Umbraco.Core/DeliveryApi/SortHandlerCollectionBuilder.cs +++ b/src/Umbraco.Core/DeliveryApi/SortHandlerCollectionBuilder.cs @@ -2,8 +2,12 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// A collection builder for implementations. +/// public sealed class SortHandlerCollectionBuilder : LazyCollectionBuilderBase { + /// protected override SortHandlerCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/DeliveryApi/SortOption.cs b/src/Umbraco.Core/DeliveryApi/SortOption.cs index 3bab63b4a1ac..b3e14702d39c 100644 --- a/src/Umbraco.Core/DeliveryApi/SortOption.cs +++ b/src/Umbraco.Core/DeliveryApi/SortOption.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.DeliveryApi; +/// +/// Represents a sort option used for ordering query results in the Delivery API. +/// public sealed class SortOption { + /// + /// Gets or sets the name of the field to sort by. + /// public required string FieldName { get; set; } + /// + /// Gets or sets the sort direction. + /// public required Direction Direction { get; set; } } diff --git a/src/Umbraco.Core/DependencyInjection/IUmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/IUmbracoBuilder.cs index 23f59d57b75a..487772e192a2 100644 --- a/src/Umbraco.Core/DependencyInjection/IUmbracoBuilder.cs +++ b/src/Umbraco.Core/DependencyInjection/IUmbracoBuilder.cs @@ -7,12 +7,24 @@ namespace Umbraco.Cms.Core.DependencyInjection; +/// +/// Represents the Umbraco builder used to configure services and dependencies during application startup. +/// public interface IUmbracoBuilder { + /// + /// Gets the where services are configured. + /// IServiceCollection Services { get; } + /// + /// Gets the containing the application configuration properties. + /// IConfiguration Config { get; } + /// + /// Gets the used for type discovery and loading. + /// TypeLoader TypeLoader { get; } /// @@ -21,12 +33,26 @@ public interface IUmbracoBuilder /// ILoggerFactory BuilderLoggerFactory { get; } + /// + /// Gets the used for performance profiling. + /// IProfiler Profiler { get; } + /// + /// Gets the containing the application caches. + /// AppCaches AppCaches { get; } + /// + /// Gets a collection builder and registers the collection. + /// + /// The type of the collection builder. + /// The collection builder instance. TBuilder WithCollectionBuilder() where TBuilder : ICollectionBuilder; + /// + /// Builds the Umbraco services by registering all configured collection builders with the service collection. + /// void Build(); } diff --git a/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs b/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs index 555ce5208ada..de6c2407777b 100644 --- a/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Umbraco.Core/DependencyInjection/ServiceCollectionExtensions.cs @@ -4,6 +4,12 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for to register services with unique semantics. +/// +/// +/// These methods ensure that only one registration exists for a given service type by removing previous registrations. +/// public static class ServiceCollectionExtensions { /// @@ -153,6 +159,11 @@ public static IServiceCollection AddUnique(this IServiceCollection ser return services; } + /// + /// Adds support for resolving dependencies from the service collection. + /// + /// The service collection. + /// A reference to this instance after the operation has completed. internal static IServiceCollection AddLazySupport(this IServiceCollection services) { services.Replace(ServiceDescriptor.Transient(typeof(Lazy<>), typeof(LazyResolve<>))); diff --git a/src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs b/src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs index a12cc21dd6e9..a8ead74b53c6 100644 --- a/src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs +++ b/src/Umbraco.Core/DependencyInjection/ServiceProviderExtensions.cs @@ -42,6 +42,11 @@ public static T CreateInstance(this IServiceProvider serviceProvider, params public static object CreateInstance(this IServiceProvider serviceProvider, Type type, params object[] args) => ActivatorUtilities.CreateInstance(serviceProvider, type, args); + /// + /// Creates the default published model factory using types discovered by the type loader. + /// + /// The service provider. + /// A new instance configured with discovered model types. [EditorBrowsable(EditorBrowsableState.Never)] public static PublishedModelFactory CreateDefaultPublishedModelFactory(this IServiceProvider factory) { diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs index dafbaff4df5a..1825f0ab4754 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Collections.cs @@ -124,6 +124,11 @@ public static ActionCollectionBuilder Actions(this IUmbracoBuilder builder) public static ContentFinderCollectionBuilder ContentFinders(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); + /// + /// Gets the event source authorizers collection builder. + /// + /// The builder. + /// The . public static EventSourceAuthorizerCollectionBuilder EventSourceAuthorizers(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); @@ -141,6 +146,11 @@ public static EditorValidatorCollectionBuilder EditorValidators(this IUmbracoBui public static HealthCheckCollectionBuilder HealthChecks(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); + /// + /// Gets the health check notification methods collection builder. + /// + /// The builder. + /// The . public static HealthCheckNotificationMethodCollectionBuilder HealthCheckNotificationMethods(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); @@ -158,9 +168,19 @@ public static UrlProviderCollectionBuilder UrlProviders(this IUmbracoBuilder bui public static MediaUrlProviderCollectionBuilder MediaUrlProviders(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); + /// + /// Gets the dynamic root origin finders collection builder. + /// + /// The builder. + /// The . public static DynamicRootOriginFinderCollectionBuilder DynamicRootOriginFinders(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); + /// + /// Gets the dynamic root query steps collection builder. + /// + /// The builder. + /// The . public static DynamicRootQueryStepCollectionBuilder DynamicRootSteps(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); @@ -240,33 +260,42 @@ public static EmbedProvidersCollectionBuilder EmbedProviders(this IUmbracoBuilde => builder.WithCollectionBuilder(); /// - /// Gets the Delivery API selector handler collection builder + /// Gets the Delivery API selector handler collection builder. /// + /// The builder. + /// The . public static SelectorHandlerCollectionBuilder SelectorHandlers(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); /// - /// Gets the Delivery API filter handler collection builder + /// Gets the Delivery API filter handler collection builder. /// + /// The builder. + /// The . public static FilterHandlerCollectionBuilder FilterHandlers(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); /// - /// Gets the Delivery API sort handler collection builder + /// Gets the Delivery API sort handler collection builder. /// + /// The builder. + /// The . public static SortHandlerCollectionBuilder SortHandlers(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); /// - /// Gets the Delivery API content index handler collection builder + /// Gets the Delivery API content index handler collection builder. /// + /// The builder. + /// The . public static ContentIndexHandlerCollectionBuilder ContentIndexHandlers(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); /// - /// Gets the content type filters collection builder. + /// Gets the content type filters collection builder. /// /// The builder. + /// The . public static ContentTypeFilterCollectionBuilder ContentTypeFilters(this IUmbracoBuilder builder) => builder.WithCollectionBuilder(); } diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs index db436b867064..9c1ffb96d4c4 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Configuration.cs @@ -14,6 +14,14 @@ namespace Umbraco.Cms.Core.DependencyInjection; /// public static partial class UmbracoBuilderExtensions { + /// + /// Adds Umbraco options of type to the builder. + /// + /// The type of options to add. Must have the . + /// The builder. + /// Optional action to configure the . + /// The . + /// Thrown when does not have the . private static IUmbracoBuilder AddUmbracoOptions(this IUmbracoBuilder builder, Action>? configure = null) where TOptions : class { diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs index 844c52a5ab0b..267be5636624 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs @@ -44,6 +44,13 @@ public static IUmbracoBuilder AddNotificationAsyncHandler + /// Registers a notification handler against the service collection. + /// + /// The type of notification. + /// The type of notification handler. + /// The service collection. + /// The . internal static IServiceCollection AddNotificationHandler( this IServiceCollection services) where TNotificationHandler : INotificationHandler @@ -63,6 +70,13 @@ internal static IServiceCollection AddNotificationHandler + /// Registers a notification async handler against the service collection. + /// + /// The type of notification. + /// The type of notification async handler. + /// The service collection. + /// The . internal static IServiceCollection AddNotificationAsyncHandler( this IServiceCollection services) where TNotificationAsyncHandler : INotificationAsyncHandler diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs index edee671b8ed7..78b9255dda70 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs @@ -54,21 +54,29 @@ namespace Umbraco.Cms.Core.DependencyInjection { + /// + /// The default implementation of used to configure Umbraco services and dependencies. + /// public class UmbracoBuilder : IUmbracoBuilder { private readonly Dictionary _builders = new Dictionary(); + /// public IServiceCollection Services { get; } + /// public IConfiguration Config { get; } + /// public TypeLoader TypeLoader { get; } /// public ILoggerFactory BuilderLoggerFactory { get; } + /// public IProfiler Profiler { get; } + /// public AppCaches AppCaches { get; } /// @@ -133,6 +141,7 @@ public TBuilder WithCollectionBuilder() return builder; } + /// public void Build() { foreach (ICollectionBuilder builder in _builders.Values) @@ -143,6 +152,9 @@ public void Build() _builders.Clear(); } + /// + /// Adds all core Umbraco services to the service collection. + /// private void AddCoreServices() { Services.AddSingleton(AppCaches); diff --git a/src/Umbraco.Core/Diagnostics/MiniDump.cs b/src/Umbraco.Core/Diagnostics/MiniDump.cs index c553f921af62..5e3f13650efd 100644 --- a/src/Umbraco.Core/Diagnostics/MiniDump.cs +++ b/src/Umbraco.Core/Diagnostics/MiniDump.cs @@ -4,39 +4,142 @@ namespace Umbraco.Cms.Core.Diagnostics; -// taken from https://blogs.msdn.microsoft.com/dondu/2010/10/24/writing-minidumps-in-c/ -// and https://blogs.msdn.microsoft.com/dondu/2010/10/31/writing-minidumps-from-exceptions-in-c/ -// which itself got it from http://blog.kalmbach-software.de/2008/12/13/writing-minidumps-in-c/ +/// +/// Provides functionality to create Windows minidump files for diagnostic purposes. +/// +/// +/// +/// This class enables the creation of memory dump files that can be analyzed +/// to diagnose application crashes and other issues. +/// +/// +/// Based on: https://blogs.msdn.microsoft.com/dondu/2010/10/24/writing-minidumps-in-c/ +/// and https://blogs.msdn.microsoft.com/dondu/2010/10/31/writing-minidumps-from-exceptions-in-c/ +/// which itself got it from http://blog.kalmbach-software.de/2008/12/13/writing-minidumps-in-c/ +/// +/// public static class MiniDump { private static readonly Lock LockO = new(); + /// + /// Specifies the type of information to include in the minidump file. + /// + /// + /// These values correspond to the MINIDUMP_TYPE enumeration in dbghelp.h. + /// [Flags] public enum Option : uint { - // From dbghelp.h: + /// + /// Include just the information necessary to capture stack traces for all existing threads in a process. + /// Normal = 0x00000000, + + /// + /// Include the data sections from all loaded modules. + /// WithDataSegs = 0x00000001, + + /// + /// Include all accessible memory in the process. + /// WithFullMemory = 0x00000002, + + /// + /// Include high-level information about the operating system handles. + /// WithHandleData = 0x00000004, + + /// + /// Stack and backing store memory written to the minidump file should be filtered. + /// FilterMemory = 0x00000008, + + /// + /// Stack and backing store memory should be scanned for pointer references to modules. + /// ScanMemory = 0x00000010, + + /// + /// Include information from the list of modules that were recently unloaded. + /// WithUnloadedModules = 0x00000020, + + /// + /// Include pages with data referenced by locals or other stack memory. + /// WithIndirectlyReferencedMemory = 0x00000040, + + /// + /// Filter module paths for information such as user names or important directories. + /// FilterModulePaths = 0x00000080, + + /// + /// Include complete per-process and per-thread information. + /// WithProcessThreadData = 0x00000100, + + /// + /// Scan the virtual address space for PAGE_READWRITE memory to be included. + /// WithPrivateReadWriteMemory = 0x00000200, + + /// + /// Reduce the data that is dumped by eliminating memory regions that are not essential. + /// WithoutOptionalData = 0x00000400, + + /// + /// Include memory region information. + /// WithFullMemoryInfo = 0x00000800, + + /// + /// Include thread state information. + /// WithThreadInfo = 0x00001000, + + /// + /// Include all code and code-related sections from loaded modules. + /// WithCodeSegs = 0x00002000, + + /// + /// Turns off secondary auxiliary-supported memory gathering. + /// WithoutAuxiliaryState = 0x00004000, + + /// + /// Requests that auxiliary data providers include their state in the dump. + /// WithFullAuxiliaryState = 0x00008000, + + /// + /// Scan the virtual address space for PAGE_WRITECOPY memory to be included. + /// WithPrivateWriteCopyMemory = 0x00010000, + + /// + /// Ignore inaccessible memory during memory enumeration. + /// IgnoreInaccessibleMemory = 0x00020000, + + /// + /// Mask of all valid type flags. + /// ValidTypeFlags = 0x0003ffff, } + /// + /// Creates a minidump file in the MiniDump directory. + /// + /// The marshalling interface for getting exception pointers. + /// The hosting environment for path resolution. + /// The dump options specifying what information to include. + /// Whether to include exception information in the dump. + /// true if the dump was created successfully; otherwise, false. public static bool Dump(IMarchal marchal, IHostingEnvironment hostingEnvironment, Option options = Option.WithFullMemory, bool withException = false) { lock (LockO) @@ -127,6 +230,14 @@ private static bool Write(IMarchal marchal, SafeHandle fileHandle, Option option } } + /// + /// Determines whether it is safe to create a new dump file. + /// + /// The hosting environment for path resolution. + /// true if fewer than 8 dump files exist; otherwise, false. + /// + /// This method limits the number of dump files to prevent disk space exhaustion. + /// public static bool OkToDump(IHostingEnvironment hostingEnvironment) { lock (LockO) @@ -142,16 +253,29 @@ public static bool OkToDump(IHostingEnvironment hostingEnvironment) } } - // typedef struct _MINIDUMP_EXCEPTION_INFORMATION { - // DWORD ThreadId; - // PEXCEPTION_POINTERS ExceptionPointers; - // BOOL ClientPointers; - // } MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION; - [StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64! + /// + /// Contains information about the exception that caused the dump. + /// + /// + /// This structure maps to the Windows MINIDUMP_EXCEPTION_INFORMATION structure. + /// Pack=4 is important so it works for both x86 and x64. + /// + [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct MiniDumpExceptionInformation { + /// + /// The identifier of the thread that caused the exception. + /// public uint ThreadId; + + /// + /// A pointer to an EXCEPTION_POINTERS structure. + /// public IntPtr ExceptionPointers; + + /// + /// Indicates whether the exception pointers are in client memory. + /// [MarshalAs(UnmanagedType.Bool)] public bool ClientPointers; } diff --git a/src/Umbraco.Core/Diagnostics/NoopMarchal.cs b/src/Umbraco.Core/Diagnostics/NoopMarchal.cs index 991426aab99d..7b1dbf4ca13a 100644 --- a/src/Umbraco.Core/Diagnostics/NoopMarchal.cs +++ b/src/Umbraco.Core/Diagnostics/NoopMarchal.cs @@ -1,6 +1,13 @@ namespace Umbraco.Cms.Core.Diagnostics; +/// +/// A no-operation implementation of that returns null pointers. +/// +/// +/// This implementation is used on platforms where minidump functionality is not supported. +/// internal sealed class NoopMarchal : IMarchal { + /// public IntPtr GetExceptionPointers() => IntPtr.Zero; } diff --git a/src/Umbraco.Core/Dictionary/DefaultCultureDictionary.cs b/src/Umbraco.Core/Dictionary/DefaultCultureDictionary.cs index 9c6caba2d592..fa4b25d64d47 100644 --- a/src/Umbraco.Core/Dictionary/DefaultCultureDictionary.cs +++ b/src/Umbraco.Core/Dictionary/DefaultCultureDictionary.cs @@ -139,5 +139,10 @@ public IDictionary GetChildren(string key) return result; } + /// + /// Determines whether the specified translation matches the current language. + /// + /// The dictionary translation to check. + /// true if the translation's language ISO code matches the current language; otherwise, false. private bool IsCurrentLanguage(IDictionaryTranslation translation) => translation.LanguageIsoCode.Equals(Language?.IsoCode); } diff --git a/src/Umbraco.Core/Dictionary/DefaultCultureDictionaryFactory.cs b/src/Umbraco.Core/Dictionary/DefaultCultureDictionaryFactory.cs index 2f00114c13a8..273aad718619 100644 --- a/src/Umbraco.Core/Dictionary/DefaultCultureDictionaryFactory.cs +++ b/src/Umbraco.Core/Dictionary/DefaultCultureDictionaryFactory.cs @@ -16,15 +16,22 @@ public class DefaultCultureDictionaryFactory : ICultureDictionaryFactory private readonly AppCaches _appCaches; private readonly ILocalizationService _localizationService; + /// + /// Initializes a new instance of the class. + /// + /// The localization service for accessing dictionary items. + /// The application caches containing the request cache. public DefaultCultureDictionaryFactory(ILocalizationService localizationService, AppCaches appCaches) { _localizationService = localizationService; _appCaches = appCaches; } + /// public ICultureDictionary CreateDictionary() => new DefaultCultureDictionary(_localizationService, _appCaches.RequestCache); + /// public ICultureDictionary CreateDictionary(CultureInfo specificCulture) => new DefaultCultureDictionary(specificCulture, _localizationService, _appCaches.RequestCache); } diff --git a/src/Umbraco.Core/Dictionary/ICultureDictionaryFactory.cs b/src/Umbraco.Core/Dictionary/ICultureDictionaryFactory.cs index 242cfb8e3575..2754d3854975 100644 --- a/src/Umbraco.Core/Dictionary/ICultureDictionaryFactory.cs +++ b/src/Umbraco.Core/Dictionary/ICultureDictionaryFactory.cs @@ -2,9 +2,26 @@ namespace Umbraco.Cms.Core.Dictionary; +/// +/// Factory for creating instances. +/// +/// +/// This factory allows for creating dictionaries using either the current thread's culture +/// or a specific culture. It enables flexibility in dictionary item retrieval across different +/// cultures and can be extended to support alternative storage mechanisms. +/// public interface ICultureDictionaryFactory { + /// + /// Creates a dictionary using the current thread's culture. + /// + /// A culture dictionary for the current thread's culture. ICultureDictionary CreateDictionary(); - ICultureDictionary CreateDictionary(CultureInfo specificCulture) => throw new NotImplementedException(); + /// + /// Creates a dictionary for a specific culture. + /// + /// The culture to create the dictionary for. + /// A culture dictionary for the specified culture. + ICultureDictionary CreateDictionary(CultureInfo specificCulture) => throw new NotImplementedException(); } diff --git a/src/Umbraco.Core/Direction.cs b/src/Umbraco.Core/Direction.cs index 874a00a4ac87..ffa96624ef6f 100644 --- a/src/Umbraco.Core/Direction.cs +++ b/src/Umbraco.Core/Direction.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core; +/// +/// Defines the direction for sorting operations. +/// public enum Direction { + /// + /// Ascending sort order (A to Z, 0 to 9). + /// Ascending = 0, + + /// + /// Descending sort order (Z to A, 9 to 0). + /// Descending = 1, } diff --git a/src/Umbraco.Core/DistributedLocking/IDistributedLockingMechanismFactory.cs b/src/Umbraco.Core/DistributedLocking/IDistributedLockingMechanismFactory.cs index ecc1c99cfa01..499eb8153fe9 100644 --- a/src/Umbraco.Core/DistributedLocking/IDistributedLockingMechanismFactory.cs +++ b/src/Umbraco.Core/DistributedLocking/IDistributedLockingMechanismFactory.cs @@ -5,5 +5,8 @@ namespace Umbraco.Cms.Core.DistributedLocking; /// public interface IDistributedLockingMechanismFactory { + /// + /// Gets the most appropriate distributed locking mechanism for the current environment. + /// IDistributedLockingMechanism DistributedLockingMechanism { get; } } diff --git a/src/Umbraco.Core/DynamicRoot/DynamicRootContext.cs b/src/Umbraco.Core/DynamicRoot/DynamicRootContext.cs index 755c8a3c7142..43a2fc3b1bd1 100644 --- a/src/Umbraco.Core/DynamicRoot/DynamicRootContext.cs +++ b/src/Umbraco.Core/DynamicRoot/DynamicRootContext.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.DynamicRoot; +/// +/// Represents the context for resolving a dynamic root, containing information about the current and parent content items. +/// public struct DynamicRootContext { + /// + /// Gets or sets the unique identifier of the current content item, or null when creating new content. + /// public required Guid? CurrentKey { get; set; } + /// + /// Gets or sets the unique identifier of the parent content item. + /// public required Guid ParentKey { get; set; } } diff --git a/src/Umbraco.Core/DynamicRoot/DynamicRootNodeQuery.cs b/src/Umbraco.Core/DynamicRoot/DynamicRootNodeQuery.cs index 08371e8dae7f..f9d3bc8ba19c 100644 --- a/src/Umbraco.Core/DynamicRoot/DynamicRootNodeQuery.cs +++ b/src/Umbraco.Core/DynamicRoot/DynamicRootNodeQuery.cs @@ -7,11 +7,23 @@ namespace Umbraco.Cms.Core.DynamicRoot; /// public class DynamicRootNodeQuery { + /// + /// Gets or sets the alias identifying the type of origin finder to use (e.g., "ByKey", "Root", "Current", "Parent", "Site", "ContentRoot"). + /// public required string OriginAlias { get; set; } + /// + /// Gets or sets the optional unique identifier for the origin content item, used by certain origin finders like "ByKey". + /// public Guid? OriginKey { get; set; } + /// + /// Gets or sets the context containing current and parent content information for resolving the dynamic root. + /// public required DynamicRootContext Context { get; set; } + /// + /// Gets or sets the collection of query steps to apply after finding the origin to further filter or traverse the content tree. + /// public IEnumerable QuerySteps { get; set; } = Array.Empty(); } diff --git a/src/Umbraco.Core/DynamicRoot/DynamicRootService.cs b/src/Umbraco.Core/DynamicRoot/DynamicRootService.cs index 23b8f758782a..e39d3d4890c9 100644 --- a/src/Umbraco.Core/DynamicRoot/DynamicRootService.cs +++ b/src/Umbraco.Core/DynamicRoot/DynamicRootService.cs @@ -4,17 +4,27 @@ namespace Umbraco.Cms.Core.DynamicRoot; +/// +/// Default implementation of that resolves dynamic roots for content pickers +/// using a collection of origin finders and query steps. +/// public class DynamicRootService : IDynamicRootService { private readonly DynamicRootOriginFinderCollection _originFinderCollection; private readonly DynamicRootQueryStepCollection _queryStepCollection; + /// + /// Initializes a new instance of the class. + /// + /// The collection of origin finders used to locate the starting point for dynamic root resolution. + /// The collection of query steps used to filter or traverse the content tree from the origin. public DynamicRootService(DynamicRootOriginFinderCollection originFinderCollection, DynamicRootQueryStepCollection queryStepCollection) { _originFinderCollection = originFinderCollection; _queryStepCollection = queryStepCollection; } + /// public async Task> GetDynamicRootsAsync(DynamicRootNodeQuery dynamicRootNodeQuery) { var originKey = FindOriginKey(dynamicRootNodeQuery); @@ -42,6 +52,13 @@ public async Task> GetDynamicRootsAsync(DynamicRootNodeQuery d return filtered; } + /// + /// Executes the query steps to filter the origin keys based on the specified query step. + /// + /// The collection of origin keys to filter. + /// The query step defining the filter operation to apply. + /// A collection of filtered content keys. + /// Thrown when no query step handler supports the specified alias. internal async Task> ExcuteFiltersAsync(ICollection origin, DynamicRootQueryStep dynamicRootQueryStep) { foreach (IDynamicRootQueryStep queryStep in _queryStepCollection) @@ -56,6 +73,11 @@ internal async Task> ExcuteFiltersAsync(ICollection orig throw new NotSupportedException($"Did not find any filteres that could handle {dynamicRootQueryStep.Alias}"); } + /// + /// Finds the origin key using the configured origin finders. + /// + /// The query containing the origin alias and context. + /// The unique identifier of the origin content, or null if no origin finder could resolve it. internal Guid? FindOriginKey(DynamicRootNodeQuery dynamicRootNodeQuery) { foreach (IDynamicRootOriginFinder originFinder in _originFinderCollection) @@ -71,4 +93,3 @@ internal async Task> ExcuteFiltersAsync(ICollection orig return null; } } - diff --git a/src/Umbraco.Core/DynamicRoot/IDynamicRootService.cs b/src/Umbraco.Core/DynamicRoot/IDynamicRootService.cs index 226b5d9f825c..1ccaa0b1cb82 100644 --- a/src/Umbraco.Core/DynamicRoot/IDynamicRootService.cs +++ b/src/Umbraco.Core/DynamicRoot/IDynamicRootService.cs @@ -5,5 +5,10 @@ namespace Umbraco.Cms.Core.DynamicRoot; /// public interface IDynamicRootService { + /// + /// Gets the dynamic root content keys based on the specified query. + /// + /// The query specifying the origin, context, and optional query steps for finding dynamic roots. + /// A task that represents the asynchronous operation, containing a collection of unique identifiers for the resolved dynamic root content items. Task> GetDynamicRootsAsync(DynamicRootNodeQuery dynamicRootNodeQuery); } diff --git a/src/Umbraco.Core/DynamicRoot/Origin/ByKeyDynamicRootOriginFinder.cs b/src/Umbraco.Core/DynamicRoot/Origin/ByKeyDynamicRootOriginFinder.cs index f720d08e1b73..67e21caf8c34 100644 --- a/src/Umbraco.Core/DynamicRoot/Origin/ByKeyDynamicRootOriginFinder.cs +++ b/src/Umbraco.Core/DynamicRoot/Origin/ByKeyDynamicRootOriginFinder.cs @@ -3,8 +3,15 @@ namespace Umbraco.Cms.Core.DynamicRoot.Origin; +/// +/// An origin finder that locates a content item by its unique key. +/// This finder handles the "ByKey" origin type and validates that the entity exists and is of an allowed type. +/// public class ByKeyDynamicRootOriginFinder : IDynamicRootOriginFinder { + /// + /// Gets or sets the origin type alias that this finder supports. + /// protected virtual string SupportedOriginType { get; set; } = "ByKey"; private readonly IEntityService _entityService; @@ -14,11 +21,16 @@ public class ByKeyDynamicRootOriginFinder : IDynamicRootOriginFinder Constants.ObjectTypes.Document, Constants.ObjectTypes.SystemRoot }); + /// + /// Initializes a new instance of the class. + /// + /// The entity service used to retrieve entities by key. public ByKeyDynamicRootOriginFinder(IEntityService entityService) { _entityService = entityService; } + /// public virtual Guid? FindOriginKey(DynamicRootNodeQuery query) { if (query.OriginAlias != SupportedOriginType || query.OriginKey is null) diff --git a/src/Umbraco.Core/DynamicRoot/Origin/ContentRootDynamicRootOriginFinder.cs b/src/Umbraco.Core/DynamicRoot/Origin/ContentRootDynamicRootOriginFinder.cs index 878766cbbb31..447fdb7033d9 100644 --- a/src/Umbraco.Core/DynamicRoot/Origin/ContentRootDynamicRootOriginFinder.cs +++ b/src/Umbraco.Core/DynamicRoot/Origin/ContentRootDynamicRootOriginFinder.cs @@ -1,9 +1,17 @@ namespace Umbraco.Cms.Core.DynamicRoot.Origin; +/// +/// An origin finder that returns the content root (system root) as the origin. +/// This finder handles the "ContentRoot" origin type. +/// public class ContentRootDynamicRootOriginFinder : IDynamicRootOriginFinder { + /// + /// Gets or sets the origin type alias that this finder supports. + /// protected virtual string SupportedOriginType { get; set; } = "ContentRoot"; + /// public virtual Guid? FindOriginKey(DynamicRootNodeQuery query) { if (query.OriginAlias != SupportedOriginType) diff --git a/src/Umbraco.Core/DynamicRoot/Origin/CurrentDynamicRootOriginFinder.cs b/src/Umbraco.Core/DynamicRoot/Origin/CurrentDynamicRootOriginFinder.cs index cb4bd6d26e77..07eb114aa166 100644 --- a/src/Umbraco.Core/DynamicRoot/Origin/CurrentDynamicRootOriginFinder.cs +++ b/src/Umbraco.Core/DynamicRoot/Origin/CurrentDynamicRootOriginFinder.cs @@ -2,15 +2,25 @@ namespace Umbraco.Cms.Core.DynamicRoot.Origin; +/// +/// An origin finder that uses the current content item from the context as the origin. +/// This finder handles the "Current" origin type and extends . +/// public class CurrentDynamicRootOriginFinder : ByKeyDynamicRootOriginFinder { + /// + /// Initializes a new instance of the class. + /// + /// The entity service used to retrieve entities by key. public CurrentDynamicRootOriginFinder(IEntityService entityService) : base(entityService) { } + /// protected override string SupportedOriginType { get; set; } = "Current"; + /// public override Guid? FindOriginKey(DynamicRootNodeQuery query) { query.OriginKey = query.Context.CurrentKey; diff --git a/src/Umbraco.Core/DynamicRoot/Origin/DynamicRootOriginFinderCollection.cs b/src/Umbraco.Core/DynamicRoot/Origin/DynamicRootOriginFinderCollection.cs index 1d137ca92406..b96cebb52220 100644 --- a/src/Umbraco.Core/DynamicRoot/Origin/DynamicRootOriginFinderCollection.cs +++ b/src/Umbraco.Core/DynamicRoot/Origin/DynamicRootOriginFinderCollection.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.DynamicRoot.Origin; +/// +/// A collection of implementations used to find the origin for dynamic root resolution. +/// public class DynamicRootOriginFinderCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection of origin finders. public DynamicRootOriginFinderCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/DynamicRoot/Origin/DynamicRootOriginFinderCollectionBuilder.cs b/src/Umbraco.Core/DynamicRoot/Origin/DynamicRootOriginFinderCollectionBuilder.cs index 1ee1693bb117..985fca05af3b 100644 --- a/src/Umbraco.Core/DynamicRoot/Origin/DynamicRootOriginFinderCollectionBuilder.cs +++ b/src/Umbraco.Core/DynamicRoot/Origin/DynamicRootOriginFinderCollectionBuilder.cs @@ -2,7 +2,11 @@ namespace Umbraco.Cms.Core.DynamicRoot.Origin; +/// +/// A collection builder for that allows ordered registration of implementations. +/// public class DynamicRootOriginFinderCollectionBuilder : OrderedCollectionBuilderBase { + /// protected override DynamicRootOriginFinderCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/DynamicRoot/Origin/IDynamicRootOriginFinder.cs b/src/Umbraco.Core/DynamicRoot/Origin/IDynamicRootOriginFinder.cs index 838f1822f77d..3daf1a102798 100644 --- a/src/Umbraco.Core/DynamicRoot/Origin/IDynamicRootOriginFinder.cs +++ b/src/Umbraco.Core/DynamicRoot/Origin/IDynamicRootOriginFinder.cs @@ -5,5 +5,10 @@ namespace Umbraco.Cms.Core.DynamicRoot.Origin; /// public interface IDynamicRootOriginFinder { + /// + /// Attempts to find the origin content key based on the specified query. + /// + /// The query containing the origin alias, optional origin key, and context information. + /// The unique identifier of the origin content, or null if this finder does not support the query or cannot find the origin. Guid? FindOriginKey(DynamicRootNodeQuery dynamicRootNodeQuery); } diff --git a/src/Umbraco.Core/DynamicRoot/Origin/ParentDynamicRootOriginFinder.cs b/src/Umbraco.Core/DynamicRoot/Origin/ParentDynamicRootOriginFinder.cs index 3ab6f4e71f55..d264a41cc121 100644 --- a/src/Umbraco.Core/DynamicRoot/Origin/ParentDynamicRootOriginFinder.cs +++ b/src/Umbraco.Core/DynamicRoot/Origin/ParentDynamicRootOriginFinder.cs @@ -2,14 +2,24 @@ namespace Umbraco.Cms.Core.DynamicRoot.Origin; +/// +/// An origin finder that uses the parent content item from the context as the origin. +/// This finder handles the "Parent" origin type and extends . +/// public class ParentDynamicRootOriginFinder : ByKeyDynamicRootOriginFinder { + /// + /// Initializes a new instance of the class. + /// + /// The entity service used to retrieve entities by key. public ParentDynamicRootOriginFinder(IEntityService entityService) : base(entityService) { } + /// protected override string SupportedOriginType { get; set; } = "Parent"; + /// public override Guid? FindOriginKey(DynamicRootNodeQuery query) { query.OriginKey = query.Context.ParentKey; diff --git a/src/Umbraco.Core/DynamicRoot/Origin/RootDynamicRootOriginFinder.cs b/src/Umbraco.Core/DynamicRoot/Origin/RootDynamicRootOriginFinder.cs index c5c28ffcfa2c..65585cbbdc66 100644 --- a/src/Umbraco.Core/DynamicRoot/Origin/RootDynamicRootOriginFinder.cs +++ b/src/Umbraco.Core/DynamicRoot/Origin/RootDynamicRootOriginFinder.cs @@ -4,10 +4,18 @@ namespace Umbraco.Cms.Core.DynamicRoot.Origin; +/// +/// An origin finder that locates the content tree root (first content item below the system root) for the current or parent content. +/// This finder handles the "Root" origin type and traverses the content path to find the topmost document node. +/// public class RootDynamicRootOriginFinder : IDynamicRootOriginFinder { private readonly IEntityService _entityService; + /// + /// Initializes a new instance of the class. + /// + /// The entity service used to retrieve entities and traverse the content tree. public RootDynamicRootOriginFinder(IEntityService entityService) { _entityService = entityService; @@ -18,8 +26,12 @@ public RootDynamicRootOriginFinder(IEntityService entityService) Constants.ObjectTypes.Document, Constants.ObjectTypes.SystemRoot }); + /// + /// Gets or sets the origin type alias that this finder supports. + /// protected virtual string SupportedOriginType { get; set; } = "Root"; + /// public virtual Guid? FindOriginKey(DynamicRootNodeQuery query) { if (query.OriginAlias != SupportedOriginType) @@ -55,6 +67,11 @@ public RootDynamicRootOriginFinder(IEntityService entityService) return root.Key; } + /// + /// Gets the root content ID from the path, skipping the system root and recycle bin. + /// + /// The path segments as an array of ID strings. + /// The root content ID, or null if no valid root is found. private static int? GetRootId(string[] path) { foreach (var contentId in path) diff --git a/src/Umbraco.Core/DynamicRoot/Origin/SiteDynamicRootOriginFinder.cs b/src/Umbraco.Core/DynamicRoot/Origin/SiteDynamicRootOriginFinder.cs index 1e6059361b7e..311756611c34 100644 --- a/src/Umbraco.Core/DynamicRoot/Origin/SiteDynamicRootOriginFinder.cs +++ b/src/Umbraco.Core/DynamicRoot/Origin/SiteDynamicRootOriginFinder.cs @@ -5,19 +5,31 @@ namespace Umbraco.Cms.Core.DynamicRoot.Origin; +/// +/// An origin finder that locates the nearest ancestor content item with an assigned domain (site root). +/// This finder handles the "Site" origin type and extends , +/// falling back to the content tree root if no domain is found. +/// public class SiteDynamicRootOriginFinder : RootDynamicRootOriginFinder { private readonly IEntityService _entityService; private readonly IDomainService _domainService; + /// + /// Initializes a new instance of the class. + /// + /// The entity service used to retrieve entities and traverse the content tree. + /// The domain service used to check for assigned domains on content items. public SiteDynamicRootOriginFinder(IEntityService entityService, IDomainService domainService) : base(entityService) { _entityService = entityService; _domainService = domainService; } + /// protected override string SupportedOriginType { get; set; } = "Site"; + /// public override Guid? FindOriginKey(DynamicRootNodeQuery query) { if (query.OriginAlias != SupportedOriginType) diff --git a/src/Umbraco.Core/DynamicRoot/QuerySteps/DynamicRootQueryStep.cs b/src/Umbraco.Core/DynamicRoot/QuerySteps/DynamicRootQueryStep.cs index be4d7ae030a0..6759b1d2151d 100644 --- a/src/Umbraco.Core/DynamicRoot/QuerySteps/DynamicRootQueryStep.cs +++ b/src/Umbraco.Core/DynamicRoot/QuerySteps/DynamicRootQueryStep.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.DynamicRoot.QuerySteps; +/// +/// Represents a query step configuration that defines how to traverse or filter the content tree during dynamic root resolution. +/// public class DynamicRootQueryStep { /// @@ -7,5 +10,8 @@ public class DynamicRootQueryStep /// public IEnumerable AnyOfDocTypeKeys { get; set; } = Array.Empty(); + /// + /// Gets or sets the alias identifying the type of query step to execute (e.g., "NearestAncestorOrSelf", "FurthestDescendantOrSelf"). + /// public string Alias { get; set; } = string.Empty; } diff --git a/src/Umbraco.Core/DynamicRoot/QuerySteps/DynamicRootQueryStepCollection.cs b/src/Umbraco.Core/DynamicRoot/QuerySteps/DynamicRootQueryStepCollection.cs index ba084025da70..f4adf818f4a4 100644 --- a/src/Umbraco.Core/DynamicRoot/QuerySteps/DynamicRootQueryStepCollection.cs +++ b/src/Umbraco.Core/DynamicRoot/QuerySteps/DynamicRootQueryStepCollection.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.DynamicRoot.QuerySteps; +/// +/// A collection of implementations used to filter or traverse the content tree during dynamic root resolution. +/// public class DynamicRootQueryStepCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection of query steps. public DynamicRootQueryStepCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/DynamicRoot/QuerySteps/DynamicRootQueryStepCollectionBuilder.cs b/src/Umbraco.Core/DynamicRoot/QuerySteps/DynamicRootQueryStepCollectionBuilder.cs index b10f4ea2e2ea..2efabf3dff49 100644 --- a/src/Umbraco.Core/DynamicRoot/QuerySteps/DynamicRootQueryStepCollectionBuilder.cs +++ b/src/Umbraco.Core/DynamicRoot/QuerySteps/DynamicRootQueryStepCollectionBuilder.cs @@ -2,7 +2,11 @@ namespace Umbraco.Cms.Core.DynamicRoot.QuerySteps; +/// +/// A collection builder for that allows ordered registration of implementations. +/// public class DynamicRootQueryStepCollectionBuilder : OrderedCollectionBuilderBase { + /// protected override DynamicRootQueryStepCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/DynamicRoot/QuerySteps/FurthestAncestorOrSelfDynamicRootQueryStep.cs b/src/Umbraco.Core/DynamicRoot/QuerySteps/FurthestAncestorOrSelfDynamicRootQueryStep.cs index 83b377493ac0..465530ce4fd7 100644 --- a/src/Umbraco.Core/DynamicRoot/QuerySteps/FurthestAncestorOrSelfDynamicRootQueryStep.cs +++ b/src/Umbraco.Core/DynamicRoot/QuerySteps/FurthestAncestorOrSelfDynamicRootQueryStep.cs @@ -2,19 +2,30 @@ namespace Umbraco.Cms.Core.DynamicRoot.QuerySteps; +/// +/// A query step that finds the furthest (topmost) ancestor or self matching the specified document type criteria. +/// This step traverses up the content tree from the origin and returns the matching node furthest from the origin. +/// public class FurthestAncestorOrSelfDynamicRootQueryStep : IDynamicRootQueryStep { private readonly ICoreScopeProvider _scopeProvider; private readonly IDynamicRootRepository _nodeFilterRepository; + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for database operations. + /// The repository used to query for ancestors matching the filter criteria. public FurthestAncestorOrSelfDynamicRootQueryStep(ICoreScopeProvider scopeProvider, IDynamicRootRepository nodeFilterRepository) { _scopeProvider = scopeProvider; _nodeFilterRepository = nodeFilterRepository; } + /// public virtual string SupportedDirectionAlias { get; set; } = "FurthestAncestorOrSelf"; + /// public async Task>> ExecuteAsync(ICollection origins, DynamicRootQueryStep filter) { if (filter.Alias != SupportedDirectionAlias) diff --git a/src/Umbraco.Core/DynamicRoot/QuerySteps/FurthestDescendantOrSelfDynamicRootQueryStep.cs b/src/Umbraco.Core/DynamicRoot/QuerySteps/FurthestDescendantOrSelfDynamicRootQueryStep.cs index 137ccfab88d4..da91dda7865d 100644 --- a/src/Umbraco.Core/DynamicRoot/QuerySteps/FurthestDescendantOrSelfDynamicRootQueryStep.cs +++ b/src/Umbraco.Core/DynamicRoot/QuerySteps/FurthestDescendantOrSelfDynamicRootQueryStep.cs @@ -2,19 +2,30 @@ namespace Umbraco.Cms.Core.DynamicRoot.QuerySteps; +/// +/// A query step that finds the furthest (deepest) descendants or self matching the specified document type criteria. +/// This step traverses down the content tree from the origin and returns all matching nodes at the greatest depth. +/// public class FurthestDescendantOrSelfDynamicRootQueryStep : IDynamicRootQueryStep { private readonly ICoreScopeProvider _scopeProvider; private readonly IDynamicRootRepository _nodeFilterRepository; + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for database operations. + /// The repository used to query for descendants matching the filter criteria. public FurthestDescendantOrSelfDynamicRootQueryStep(ICoreScopeProvider scopeProvider, IDynamicRootRepository nodeFilterRepository) { _scopeProvider = scopeProvider; _nodeFilterRepository = nodeFilterRepository; } + /// public virtual string SupportedDirectionAlias { get; set; } = "FurthestDescendantOrSelf"; + /// public async Task>> ExecuteAsync(ICollection origins, DynamicRootQueryStep filter) { if (filter.Alias != SupportedDirectionAlias) diff --git a/src/Umbraco.Core/DynamicRoot/QuerySteps/IDynamicRootQueryStep.cs b/src/Umbraco.Core/DynamicRoot/QuerySteps/IDynamicRootQueryStep.cs index 7468485ab436..5cc9c98a8593 100644 --- a/src/Umbraco.Core/DynamicRoot/QuerySteps/IDynamicRootQueryStep.cs +++ b/src/Umbraco.Core/DynamicRoot/QuerySteps/IDynamicRootQueryStep.cs @@ -2,8 +2,24 @@ namespace Umbraco.Cms.Core.DynamicRoot.QuerySteps; +/// +/// Defines a query step that can filter or traverse the content tree during dynamic root resolution. +/// public interface IDynamicRootQueryStep { + /// + /// Executes the query step on the specified origin content items. + /// + /// The collection of content keys to use as starting points for this query step. + /// The query step configuration containing the alias and document type filter criteria. + /// + /// A task representing the asynchronous operation, containing an with the filtered content keys. + /// Returns a failed attempt if this query step does not support the specified alias. + /// Task>> ExecuteAsync(ICollection origins, DynamicRootQueryStep filter); + + /// + /// Gets the direction alias that this query step supports (e.g., "NearestAncestorOrSelf", "FurthestDescendantOrSelf"). + /// string SupportedDirectionAlias { get; } } diff --git a/src/Umbraco.Core/DynamicRoot/QuerySteps/IDynamicRootRepository.cs b/src/Umbraco.Core/DynamicRoot/QuerySteps/IDynamicRootRepository.cs index fb385324eda9..844d59813161 100644 --- a/src/Umbraco.Core/DynamicRoot/QuerySteps/IDynamicRootRepository.cs +++ b/src/Umbraco.Core/DynamicRoot/QuerySteps/IDynamicRootRepository.cs @@ -1,12 +1,39 @@ namespace Umbraco.Cms.Core.DynamicRoot.QuerySteps; +/// +/// Provides data access operations for dynamic root query steps, supporting ancestor and descendant traversal with document type filtering. +/// public interface IDynamicRootRepository { + /// + /// Finds the nearest (closest to origin) ancestor or self that matches the query step criteria. + /// + /// The collection of content keys to start the search from. + /// The query step containing document type filter criteria. + /// A task representing the asynchronous operation, containing the key of the nearest matching ancestor or self, or null if none found. Task NearestAncestorOrSelfAsync(IEnumerable origins, DynamicRootQueryStep queryStep); + /// + /// Finds the furthest (topmost) ancestor or self that matches the query step criteria. + /// + /// The collection of content keys to start the search from. + /// The query step containing document type filter criteria. + /// A task representing the asynchronous operation, containing the key of the furthest matching ancestor or self, or null if none found. Task FurthestAncestorOrSelfAsync(IEnumerable origins, DynamicRootQueryStep queryStep); + /// + /// Finds the nearest (closest to origin) descendants or self that match the query step criteria. + /// + /// The collection of content keys to start the search from. + /// The query step containing document type filter criteria. + /// A task representing the asynchronous operation, containing a collection of keys for the nearest matching descendants or self. Task> NearestDescendantOrSelfAsync(ICollection origins, DynamicRootQueryStep queryStep); + /// + /// Finds the furthest (deepest) descendants or self that match the query step criteria. + /// + /// The collection of content keys to start the search from. + /// The query step containing document type filter criteria. + /// A task representing the asynchronous operation, containing a collection of keys for the furthest matching descendants or self. Task> FurthestDescendantOrSelfAsync(ICollection origins, DynamicRootQueryStep queryStep); } diff --git a/src/Umbraco.Core/DynamicRoot/QuerySteps/NearestAncestorOrSelfDynamicRootQueryStep.cs b/src/Umbraco.Core/DynamicRoot/QuerySteps/NearestAncestorOrSelfDynamicRootQueryStep.cs index 8fd80161609c..4d1fbfde146d 100644 --- a/src/Umbraco.Core/DynamicRoot/QuerySteps/NearestAncestorOrSelfDynamicRootQueryStep.cs +++ b/src/Umbraco.Core/DynamicRoot/QuerySteps/NearestAncestorOrSelfDynamicRootQueryStep.cs @@ -2,19 +2,30 @@ namespace Umbraco.Cms.Core.DynamicRoot.QuerySteps; +/// +/// A query step that finds the nearest (closest) ancestor or self matching the specified document type criteria. +/// This step traverses up the content tree from the origin and returns the first matching node. +/// public class NearestAncestorOrSelfDynamicRootQueryStep : IDynamicRootQueryStep { private readonly ICoreScopeProvider _scopeProvider; private readonly IDynamicRootRepository _nodeFilterRepository; + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for database operations. + /// The repository used to query for ancestors matching the filter criteria. public NearestAncestorOrSelfDynamicRootQueryStep(ICoreScopeProvider scopeProvider, IDynamicRootRepository nodeFilterRepository) { _scopeProvider = scopeProvider; _nodeFilterRepository = nodeFilterRepository; } + /// public virtual string SupportedDirectionAlias { get; set; } = "NearestAncestorOrSelf"; + /// public async Task>> ExecuteAsync(ICollection origins, DynamicRootQueryStep filter) { if (filter.Alias != SupportedDirectionAlias) diff --git a/src/Umbraco.Core/DynamicRoot/QuerySteps/NearestDescendantOrSelfDynamicRootQueryStep.cs b/src/Umbraco.Core/DynamicRoot/QuerySteps/NearestDescendantOrSelfDynamicRootQueryStep.cs index 3a2c6f412688..999521e46bb9 100644 --- a/src/Umbraco.Core/DynamicRoot/QuerySteps/NearestDescendantOrSelfDynamicRootQueryStep.cs +++ b/src/Umbraco.Core/DynamicRoot/QuerySteps/NearestDescendantOrSelfDynamicRootQueryStep.cs @@ -2,19 +2,30 @@ namespace Umbraco.Cms.Core.DynamicRoot.QuerySteps; +/// +/// A query step that finds the nearest (closest) descendants or self matching the specified document type criteria. +/// This step traverses down the content tree from the origin and returns all matching nodes at the shallowest depth. +/// public class NearestDescendantOrSelfDynamicRootQueryStep : IDynamicRootQueryStep { private readonly ICoreScopeProvider _scopeProvider; private readonly IDynamicRootRepository _nodeFilterRepository; + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for database operations. + /// The repository used to query for descendants matching the filter criteria. public NearestDescendantOrSelfDynamicRootQueryStep(ICoreScopeProvider scopeProvider, IDynamicRootRepository nodeFilterRepository) { _scopeProvider = scopeProvider; _nodeFilterRepository = nodeFilterRepository; } + /// public virtual string SupportedDirectionAlias { get; set; } = "NearestDescendantOrSelf"; + /// public async Task>> ExecuteAsync(ICollection origins, DynamicRootQueryStep filter) { if (filter.Alias != SupportedDirectionAlias) diff --git a/src/Umbraco.Core/Editors/BackOfficePreviewModel.cs b/src/Umbraco.Core/Editors/BackOfficePreviewModel.cs index 6ab0b76e3307..aca46f8f258a 100644 --- a/src/Umbraco.Core/Editors/BackOfficePreviewModel.cs +++ b/src/Umbraco.Core/Editors/BackOfficePreviewModel.cs @@ -3,19 +3,36 @@ namespace Umbraco.Cms.Core.Editors; +/// +/// Represents the model used for the backoffice content preview functionality. +/// public class BackOfficePreviewModel { private readonly UmbracoFeatures _features; + /// + /// Initializes a new instance of the class. + /// + /// The Umbraco features configuration. + /// The collection of available languages. public BackOfficePreviewModel(UmbracoFeatures features, IEnumerable languages) { _features = features; Languages = languages; } + /// + /// Gets the collection of available languages for preview. + /// public IEnumerable Languages { get; } + /// + /// Gets a value indicating whether device preview is disabled. + /// public bool DisableDevicePreview => _features.Disabled.DisableDevicePreview; + /// + /// Gets the path to an extended preview header view, if configured. + /// public string? PreviewExtendedHeaderView => _features.Enabled.PreviewExtendedView; } diff --git a/src/Umbraco.Core/Editors/EditorValidatorCollection.cs b/src/Umbraco.Core/Editors/EditorValidatorCollection.cs index a1c46cdb57e5..b2c06a0cd8d1 100644 --- a/src/Umbraco.Core/Editors/EditorValidatorCollection.cs +++ b/src/Umbraco.Core/Editors/EditorValidatorCollection.cs @@ -2,8 +2,18 @@ namespace Umbraco.Cms.Core.Editors; +/// +/// Represents a collection of instances. +/// +/// +/// This collection is used to validate editor models in the backoffice. +/// public class EditorValidatorCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection of editor validators. public EditorValidatorCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/Editors/EditorValidatorCollectionBuilder.cs b/src/Umbraco.Core/Editors/EditorValidatorCollectionBuilder.cs index b7b5269ee7d0..a94749ad35ec 100644 --- a/src/Umbraco.Core/Editors/EditorValidatorCollectionBuilder.cs +++ b/src/Umbraco.Core/Editors/EditorValidatorCollectionBuilder.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.Editors; +/// +/// Builds the using lazy initialization. +/// +/// +/// Use this builder during composition to register implementations. +/// public class EditorValidatorCollectionBuilder : LazyCollectionBuilderBase { + /// protected override EditorValidatorCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/Editors/EditorValidator{T}.cs b/src/Umbraco.Core/Editors/EditorValidator{T}.cs index 3e2b8995192b..fa756bcc0553 100644 --- a/src/Umbraco.Core/Editors/EditorValidator{T}.cs +++ b/src/Umbraco.Core/Editors/EditorValidator{T}.cs @@ -3,14 +3,21 @@ namespace Umbraco.Cms.Core.Editors; /// -/// Provides a base class for implementations. +/// Provides a base class for implementations. /// /// The validated object type. public abstract class EditorValidator : IEditorValidator { + /// public Type ModelType => typeof(T); + /// public IEnumerable Validate(object model) => Validate((T)model); + /// + /// Validates the specified model instance. + /// + /// The strongly-typed model to validate. + /// A collection of validation results indicating any validation failures. protected abstract IEnumerable Validate(T model); } diff --git a/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs b/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs index eb1e67da9d68..d8ede6224f1c 100644 --- a/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs +++ b/src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs @@ -1,6 +1,3 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Membership; @@ -10,6 +7,13 @@ namespace Umbraco.Cms.Core.Editors; +/// +/// Provides authorization helper methods for user editor operations in the backoffice. +/// +/// +/// This helper validates that the current user has the necessary permissions to modify +/// another user's settings, including start nodes, user groups, and section access. +/// public class UserEditorAuthorizationHelper { private readonly AppCaches _appCaches; @@ -17,6 +21,13 @@ public class UserEditorAuthorizationHelper private readonly IEntityService _entityService; private readonly IMediaService _mediaService; + /// + /// Initializes a new instance of the class. + /// + /// The content service. + /// The media service. + /// The entity service. + /// The application caches. public UserEditorAuthorizationHelper(IContentService contentService, IMediaService mediaService, IEntityService entityService, AppCaches appCaches) { _contentService = contentService; @@ -126,6 +137,15 @@ public UserEditorAuthorizationHelper(IContentService contentService, IMediaServi return Attempt.Succeed(); } + /// + /// Authorizes that the current user has access to the specified start content and media paths. + /// + /// The current user attempting the operation. + /// The content start node IDs to authorize. + /// The media start node IDs to authorize. + /// + /// A successful attempt if the user has access to all paths; otherwise, a failed attempt with an error message. + /// private Attempt AuthorizePath(IUser currentUser, IEnumerable? startContentIds, IEnumerable? startMediaIds) { if (startContentIds != null) diff --git a/src/Umbraco.Core/Enum.cs b/src/Umbraco.Core/Enum.cs index 63e4db17f963..d761d5c45aac 100644 --- a/src/Umbraco.Core/Enum.cs +++ b/src/Umbraco.Core/Enum.cs @@ -15,6 +15,9 @@ public static class Enum private static readonly Dictionary IntToValue; private static readonly Dictionary ValueToName; + /// + /// Static constructor that initializes the enum value dictionaries. + /// static Enum() { Values = Enum.GetValues(typeof(T)).Cast().ToList(); @@ -35,18 +38,53 @@ static Enum() } } + /// + /// Determines whether the specified value is defined in the enumeration. + /// + /// The enum value to check. + /// true if the value is defined; otherwise, false. public static bool IsDefined(T value) => ValueToName.ContainsKey(value); + /// + /// Determines whether the specified string is a defined name in the enumeration. + /// + /// The string value to check. + /// true if the name is defined; otherwise, false. public static bool IsDefined(string value) => SensitiveNameToValue.ContainsKey(value); + /// + /// Determines whether the specified integer is a defined value in the enumeration. + /// + /// The integer value to check. + /// true if the value is defined; otherwise, false. public static bool IsDefined(int value) => IntToValue.ContainsKey(value); + /// + /// Gets all values defined in the enumeration. + /// + /// An enumerable containing all enum values. public static IEnumerable GetValues() => Values; + /// + /// Gets all names defined in the enumeration. + /// + /// An array containing all enum names. public static string[] GetNames() => ValueToName.Values.ToArray(); + /// + /// Gets the name of the specified enum value. + /// + /// The enum value. + /// The name of the value, or null if not found. public static string? GetName(T value) => ValueToName.GetValueOrDefault(value); + /// + /// Parses the string representation of an enum value. + /// + /// The string to parse. + /// If true, case is ignored during parsing. + /// The parsed enum value. + /// The string is not a valid enum name. public static T Parse(string value, bool ignoreCase = false) { Dictionary names = ignoreCase ? InsensitiveNameToValue : SensitiveNameToValue; @@ -56,6 +94,13 @@ public static T Parse(string value, bool ignoreCase = false) T Throw() => throw new ArgumentException($"Value \"{value}\"is not a valid {typeof(T).Name} enumeration value.", nameof(value)); } + /// + /// Tries to parse the string representation of an enum value. + /// + /// The string to parse. + /// When this method returns, contains the parsed value if successful. + /// If true, case is ignored during parsing. + /// true if parsing succeeded; otherwise, false. public static bool TryParse(string value, out T returnValue, bool ignoreCase = false) { Dictionary names = ignoreCase ? InsensitiveNameToValue : SensitiveNameToValue; @@ -63,6 +108,11 @@ public static bool TryParse(string value, out T returnValue, bool ignoreCase = f return names.TryGetValue(value, out returnValue); } + /// + /// Parses the string representation of an enum value, returning null if parsing fails. + /// + /// The string to parse. + /// The parsed enum value, or null if parsing failed. public static T? ParseOrNull(string value) { if (string.IsNullOrWhiteSpace(value)) @@ -78,6 +128,11 @@ public static bool TryParse(string value, out T returnValue, bool ignoreCase = f return null; } + /// + /// Casts an integer to the enum type, returning null if the integer is not a valid value. + /// + /// The integer value to cast. + /// The enum value, or null if the integer is not valid. public static T? CastOrNull(int value) { if (IntToValue.TryGetValue(value, out T foundValue)) diff --git a/src/Umbraco.Core/Events/AddDomainWarningsWhenPublishingNotificationHandler.cs b/src/Umbraco.Core/Events/AddDomainWarningsWhenPublishingNotificationHandler.cs index ab9244bfc08e..8cdbe8ae5f1c 100644 --- a/src/Umbraco.Core/Events/AddDomainWarningsWhenPublishingNotificationHandler.cs +++ b/src/Umbraco.Core/Events/AddDomainWarningsWhenPublishingNotificationHandler.cs @@ -8,6 +8,9 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Handles the to add warnings when domains are not properly configured for multilingual sites. +/// public class AddDomainWarningsWhenPublishingNotificationHandler : INotificationHandler { private readonly IOptions _contentSettings; @@ -16,6 +19,14 @@ public class AddDomainWarningsWhenPublishingNotificationHandler : INotificationH private readonly IEventMessagesFactory _eventMessagesFactory; private readonly ILogger _logger; + /// + /// Initializes a new instance of the class. + /// + /// The content settings. + /// The content service. + /// The domain service. + /// The event messages factory. + /// The logger. public AddDomainWarningsWhenPublishingNotificationHandler( IOptions contentSettings, IContentService contentService, @@ -30,6 +41,7 @@ public AddDomainWarningsWhenPublishingNotificationHandler( _logger = logger; } + /// public void Handle(ContentPublishedNotification notification) { if (_contentSettings.Value.ShowDomainWarnings is false) @@ -95,6 +107,11 @@ public void Handle(ContentPublishedNotification notification) } } + /// + /// Gets all published cultures from the content and its ancestors. + /// + /// The content to check. + /// An enumerable of published culture codes. private IEnumerable GetPublishedCulturesFromAncestors(IContent? content) { if (content?.ParentId is not -1 && content?.HasIdentity is false) diff --git a/src/Umbraco.Core/Events/AddUnroutableContentWarningsWhenPublishingNotificationHandler.cs b/src/Umbraco.Core/Events/AddUnroutableContentWarningsWhenPublishingNotificationHandler.cs index 5e6fb71a0228..0b8433bc63c9 100644 --- a/src/Umbraco.Core/Events/AddUnroutableContentWarningsWhenPublishingNotificationHandler.cs +++ b/src/Umbraco.Core/Events/AddUnroutableContentWarningsWhenPublishingNotificationHandler.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; @@ -15,6 +15,9 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Handles the to add warnings when published content may not be routable. +/// public class AddUnroutableContentWarningsWhenPublishingNotificationHandler : INotificationAsyncHandler { private readonly IPublishedRouter _publishedRouter; @@ -31,6 +34,22 @@ public class AddUnroutableContentWarningsWhenPublishingNotificationHandler : INo private readonly IEventMessagesFactory _eventMessagesFactory; private readonly ContentSettings _contentSettings; + /// + /// Initializes a new instance of the class. + /// + /// The published router. + /// The Umbraco context accessor. + /// The language service. + /// The localized text service. + /// The content service. + /// The variation context accessor. + /// The logger factory. + /// The URI utility. + /// The published URL provider. + /// The navigation query service. + /// The published content status filtering service. + /// The event messages factory. + /// The content settings. public AddUnroutableContentWarningsWhenPublishingNotificationHandler( IPublishedRouter publishedRouter, IUmbracoContextAccessor umbracoContextAccessor, @@ -61,6 +80,7 @@ public AddUnroutableContentWarningsWhenPublishingNotificationHandler( _contentSettings = contentSettings.Value; } + /// public async Task HandleAsync(ContentPublishedNotification notification, CancellationToken cancellationToken) { if (_contentSettings.ShowUnroutableContentWarnings is false) diff --git a/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs b/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs index 22c7ef4c7e22..840dfdff7671 100644 --- a/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs +++ b/src/Umbraco.Core/Events/CancellableEnumerableObjectEventArgs.cs @@ -7,31 +7,59 @@ namespace Umbraco.Cms.Core.Events; public class CancellableEnumerableObjectEventArgs : CancellableObjectEventArgs>, IEquatable> { + /// + /// Initializes a new instance of the class. + /// + /// The collection of impacted objects. + /// A value indicating whether the event can be cancelled. + /// The event messages. + /// Additional data associated with the event. public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) : base(eventObject, canCancel, messages, additionalData) { } + /// + /// Initializes a new instance of the class. + /// + /// The collection of impacted objects. + /// A value indicating whether the event can be cancelled. + /// The event messages. public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, bool canCancel, EventMessages eventMessages) : base(eventObject, canCancel, eventMessages) { } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The collection of impacted objects. + /// The event messages. public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, EventMessages eventMessages) : base(eventObject, eventMessages) { } + /// + /// Initializes a new instance of the class. + /// + /// The collection of impacted objects. + /// A value indicating whether the event can be cancelled. public CancellableEnumerableObjectEventArgs(IEnumerable eventObject, bool canCancel) : base(eventObject, canCancel) { } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The collection of impacted objects. public CancellableEnumerableObjectEventArgs(IEnumerable eventObject) : base(eventObject) { } + /// public bool Equals(CancellableEnumerableObjectEventArgs? other) { if (other is null || other.EventObject is null) @@ -47,6 +75,7 @@ public bool Equals(CancellableEnumerableObjectEventArgs? other) return EventObject?.SequenceEqual(other.EventObject) ?? false; } + /// public override bool Equals(object? obj) { if (obj is null) @@ -67,6 +96,7 @@ public override bool Equals(object? obj) return Equals((CancellableEnumerableObjectEventArgs)obj); } + /// public override int GetHashCode() { if (EventObject is not null) diff --git a/src/Umbraco.Core/Events/CancellableEventArgs.cs b/src/Umbraco.Core/Events/CancellableEventArgs.cs index 7768da05f5cd..61a469f48fad 100644 --- a/src/Umbraco.Core/Events/CancellableEventArgs.cs +++ b/src/Umbraco.Core/Events/CancellableEventArgs.cs @@ -12,6 +12,12 @@ public class CancellableEventArgs : EventArgs, IEquatable private bool _cancel; private IDictionary? _eventState; + /// + /// Initializes a new instance of the class. + /// + /// A value indicating whether the event can be cancelled. + /// The event messages. + /// Additional data associated with the event. public CancellableEventArgs(bool canCancel, EventMessages messages, IDictionary additionalData) { CanCancel = canCancel; @@ -19,6 +25,11 @@ public CancellableEventArgs(bool canCancel, EventMessages messages, IDictionary< AdditionalData = new ReadOnlyDictionary(additionalData); } + /// + /// Initializes a new instance of the class. + /// + /// A value indicating whether the event can be cancelled. + /// The event messages. public CancellableEventArgs(bool canCancel, EventMessages eventMessages) { CanCancel = canCancel; @@ -26,6 +37,10 @@ public CancellableEventArgs(bool canCancel, EventMessages eventMessages) AdditionalData = EmptyAdditionalData; } + /// + /// Initializes a new instance of the class. + /// + /// A value indicating whether the event can be cancelled. public CancellableEventArgs(bool canCancel) { CanCancel = canCancel; @@ -35,11 +50,18 @@ public CancellableEventArgs(bool canCancel) AdditionalData = EmptyAdditionalData; } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The event messages. public CancellableEventArgs(EventMessages eventMessages) : this(true, eventMessages) { } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// public CancellableEventArgs() : this(true) { @@ -103,10 +125,23 @@ public IDictionary EventState set => _eventState = value; } + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(CancellableEventArgs? left, CancellableEventArgs? right) => Equals(left, right); + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(CancellableEventArgs left, CancellableEventArgs right) => Equals(left, right) == false; + /// public bool Equals(CancellableEventArgs? other) { if (ReferenceEquals(null, other)) @@ -133,6 +168,7 @@ public void CancelOperation(EventMessage cancelationMessage) Messages.Add(cancelationMessage); } + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -153,5 +189,6 @@ public override bool Equals(object? obj) return Equals((CancellableEventArgs)obj); } + /// public override int GetHashCode() => AdditionalData != null ? AdditionalData.GetHashCode() : 0; } diff --git a/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs b/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs index 26aa61b67a9e..19e5cfc31d12 100644 --- a/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs +++ b/src/Umbraco.Core/Events/CancellableObjectEventArgs.cs @@ -6,23 +6,50 @@ namespace Umbraco.Cms.Core.Events; /// public abstract class CancellableObjectEventArgs : CancellableEventArgs { + /// + /// Initializes a new instance of the class. + /// + /// The impacted object. + /// A value indicating whether the event can be cancelled. + /// The event messages. + /// Additional data associated with the event. protected CancellableObjectEventArgs(object? eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) : base(canCancel, messages, additionalData) => EventObject = eventObject; + /// + /// Initializes a new instance of the class. + /// + /// The impacted object. + /// A value indicating whether the event can be cancelled. + /// The event messages. protected CancellableObjectEventArgs(object? eventObject, bool canCancel, EventMessages eventMessages) : base(canCancel, eventMessages) => EventObject = eventObject; + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The impacted object. + /// The event messages. protected CancellableObjectEventArgs(object? eventObject, EventMessages eventMessages) : this(eventObject, true, eventMessages) { } + /// + /// Initializes a new instance of the class. + /// + /// The impacted object. + /// A value indicating whether the event can be cancelled. protected CancellableObjectEventArgs(object? eventObject, bool canCancel) : base(canCancel) => EventObject = eventObject; + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The impacted object. protected CancellableObjectEventArgs(object? eventObject) : this(eventObject, true) { diff --git a/src/Umbraco.Core/Events/CancellableObjectEventArgs{TEventObject}.cs b/src/Umbraco.Core/Events/CancellableObjectEventArgs{TEventObject}.cs index 5d9865c253ae..3694d2d35ce9 100644 --- a/src/Umbraco.Core/Events/CancellableObjectEventArgs{TEventObject}.cs +++ b/src/Umbraco.Core/Events/CancellableObjectEventArgs{TEventObject}.cs @@ -7,26 +7,53 @@ namespace Umbraco.Cms.Core.Events; public class CancellableObjectEventArgs : CancellableObjectEventArgs, IEquatable> { + /// + /// Initializes a new instance of the class. + /// + /// The impacted object. + /// A value indicating whether the event can be cancelled. + /// The event messages. + /// Additional data associated with the event. public CancellableObjectEventArgs(TEventObject? eventObject, bool canCancel, EventMessages messages, IDictionary additionalData) : base(eventObject, canCancel, messages, additionalData) { } + /// + /// Initializes a new instance of the class. + /// + /// The impacted object. + /// A value indicating whether the event can be cancelled. + /// The event messages. public CancellableObjectEventArgs(TEventObject? eventObject, bool canCancel, EventMessages eventMessages) : base(eventObject, canCancel, eventMessages) { } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The impacted object. + /// The event messages. public CancellableObjectEventArgs(TEventObject? eventObject, EventMessages eventMessages) : base(eventObject, eventMessages) { } + /// + /// Initializes a new instance of the class. + /// + /// The impacted object. + /// A value indicating whether the event can be cancelled. public CancellableObjectEventArgs(TEventObject? eventObject, bool canCancel) : base(eventObject, canCancel) { } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The impacted object. public CancellableObjectEventArgs(TEventObject? eventObject) : base(eventObject) { @@ -44,14 +71,27 @@ public CancellableObjectEventArgs(TEventObject? eventObject) set => base.EventObject = value; } + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==( CancellableObjectEventArgs left, CancellableObjectEventArgs right) => Equals(left, right); + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=( CancellableObjectEventArgs left, CancellableObjectEventArgs right) => !Equals(left, right); + /// public bool Equals(CancellableObjectEventArgs? other) { if (other is null) @@ -67,6 +107,7 @@ public bool Equals(CancellableObjectEventArgs? other) return base.Equals(other) && EqualityComparer.Default.Equals(EventObject, other.EventObject); } + /// public override bool Equals(object? obj) { if (obj is null) @@ -87,6 +128,7 @@ public override bool Equals(object? obj) return Equals((CancellableObjectEventArgs)obj); } + /// public override int GetHashCode() { unchecked diff --git a/src/Umbraco.Core/Events/ContentCacheEventArgs.cs b/src/Umbraco.Core/Events/ContentCacheEventArgs.cs index 732e6f2452b4..ef88df9499bd 100644 --- a/src/Umbraco.Core/Events/ContentCacheEventArgs.cs +++ b/src/Umbraco.Core/Events/ContentCacheEventArgs.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for content cache events. +/// public class ContentCacheEventArgs : CancelEventArgs { } diff --git a/src/Umbraco.Core/Events/CopyEventArgs.cs b/src/Umbraco.Core/Events/CopyEventArgs.cs index bead8213b618..ed3f0f636caf 100644 --- a/src/Umbraco.Core/Events/CopyEventArgs.cs +++ b/src/Umbraco.Core/Events/CopyEventArgs.cs @@ -1,7 +1,18 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for copy operations. +/// +/// The type of the entity being copied. public class CopyEventArgs : CancellableObjectEventArgs, IEquatable> { + /// + /// Initializes a new instance of the class. + /// + /// The original entity being copied. + /// The copied entity. + /// A value indicating whether the event can be cancelled. + /// The identifier of the new parent. public CopyEventArgs(TEntity original, TEntity copy, bool canCancel, int parentId) : base(original, canCancel) { @@ -9,6 +20,12 @@ public CopyEventArgs(TEntity original, TEntity copy, bool canCancel, int parentI ParentId = parentId; } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The original entity being copied. + /// The copied entity. + /// The identifier of the new parent. public CopyEventArgs(TEntity eventObject, TEntity copy, int parentId) : base(eventObject) { @@ -16,6 +33,14 @@ public CopyEventArgs(TEntity eventObject, TEntity copy, int parentId) ParentId = parentId; } + /// + /// Initializes a new instance of the class. + /// + /// The original entity being copied. + /// The copied entity. + /// A value indicating whether the event can be cancelled. + /// The identifier of the new parent. + /// A value indicating whether to create a relation to the original entity. public CopyEventArgs(TEntity eventObject, TEntity copy, bool canCancel, int parentId, bool relateToOriginal) : base(eventObject, canCancel) { @@ -39,10 +64,20 @@ public CopyEventArgs(TEntity eventObject, TEntity copy, bool canCancel, int pare /// public int ParentId { get; } + /// + /// Gets or sets a value indicating whether to create a relation to the original entity. + /// public bool RelateToOriginal { get; set; } + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(CopyEventArgs left, CopyEventArgs right) => Equals(left, right); + /// public bool Equals(CopyEventArgs? other) { if (ReferenceEquals(null, other)) @@ -59,6 +94,7 @@ public bool Equals(CopyEventArgs? other) ParentId == other.ParentId && RelateToOriginal == other.RelateToOriginal; } + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -79,6 +115,7 @@ public override bool Equals(object? obj) return Equals((CopyEventArgs)obj); } + /// public override int GetHashCode() { unchecked @@ -95,5 +132,11 @@ public override int GetHashCode() } } + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(CopyEventArgs left, CopyEventArgs right) => !Equals(left, right); } diff --git a/src/Umbraco.Core/Events/DeleteEventArgs.cs b/src/Umbraco.Core/Events/DeleteEventArgs.cs index 3ca366834f7e..b245f2f4ae26 100644 --- a/src/Umbraco.Core/Events/DeleteEventArgs.cs +++ b/src/Umbraco.Core/Events/DeleteEventArgs.cs @@ -1,5 +1,9 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for delete operations. +/// +/// The type of the entity being deleted. [SupersedeEvent(typeof(SaveEventArgs<>))] [SupersedeEvent(typeof(PublishEventArgs<>))] [SupersedeEvent(typeof(MoveEventArgs<>))] @@ -93,9 +97,16 @@ public IEnumerable DeletedEntities /// public List MediaFilesToDelete { get; } + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(DeleteEventArgs left, DeleteEventArgs right) => Equals(left, right); + /// public bool Equals(DeleteEventArgs? other) { if (ReferenceEquals(null, other)) @@ -111,6 +122,7 @@ public bool Equals(DeleteEventArgs? other) return base.Equals(other) && MediaFilesToDelete.SequenceEqual(other.MediaFilesToDelete); } + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -131,6 +143,7 @@ public override bool Equals(object? obj) return Equals((DeleteEventArgs)obj); } + /// public override int GetHashCode() { unchecked @@ -139,20 +152,44 @@ public override int GetHashCode() } } + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(DeleteEventArgs left, DeleteEventArgs right) => !Equals(left, right); } +/// +/// Represents event data for delete operations with an identifier. +/// public class DeleteEventArgs : CancellableEventArgs, IEquatable { + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the object being deleted. + /// A value indicating whether the event can be cancelled. + /// The event messages. public DeleteEventArgs(int id, bool canCancel, EventMessages eventMessages) : base(canCancel, eventMessages) => Id = id; + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the object being deleted. + /// A value indicating whether the event can be cancelled. public DeleteEventArgs(int id, bool canCancel) : base(canCancel) => Id = id; + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The identifier of the object being deleted. public DeleteEventArgs(int id) => Id = id; /// @@ -160,8 +197,15 @@ public DeleteEventArgs(int id, bool canCancel) /// public int Id { get; } + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(DeleteEventArgs left, DeleteEventArgs right) => Equals(left, right); + /// public bool Equals(DeleteEventArgs? other) { if (ReferenceEquals(null, other)) @@ -177,6 +221,7 @@ public bool Equals(DeleteEventArgs? other) return base.Equals(other) && Id == other.Id; } + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -197,6 +242,7 @@ public override bool Equals(object? obj) return Equals((DeleteEventArgs)obj); } + /// public override int GetHashCode() { unchecked @@ -205,5 +251,11 @@ public override int GetHashCode() } } + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(DeleteEventArgs left, DeleteEventArgs right) => !Equals(left, right); } diff --git a/src/Umbraco.Core/Events/EventAggregator.Notifications.cs b/src/Umbraco.Core/Events/EventAggregator.Notifications.cs index 2950301b4212..b8a6167c01a2 100644 --- a/src/Umbraco.Core/Events/EventAggregator.Notifications.cs +++ b/src/Umbraco.Core/Events/EventAggregator.Notifications.cs @@ -8,6 +8,9 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Default implementation of that channels events from multiple objects into a single object. +/// public partial class EventAggregator : IEventAggregator { private static readonly ConcurrentDictionary _notificationAsyncHandlers = new(); @@ -21,6 +24,12 @@ public partial class EventAggregator : IEventAggregator public EventAggregator(ServiceFactory serviceFactory) => _serviceFactory = serviceFactory; + /// + /// Publishes notifications synchronously to registered handlers. + /// + /// The type of notification being handled. + /// The type of the notification handler. + /// The notifications to publish. private void PublishNotifications(IEnumerable notifications) where TNotification : INotification where TNotificationHandler : INotificationHandler @@ -40,6 +49,14 @@ private void PublishNotifications(IEnumerab } } + /// + /// Publishes notifications asynchronously to registered handlers. + /// + /// The type of notification being handled. + /// The type of the notification handler. + /// The notifications to publish. + /// An optional cancellation token. + /// A task that represents the publish operation. private async Task PublishNotificationsAsync(IEnumerable notifications, CancellationToken cancellationToken = default) where TNotification : INotification where TNotificationHandler : INotificationHandler @@ -64,6 +81,12 @@ private async Task PublishNotificationsAsync + /// Invokes all synchronous handlers with the provided notifications. + /// + /// The type of notification being handled. + /// The handlers to invoke. + /// The notifications to handle. private static void PublishCore(IEnumerable>> allHandlers, IEnumerable notifications) { foreach (Action> handler in allHandlers) @@ -72,6 +95,14 @@ private static void PublishCore(IEnumerable + /// Invokes all asynchronous handlers with the provided notifications. + /// + /// The type of notification being handled. + /// The handlers to invoke. + /// The notifications to handle. + /// The cancellation token. + /// A task that represents the asynchronous operation. private static async Task PublishCoreAsync(IEnumerable, CancellationToken, Task>> allHandlers, IEnumerable notifications, CancellationToken cancellationToken) { foreach (Func, CancellationToken, Task> handler in allHandlers) @@ -85,6 +116,12 @@ private static async Task PublishCoreAsync(IEnumerable + /// Chunks a sequence of items into groups by their runtime type. + /// + /// The type of items in the sequence. + /// The source sequence to chunk. + /// An enumerable of groupings by type. private static IEnumerable> ChunkByType(IEnumerable source) where T : notnull { @@ -124,17 +161,40 @@ private static IEnumerable> ChunkByType(IEnumerable sou yield return grouping; } + /// + /// A helper class for grouping items by a key while implementing . + /// + /// The type of the grouping key. + /// The type of elements in the group. private sealed class ChunkGrouping : List, IGrouping { + /// + /// Gets the key of the grouping. + /// public TKey Key { get; } + /// + /// Initializes a new instance of the class. + /// + /// The key for this grouping. public ChunkGrouping(TKey key) => Key = key; } } +/// +/// Abstract wrapper for synchronous notification handlers. +/// internal abstract class NotificationHandlerWrapper { + /// + /// Handles the notifications by invoking the appropriate handlers. + /// + /// The type of notification being handled. + /// The type of the notification handler. + /// The notifications to handle. + /// The service factory for resolving handlers. + /// The publish action to invoke handlers. public abstract void Handle( IEnumerable notifications, ServiceFactory serviceFactory, @@ -143,8 +203,21 @@ public abstract void Handle( where TNotificationHandler : INotificationHandler; } +/// +/// Abstract wrapper for asynchronous notification handlers. +/// internal abstract class NotificationAsyncHandlerWrapper { + /// + /// Handles the notifications asynchronously by invoking the appropriate handlers. + /// + /// The type of notification being handled. + /// The type of the notification handler. + /// The notifications to handle. + /// The cancellation token. + /// The service factory for resolving handlers. + /// The publish function to invoke handlers. + /// A task that represents the asynchronous operation. public abstract Task HandleAsync( IEnumerable notifications, CancellationToken cancellationToken, @@ -154,6 +227,10 @@ public abstract Task HandleAsync( where TNotificationHandler : INotificationHandler; } +/// +/// Implementation of for a specific notification type. +/// +/// The type of notification being handled. internal sealed class NotificationAsyncHandlerWrapperImpl : NotificationAsyncHandlerWrapper where TNotificationType : INotification { @@ -222,6 +299,10 @@ public override async Task HandleAsync( } } +/// +/// Implementation of for a specific notification type. +/// +/// The type of notification being handled. internal sealed class NotificationHandlerWrapperImpl : NotificationHandlerWrapper where TNotificationType : INotification { diff --git a/src/Umbraco.Core/Events/EventDefinition.cs b/src/Umbraco.Core/Events/EventDefinition.cs index 3f7cd382ed1c..5ae28d2d7110 100644 --- a/src/Umbraco.Core/Events/EventDefinition.cs +++ b/src/Umbraco.Core/Events/EventDefinition.cs @@ -1,11 +1,21 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents an event definition that wraps a standard . +/// public class EventDefinition : EventDefinitionBase { private readonly EventArgs _args; private readonly object _sender; private readonly EventHandler _trackedEvent; + /// + /// Initializes a new instance of the class. + /// + /// The event handler to track. + /// The source of the event. + /// The event arguments. + /// The optional name of the event. public EventDefinition(EventHandler trackedEvent, object sender, EventArgs args, string? eventName = null) : base(sender, args, eventName) { @@ -14,18 +24,30 @@ public EventDefinition(EventHandler trackedEvent, object sender, EventArgs args, _args = args; } + /// public override void RaiseEvent() { _trackedEvent?.Invoke(_sender, _args); } } +/// +/// Represents an event definition that wraps a generic . +/// +/// The type of the event arguments. public class EventDefinition : EventDefinitionBase { private readonly TEventArgs _args; private readonly object _sender; private readonly EventHandler _trackedEvent; + /// + /// Initializes a new instance of the class. + /// + /// The event handler to track. + /// The source of the event. + /// The event arguments. + /// The optional name of the event. public EventDefinition(EventHandler trackedEvent, object sender, TEventArgs args, string? eventName = null) : base(sender, args, eventName) { @@ -34,18 +56,31 @@ public EventDefinition(EventHandler trackedEvent, object sender, TEv _args = args; } + /// public override void RaiseEvent() { _trackedEvent?.Invoke(_sender, _args); } } +/// +/// Represents an event definition that wraps a . +/// +/// The type of the event sender. +/// The type of the event arguments. public class EventDefinition : EventDefinitionBase { private readonly TEventArgs _args; private readonly TSender _sender; private readonly TypedEventHandler _trackedEvent; + /// + /// Initializes a new instance of the class. + /// + /// The event handler to track. + /// The source of the event. + /// The event arguments. + /// The optional name of the event. public EventDefinition(TypedEventHandler trackedEvent, TSender sender, TEventArgs args, string? eventName = null) : base(sender, args, eventName) { @@ -54,6 +89,7 @@ public EventDefinition(TypedEventHandler trackedEvent, TSen _args = args; } + /// public override void RaiseEvent() { _trackedEvent?.Invoke(_sender, _args); diff --git a/src/Umbraco.Core/Events/EventDefinitionBase.cs b/src/Umbraco.Core/Events/EventDefinitionBase.cs index 8ac84c470d1f..08901197eb60 100644 --- a/src/Umbraco.Core/Events/EventDefinitionBase.cs +++ b/src/Umbraco.Core/Events/EventDefinitionBase.cs @@ -3,8 +3,19 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Provides a base class for event definitions that can be tracked and raised by an event dispatcher. +/// public abstract class EventDefinitionBase : IEventDefinition, IEquatable { + /// + /// Initializes a new instance of the class. + /// + /// The source of the event. + /// The event arguments. + /// The optional name of the event. + /// Thrown when or is null. + /// Thrown when the event name cannot be automatically determined. protected EventDefinitionBase(object? sender, object? args, string? eventName = null) { Sender = sender ?? throw new ArgumentNullException(nameof(sender)); @@ -29,8 +40,10 @@ protected EventDefinitionBase(object? sender, object? args, string? eventName = } } + /// public object Sender { get; } + /// public bool Equals(EventDefinitionBase? other) { if (ReferenceEquals(null, other)) @@ -46,14 +59,24 @@ public bool Equals(EventDefinitionBase? other) return Args.Equals(other.Args) && string.Equals(EventName, other.EventName) && Sender.Equals(other.Sender); } + /// public object Args { get; } + /// public string? EventName { get; } + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(EventDefinitionBase left, EventDefinitionBase right) => Equals(left, right); + /// public abstract void RaiseEvent(); + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -74,6 +97,7 @@ public override bool Equals(object? obj) return Equals((EventDefinitionBase)obj); } + /// public override int GetHashCode() { unchecked @@ -89,5 +113,11 @@ public override int GetHashCode() } } + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(EventDefinitionBase left, EventDefinitionBase right) => Equals(left, right) == false; } diff --git a/src/Umbraco.Core/Events/EventMessage.cs b/src/Umbraco.Core/Events/EventMessage.cs index 8ba2c98bf804..2029870a06e7 100644 --- a/src/Umbraco.Core/Events/EventMessage.cs +++ b/src/Umbraco.Core/Events/EventMessage.cs @@ -15,10 +15,19 @@ public EventMessage(string category, string message, EventMessageType messageTyp MessageType = messageType; } + /// + /// Gets the category of the message. + /// public string Category { get; } + /// + /// Gets the message content. + /// public string Message { get; } + /// + /// Gets the type of the message. + /// public EventMessageType MessageType { get; } /// diff --git a/src/Umbraco.Core/Events/EventMessageType.cs b/src/Umbraco.Core/Events/EventMessageType.cs index a3c6ebf2f95b..e26a39fd922a 100644 --- a/src/Umbraco.Core/Events/EventMessageType.cs +++ b/src/Umbraco.Core/Events/EventMessageType.cs @@ -5,9 +5,28 @@ namespace Umbraco.Cms.Core.Events; /// public enum EventMessageType { + /// + /// The default message type. + /// Default = 0, + + /// + /// An informational message. + /// Info = 1, + + /// + /// An error message. + /// Error = 2, + + /// + /// A success message. + /// Success = 3, + + /// + /// A warning message. + /// Warning = 4, } diff --git a/src/Umbraco.Core/Events/EventMessages.cs b/src/Umbraco.Core/Events/EventMessages.cs index 68d19f27fd15..305fa2ea789b 100644 --- a/src/Umbraco.Core/Events/EventMessages.cs +++ b/src/Umbraco.Core/Events/EventMessages.cs @@ -7,11 +7,23 @@ public sealed class EventMessages : DisposableObjectSlim { private readonly List _msgs = new(); + /// + /// Gets the number of messages in the collection. + /// public int Count => _msgs.Count; + /// + /// Adds a message to the collection. + /// + /// The message to add. public void Add(EventMessage msg) => _msgs.Add(msg); + /// + /// Gets all messages in the collection. + /// + /// An enumerable of all event messages. public IEnumerable GetAll() => _msgs; + /// protected override void DisposeResources() => _msgs.Clear(); } diff --git a/src/Umbraco.Core/Events/EventNameExtractor.cs b/src/Umbraco.Core/Events/EventNameExtractor.cs index 67eb22123821..0e9b77169691 100644 --- a/src/Umbraco.Core/Events/EventNameExtractor.cs +++ b/src/Umbraco.Core/Events/EventNameExtractor.cs @@ -63,6 +63,13 @@ public class EventNameExtractor } } + /// + /// Finds all events on the sender type that match the args type. + /// + /// The type of the event sender. + /// The type of the event arguments. + /// A filter to exclude matched event names. Return true to exclude. + /// An array of matching event names. public static string[] FindEvents(Type senderType, Type argsType, Func exclude) { var found = MatchedEventNames.GetOrAdd(new Tuple(senderType, argsType), tuple => diff --git a/src/Umbraco.Core/Events/EventNameExtractorError.cs b/src/Umbraco.Core/Events/EventNameExtractorError.cs index a2fd01f1c1df..10e1d0ed3106 100644 --- a/src/Umbraco.Core/Events/EventNameExtractorError.cs +++ b/src/Umbraco.Core/Events/EventNameExtractorError.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents errors that can occur during event name extraction. +/// public enum EventNameExtractorError { + /// + /// No matching event was found. + /// NoneFound, + + /// + /// Multiple matching events were found, making the result ambiguous. + /// Ambiguous, } diff --git a/src/Umbraco.Core/Events/EventNameExtractorResult.cs b/src/Umbraco.Core/Events/EventNameExtractorResult.cs index fb847a02821a..2c0d39feb0b4 100644 --- a/src/Umbraco.Core/Events/EventNameExtractorResult.cs +++ b/src/Umbraco.Core/Events/EventNameExtractorResult.cs @@ -1,12 +1,29 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents the result of an event name extraction operation. +/// public class EventNameExtractorResult { + /// + /// Initializes a new instance of the class with a name. + /// + /// The extracted event name. public EventNameExtractorResult(string? name) => Name = name; + /// + /// Initializes a new instance of the class with an error. + /// + /// The error that occurred during extraction. public EventNameExtractorResult(EventNameExtractorError? error) => Error = error; + /// + /// Gets the error that occurred during extraction, if any. + /// public EventNameExtractorError? Error { get; } + /// + /// Gets the extracted event name, if successful. + /// public string? Name { get; } } diff --git a/src/Umbraco.Core/Events/ExportedMemberEventArgs.cs b/src/Umbraco.Core/Events/ExportedMemberEventArgs.cs index 06b7ff81f4bc..1be470b2a9eb 100644 --- a/src/Umbraco.Core/Events/ExportedMemberEventArgs.cs +++ b/src/Umbraco.Core/Events/ExportedMemberEventArgs.cs @@ -3,15 +3,29 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for member export operations. +/// public class ExportedMemberEventArgs : EventArgs { + /// + /// Initializes a new instance of the class. + /// + /// The member being exported. + /// The exported member data model. public ExportedMemberEventArgs(IMember member, MemberExportModel exported) { Member = member; Exported = exported; } + /// + /// Gets the member being exported. + /// public IMember Member { get; } + /// + /// Gets the exported member data model. + /// public MemberExportModel Exported { get; } } diff --git a/src/Umbraco.Core/Events/IDeletingMediaFilesEventArgs.cs b/src/Umbraco.Core/Events/IDeletingMediaFilesEventArgs.cs index 4aaeeac29de8..4b4b3aefaf42 100644 --- a/src/Umbraco.Core/Events/IDeletingMediaFilesEventArgs.cs +++ b/src/Umbraco.Core/Events/IDeletingMediaFilesEventArgs.cs @@ -1,6 +1,12 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event arguments that contain a list of media files to be deleted. +/// public interface IDeletingMediaFilesEventArgs { + /// + /// Gets the list of media file paths that should be deleted. + /// List MediaFilesToDelete { get; } } diff --git a/src/Umbraco.Core/Events/IEventDefinition.cs b/src/Umbraco.Core/Events/IEventDefinition.cs index d10b931548f6..7c62ce01fa25 100644 --- a/src/Umbraco.Core/Events/IEventDefinition.cs +++ b/src/Umbraco.Core/Events/IEventDefinition.cs @@ -1,12 +1,27 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents an event definition that can be tracked and raised by an event dispatcher. +/// public interface IEventDefinition { + /// + /// Gets the source of the event. + /// object Sender { get; } + /// + /// Gets the event arguments. + /// object Args { get; } + /// + /// Gets the name of the event. + /// string? EventName { get; } + /// + /// Raises the event by invoking the tracked event handler. + /// void RaiseEvent(); } diff --git a/src/Umbraco.Core/Events/IEventMessagesAccessor.cs b/src/Umbraco.Core/Events/IEventMessagesAccessor.cs index e88ba73deedf..57fd33851e4a 100644 --- a/src/Umbraco.Core/Events/IEventMessagesAccessor.cs +++ b/src/Umbraco.Core/Events/IEventMessagesAccessor.cs @@ -1,6 +1,12 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Provides access to the current instance. +/// public interface IEventMessagesAccessor { + /// + /// Gets or sets the current event messages instance. + /// EventMessages? EventMessages { get; set; } } diff --git a/src/Umbraco.Core/Events/IEventMessagesFactory.cs b/src/Umbraco.Core/Events/IEventMessagesFactory.cs index 9ade74d20a5b..6bf23685861f 100644 --- a/src/Umbraco.Core/Events/IEventMessagesFactory.cs +++ b/src/Umbraco.Core/Events/IEventMessagesFactory.cs @@ -5,7 +5,15 @@ namespace Umbraco.Cms.Core.Events; /// public interface IEventMessagesFactory { + /// + /// Gets the current instance, creating a new one if necessary. + /// + /// The current event messages instance. EventMessages Get(); + /// + /// Gets the current instance if one exists. + /// + /// The current event messages instance, or null if none exists. EventMessages? GetOrDefault(); } diff --git a/src/Umbraco.Core/Events/IScopedNotificationPublisher.cs b/src/Umbraco.Core/Events/IScopedNotificationPublisher.cs index 89962bbb9c9a..951569665510 100644 --- a/src/Umbraco.Core/Events/IScopedNotificationPublisher.cs +++ b/src/Umbraco.Core/Events/IScopedNotificationPublisher.cs @@ -5,6 +5,9 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Provides scoped notification publishing functionality within a transaction scope. +/// public interface IScopedNotificationPublisher { /// diff --git a/src/Umbraco.Core/Events/MoveEventArgs.cs b/src/Umbraco.Core/Events/MoveEventArgs.cs index 312f1b8146c6..4fe0ad94a72a 100644 --- a/src/Umbraco.Core/Events/MoveEventArgs.cs +++ b/src/Umbraco.Core/Events/MoveEventArgs.cs @@ -1,5 +1,9 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for move operations. +/// +/// The type of the entity being moved. public class MoveEventArgs : CancellableObjectEventArgs, IEquatable> { private IEnumerable>? _moveInfoCollection; @@ -109,8 +113,15 @@ public IEnumerable>? MoveInfoCollection } } + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(MoveEventArgs left, MoveEventArgs right) => Equals(left, right); + /// public bool Equals(MoveEventArgs? other) { if (other is null) @@ -126,6 +137,7 @@ public bool Equals(MoveEventArgs? other) return base.Equals(other) && (MoveInfoCollection?.Equals(other.MoveInfoCollection) ?? false); } + /// public override bool Equals(object? obj) { if (obj is null) @@ -146,6 +158,7 @@ public override bool Equals(object? obj) return Equals((MoveEventArgs)obj); } + /// public override int GetHashCode() { unchecked @@ -159,5 +172,11 @@ public override int GetHashCode() } } + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(MoveEventArgs left, MoveEventArgs right) => !Equals(left, right); } diff --git a/src/Umbraco.Core/Events/MoveEventInfo.cs b/src/Umbraco.Core/Events/MoveEventInfo.cs index 96f1e8ac7fe0..12d51a6abf84 100644 --- a/src/Umbraco.Core/Events/MoveEventInfo.cs +++ b/src/Umbraco.Core/Events/MoveEventInfo.cs @@ -1,7 +1,18 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents information about a single entity move operation. +/// +/// The type of the entity being moved. public class MoveEventInfo : MoveEventInfoBase { + /// + /// Initializes a new instance of the class. + /// + /// The entity being moved. + /// The original path of the entity. + /// The identifier of the new parent. + /// The unique identifier of the new parent. public MoveEventInfo(TEntity entity, string originalPath, int newParentId, Guid? newParentKey) : base(entity, originalPath) { @@ -9,21 +20,46 @@ public MoveEventInfo(TEntity entity, string originalPath, int newParentId, Guid? NewParentKey = newParentKey; } + /// + /// Initializes a new instance of the class. + /// + /// The entity being moved. + /// The original path of the entity. + /// The identifier of the new parent. public MoveEventInfo(TEntity entity, string originalPath, int newParentId) : this(entity, originalPath, newParentId, null) { } + /// + /// Gets or sets the identifier of the new parent. + /// [Obsolete("Please use NewParentKey instead, scheduled for removal in V15")] public int NewParentId { get; set; } + /// + /// Gets the unique identifier of the new parent. + /// public Guid? NewParentKey { get; } + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(MoveEventInfo left, MoveEventInfo right) => Equals(left, right); + /// public override bool Equals(object? obj) => Equals((MoveEventInfo?)obj); + /// + /// Determines whether this instance is equal to another instance. + /// + /// The other instance to compare. + /// true if the instances are equal; otherwise, false. public bool Equals(MoveEventInfo? other) => NewParentId == other?.NewParentId && NewParentKey == other.NewParentKey && base.Equals(other); + /// public override int GetHashCode() { unchecked @@ -37,5 +73,11 @@ public override int GetHashCode() } } + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(MoveEventInfo left, MoveEventInfo right) => !Equals(left, right); } diff --git a/src/Umbraco.Core/Events/MoveEventInfoBase.cs b/src/Umbraco.Core/Events/MoveEventInfoBase.cs index 4a20cfd39ba5..9e092ea99f12 100644 --- a/src/Umbraco.Core/Events/MoveEventInfoBase.cs +++ b/src/Umbraco.Core/Events/MoveEventInfoBase.cs @@ -1,17 +1,33 @@ -namespace Umbraco.Cms.Core.Events; +namespace Umbraco.Cms.Core.Events; +/// +/// Provides a base class for move event information. +/// +/// The type of the entity being moved. public abstract class MoveEventInfoBase : IEquatable> { + /// + /// Initializes a new instance of the class. + /// + /// The entity being moved. + /// The original path of the entity. public MoveEventInfoBase(TEntity entity, string originalPath) { Entity = entity; OriginalPath = originalPath; } + /// + /// Gets or sets the entity being moved. + /// public TEntity Entity { get; set; } + /// + /// Gets or sets the original path of the entity before the move. + /// public string OriginalPath { get; set; } + /// public bool Equals(MoveEventInfoBase? other) { if (ReferenceEquals(null, other)) @@ -32,7 +48,9 @@ public bool Equals(MoveEventInfoBase? other) return EqualityComparer.Default.Equals(Entity, other.Entity) && OriginalPath == other.OriginalPath; } + /// public override bool Equals(object? obj) => Equals((MoveEventInfoBase?) obj); + /// public override int GetHashCode() => HashCode.Combine(Entity, OriginalPath); } diff --git a/src/Umbraco.Core/Events/MoveToRecycleBinEventInfo.cs b/src/Umbraco.Core/Events/MoveToRecycleBinEventInfo.cs index 16af79098ada..ac7b9006c8ae 100644 --- a/src/Umbraco.Core/Events/MoveToRecycleBinEventInfo.cs +++ b/src/Umbraco.Core/Events/MoveToRecycleBinEventInfo.cs @@ -1,7 +1,16 @@ -namespace Umbraco.Cms.Core.Events; +namespace Umbraco.Cms.Core.Events; +/// +/// Represents information about a move to recycle bin operation. +/// +/// The type of the entity being moved to the recycle bin. public class MoveToRecycleBinEventInfo : MoveEventInfoBase { + /// + /// Initializes a new instance of the class. + /// + /// The entity being moved to the recycle bin. + /// The original path of the entity. public MoveToRecycleBinEventInfo(TEntity entity, string originalPath) : base(entity, originalPath) { } diff --git a/src/Umbraco.Core/Events/NewEventArgs.cs b/src/Umbraco.Core/Events/NewEventArgs.cs index 0db72488aa45..c9b35f890aa1 100644 --- a/src/Umbraco.Core/Events/NewEventArgs.cs +++ b/src/Umbraco.Core/Events/NewEventArgs.cs @@ -1,7 +1,19 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for new entity creation operations. +/// +/// The type of the entity being created. public class NewEventArgs : CancellableObjectEventArgs, IEquatable> { + /// + /// Initializes a new instance of the class. + /// + /// The entity being created. + /// A value indicating whether the event can be cancelled. + /// The alias of the entity. + /// The identifier of the parent entity. + /// The event messages. public NewEventArgs(TEntity eventObject, bool canCancel, string alias, int parentId, EventMessages eventMessages) : base(eventObject, canCancel, eventMessages) { @@ -9,6 +21,14 @@ public NewEventArgs(TEntity eventObject, bool canCancel, string alias, int paren ParentId = parentId; } + /// + /// Initializes a new instance of the class. + /// + /// The entity being created. + /// A value indicating whether the event can be cancelled. + /// The alias of the entity. + /// The parent entity. + /// The event messages. public NewEventArgs(TEntity eventObject, bool canCancel, string alias, TEntity? parent, EventMessages eventMessages) : base(eventObject, canCancel, eventMessages) { @@ -16,6 +36,13 @@ public NewEventArgs(TEntity eventObject, bool canCancel, string alias, TEntity? Parent = parent; } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The entity being created. + /// The alias of the entity. + /// The identifier of the parent entity. + /// The event messages. public NewEventArgs(TEntity eventObject, string alias, int parentId, EventMessages eventMessages) : base(eventObject, eventMessages) { @@ -23,6 +50,13 @@ public NewEventArgs(TEntity eventObject, string alias, int parentId, EventMessag ParentId = parentId; } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The entity being created. + /// The alias of the entity. + /// The parent entity. + /// The event messages. public NewEventArgs(TEntity eventObject, string alias, TEntity? parent, EventMessages eventMessages) : base(eventObject, eventMessages) { @@ -30,6 +64,13 @@ public NewEventArgs(TEntity eventObject, string alias, TEntity? parent, EventMes Parent = parent; } + /// + /// Initializes a new instance of the class. + /// + /// The entity being created. + /// A value indicating whether the event can be cancelled. + /// The alias of the entity. + /// The identifier of the parent entity. public NewEventArgs(TEntity eventObject, bool canCancel, string alias, int parentId) : base(eventObject, canCancel) { @@ -37,6 +78,13 @@ public NewEventArgs(TEntity eventObject, bool canCancel, string alias, int paren ParentId = parentId; } + /// + /// Initializes a new instance of the class. + /// + /// The entity being created. + /// A value indicating whether the event can be cancelled. + /// The alias of the entity. + /// The parent entity. public NewEventArgs(TEntity eventObject, bool canCancel, string alias, TEntity? parent) : base(eventObject, canCancel) { @@ -44,6 +92,12 @@ public NewEventArgs(TEntity eventObject, bool canCancel, string alias, TEntity? Parent = parent; } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The entity being created. + /// The alias of the entity. + /// The identifier of the parent entity. public NewEventArgs(TEntity eventObject, string alias, int parentId) : base(eventObject) { @@ -51,6 +105,12 @@ public NewEventArgs(TEntity eventObject, string alias, int parentId) ParentId = parentId; } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The entity being created. + /// The alias of the entity. + /// The parent entity. public NewEventArgs(TEntity eventObject, string alias, TEntity? parent) : base(eventObject) { @@ -78,8 +138,15 @@ public NewEventArgs(TEntity eventObject, string alias, TEntity? parent) /// public TEntity? Parent { get; } + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(NewEventArgs left, NewEventArgs right) => Equals(left, right); + /// public bool Equals(NewEventArgs? other) { if (ReferenceEquals(null, other)) @@ -96,6 +163,7 @@ public bool Equals(NewEventArgs? other) EqualityComparer.Default.Equals(Parent, other.Parent) && ParentId == other.ParentId; } + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -116,6 +184,7 @@ public override bool Equals(object? obj) return Equals((NewEventArgs?)obj); } + /// public override int GetHashCode() { unchecked @@ -132,5 +201,11 @@ public override int GetHashCode() } } + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(NewEventArgs left, NewEventArgs right) => !Equals(left, right); } diff --git a/src/Umbraco.Core/Events/PassThroughEventDispatcher.cs b/src/Umbraco.Core/Events/PassThroughEventDispatcher.cs index a3b8dc02b5d7..71cce3072b9e 100644 --- a/src/Umbraco.Core/Events/PassThroughEventDispatcher.cs +++ b/src/Umbraco.Core/Events/PassThroughEventDispatcher.cs @@ -9,6 +9,7 @@ namespace Umbraco.Cms.Core.Events; /// internal sealed class PassThroughEventDispatcher : IEventDispatcher { + /// public bool DispatchCancelable(EventHandler? eventHandler, object sender, CancellableEventArgs args, string? eventName = null) { if (eventHandler == null) @@ -20,6 +21,7 @@ public bool DispatchCancelable(EventHandler? eventHandler, object sender, Cancel return args.Cancel; } + /// public bool DispatchCancelable(EventHandler? eventHandler, object sender, TArgs args, string? eventName = null) where TArgs : CancellableEventArgs { @@ -32,6 +34,7 @@ public bool DispatchCancelable(EventHandler? eventHandler, object return args.Cancel; } + /// public bool DispatchCancelable(TypedEventHandler? eventHandler, TSender sender, TArgs args, string? eventName = null) where TArgs : CancellableEventArgs { @@ -44,16 +47,21 @@ public bool DispatchCancelable(TypedEventHandler return args.Cancel; } + /// public void Dispatch(EventHandler? eventHandler, object sender, EventArgs args, string? eventName = null) => eventHandler?.Invoke(sender, args); + /// public void Dispatch(EventHandler? eventHandler, object sender, TArgs args, string? eventName = null) => eventHandler?.Invoke(sender, args); + /// public void Dispatch(TypedEventHandler? eventHandler, TSender sender, TArgs args, string? eventName = null) => eventHandler?.Invoke(sender, args); + /// public IEnumerable GetEvents(EventDefinitionFilter filter) => Enumerable.Empty(); + /// public void ScopeExit(bool completed) { } diff --git a/src/Umbraco.Core/Events/PublishEventArgs.cs b/src/Umbraco.Core/Events/PublishEventArgs.cs index 8a48a0cfa90b..5bdc174f9b32 100644 --- a/src/Umbraco.Core/Events/PublishEventArgs.cs +++ b/src/Umbraco.Core/Events/PublishEventArgs.cs @@ -1,5 +1,9 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for publish operations. +/// +/// The type of the entity being published. public class PublishEventArgs : CancellableEnumerableObjectEventArgs, IEquatable> { @@ -90,9 +94,16 @@ public PublishEventArgs(TEntity eventObject, bool canCancel, bool isAllPublished /// public IEnumerable? PublishedEntities => EventObject; + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(PublishEventArgs left, PublishEventArgs right) => Equals(left, right); + /// public bool Equals(PublishEventArgs? other) { if (ReferenceEquals(null, other)) @@ -108,6 +119,7 @@ public bool Equals(PublishEventArgs? other) return base.Equals(other); } + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -128,6 +140,7 @@ public override bool Equals(object? obj) return Equals((PublishEventArgs)obj); } + /// public override int GetHashCode() { unchecked @@ -136,6 +149,12 @@ public override int GetHashCode() } } + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(PublishEventArgs left, PublishEventArgs right) => !Equals(left, right); } diff --git a/src/Umbraco.Core/Events/QueuingEventDispatcher.cs b/src/Umbraco.Core/Events/QueuingEventDispatcher.cs index bc8eac29a15e..3ef8e47858df 100644 --- a/src/Umbraco.Core/Events/QueuingEventDispatcher.cs +++ b/src/Umbraco.Core/Events/QueuingEventDispatcher.cs @@ -13,10 +13,15 @@ public class QueuingEventDispatcher : QueuingEventDispatcherBase { private readonly MediaFileManager _mediaFileManager; + /// + /// Initializes a new instance of the class. + /// + /// The media file manager. public QueuingEventDispatcher(MediaFileManager mediaFileManager) : base(true) => _mediaFileManager = mediaFileManager; + /// protected override void ScopeExitCompleted() { // processing only the last instance of each event... diff --git a/src/Umbraco.Core/Events/QueuingEventDispatcherBase.cs b/src/Umbraco.Core/Events/QueuingEventDispatcherBase.cs index d319a1cd7104..e094800d54c1 100644 --- a/src/Umbraco.Core/Events/QueuingEventDispatcherBase.cs +++ b/src/Umbraco.Core/Events/QueuingEventDispatcherBase.cs @@ -24,10 +24,18 @@ public abstract class QueuingEventDispatcherBase : IEventDispatcher // events will be enlisted in the order they are raised private List? _events; + /// + /// Initializes a new instance of the class. + /// + /// A value indicating whether cancelable events should be raised immediately. protected QueuingEventDispatcherBase(bool raiseCancelable) => _raiseCancelable = raiseCancelable; + /// + /// Gets the list of queued events. + /// private List Events => _events ??= new List(); + /// public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string? eventName = null) { if (eventHandler == null) @@ -44,6 +52,7 @@ public bool DispatchCancelable(EventHandler eventHandler, object sender, Cancell return args.Cancel; } + /// public bool DispatchCancelable(EventHandler eventHandler, object sender, TArgs args, string? eventName = null) where TArgs : CancellableEventArgs { @@ -61,6 +70,7 @@ public bool DispatchCancelable(EventHandler eventHandler, object s return args.Cancel; } + /// public bool DispatchCancelable(TypedEventHandler eventHandler, TSender sender, TArgs args, string? eventName = null) where TArgs : CancellableEventArgs { @@ -78,6 +88,7 @@ public bool DispatchCancelable(TypedEventHandler return args.Cancel; } + /// public void Dispatch(EventHandler eventHandler, object sender, EventArgs args, string? eventName = null) { if (eventHandler == null) @@ -88,6 +99,7 @@ public void Dispatch(EventHandler eventHandler, object sender, EventArgs args, s Events.Add(new EventDefinition(eventHandler, sender, args, eventName)); } + /// public void Dispatch(EventHandler eventHandler, object sender, TArgs args, string? eventName = null) { if (eventHandler == null) @@ -98,6 +110,7 @@ public void Dispatch(EventHandler eventHandler, object sender, TAr Events.Add(new EventDefinition(eventHandler, sender, args, eventName)); } + /// public void Dispatch(TypedEventHandler eventHandler, TSender sender, TArgs args, string? eventName = null) { if (eventHandler == null) @@ -108,6 +121,7 @@ public void Dispatch(TypedEventHandler eventHand Events.Add(new EventDefinition(eventHandler, sender, args, eventName)); } + /// public IEnumerable GetEvents(EventDefinitionFilter filter) { if (_events == null) @@ -146,6 +160,7 @@ public IEnumerable GetEvents(EventDefinitionFilter filter) return FilterSupersededAndUpdateToLatestEntity(events); } + /// public void ScopeExit(bool completed) { if (_events == null) @@ -175,9 +190,16 @@ public void ScopeExit(bool completed) // due to scopes, they should not expected eg a saved entity to still be around - however, now, // going to write a ugly condition to deal with U4-10764 - // iterates over the events (latest first) and filter out any events or entities in event args that are included - // in more recent events that Supersede previous ones. For example, If an Entity has been Saved and then Deleted, we don't want - // to raise the Saved event (well actually we just don't want to include it in the args for that saved event) + /// + /// Iterates over the events (latest first) and filters out any events or entities in event args that are included + /// in more recent events that supersede previous ones. + /// + /// The list of event definitions to filter. + /// The filtered event definitions with superseded events removed and entities updated to latest versions. + /// + /// For example, if an Entity has been Saved and then Deleted, we don't want + /// to raise the Saved event (we just don't want to include it in the args for that saved event). + /// internal static IEnumerable FilterSupersededAndUpdateToLatestEntity( IReadOnlyList events) { @@ -304,9 +326,16 @@ internal static IEnumerable FilterSupersededAndUpdateToLatestE return result; } + /// + /// Called when the scope exits and has been completed. Implementations should raise the queued events. + /// protected abstract void ScopeExitCompleted(); - // edits event args to use the latest instance of each entity + /// + /// Edits event args to use the latest instance of each entity. + /// + /// The collection of entities and their event info. + /// The event args to update. private static void UpdateToLatestEntities( IEnumerable> entities, IEnumerable args) @@ -414,10 +443,19 @@ private static bool IsSuperceeded(IEntity entity, EventDefinitionInfos infos, Li } } + /// + /// Contains information about an event definition and its supersede types. + /// private sealed class EventDefinitionInfos { + /// + /// Gets or sets the event definition. + /// public IEventDefinition? EventDefinition { get; set; } + /// + /// Gets or sets the types of event arguments that this event supersedes. + /// public Type[]? SupersedeTypes { get; set; } } } diff --git a/src/Umbraco.Core/Events/RecycleBinEventArgs.cs b/src/Umbraco.Core/Events/RecycleBinEventArgs.cs index 44fb13016b55..b31d46fb8786 100644 --- a/src/Umbraco.Core/Events/RecycleBinEventArgs.cs +++ b/src/Umbraco.Core/Events/RecycleBinEventArgs.cs @@ -1,11 +1,23 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for recycle bin operations. +/// public class RecycleBinEventArgs : CancellableEventArgs, IEquatable { + /// + /// Initializes a new instance of the class. + /// + /// The object type identifier of the items in the recycle bin. + /// The event messages. public RecycleBinEventArgs(Guid nodeObjectType, EventMessages eventMessages) : base(true, eventMessages) => NodeObjectType = nodeObjectType; + /// + /// Initializes a new instance of the class. + /// + /// The object type identifier of the items in the recycle bin. public RecycleBinEventArgs(Guid nodeObjectType) : base(true) => NodeObjectType = nodeObjectType; @@ -31,8 +43,15 @@ public RecycleBinEventArgs(Guid nodeObjectType) /// public bool IsMediaRecycleBin => NodeObjectType == Constants.ObjectTypes.Media; + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(RecycleBinEventArgs left, RecycleBinEventArgs right) => Equals(left, right); + /// public bool Equals(RecycleBinEventArgs? other) { if (ReferenceEquals(null, other)) @@ -49,6 +68,7 @@ public bool Equals(RecycleBinEventArgs? other) RecycleBinEmptiedSuccessfully == other.RecycleBinEmptiedSuccessfully; } + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -69,6 +89,7 @@ public override bool Equals(object? obj) return Equals((RecycleBinEventArgs)obj); } + /// public override int GetHashCode() { unchecked @@ -80,5 +101,11 @@ public override int GetHashCode() } } + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(RecycleBinEventArgs left, RecycleBinEventArgs right) => !Equals(left, right); } diff --git a/src/Umbraco.Core/Events/RelateOnCopyNotificationHandler.cs b/src/Umbraco.Core/Events/RelateOnCopyNotificationHandler.cs index ad0cdaac8c31..ad3e23a683c6 100644 --- a/src/Umbraco.Core/Events/RelateOnCopyNotificationHandler.cs +++ b/src/Umbraco.Core/Events/RelateOnCopyNotificationHandler.cs @@ -9,6 +9,9 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Handles the to create a relation between the original and copied content. +/// public class RelateOnCopyNotificationHandler : INotificationHandler, INotificationAsyncHandler @@ -17,6 +20,12 @@ public class RelateOnCopyNotificationHandler : private readonly IUserIdKeyResolver _userIdKeyResolver; private readonly IRelationService _relationService; + /// + /// Initializes a new instance of the class. + /// + /// The relation service. + /// The audit service. + /// The user ID key resolver. public RelateOnCopyNotificationHandler( IRelationService relationService, IAuditService auditService, @@ -27,6 +36,11 @@ public RelateOnCopyNotificationHandler( _userIdKeyResolver = userIdKeyResolver; } + /// + /// Initializes a new instance of the class. + /// + /// The relation service. + /// The audit service. [Obsolete("Use the non-obsolete constructor instead. Scheduled for removal in V19.")] public RelateOnCopyNotificationHandler( IRelationService relationService, @@ -74,6 +88,7 @@ await _auditService.AddAsync( $"Copied content with Id: '{notification.Copy.Id}' related to original content with Id: '{notification.Original.Id}'"); } + /// [Obsolete("Use the INotificationAsyncHandler.HandleAsync implementation instead. Scheduled for removal in V19.")] public void Handle(ContentCopiedNotification notification) => HandleAsync(notification, CancellationToken.None).GetAwaiter().GetResult(); diff --git a/src/Umbraco.Core/Events/RolesEventArgs.cs b/src/Umbraco.Core/Events/RolesEventArgs.cs index a96de0671397..93ff7d5b1744 100644 --- a/src/Umbraco.Core/Events/RolesEventArgs.cs +++ b/src/Umbraco.Core/Events/RolesEventArgs.cs @@ -1,14 +1,28 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for role assignment operations. +/// public class RolesEventArgs : EventArgs { + /// + /// Initializes a new instance of the class. + /// + /// The identifiers of the members being assigned roles. + /// The names of the roles being assigned. public RolesEventArgs(int[] memberIds, string[] roles) { MemberIds = memberIds; Roles = roles; } + /// + /// Gets or sets the identifiers of the members being assigned roles. + /// public int[] MemberIds { get; set; } + /// + /// Gets or sets the names of the roles being assigned. + /// public string[] Roles { get; set; } } diff --git a/src/Umbraco.Core/Events/RollbackEventArgs.cs b/src/Umbraco.Core/Events/RollbackEventArgs.cs index d23ac75f9aca..901a1cd78f1c 100644 --- a/src/Umbraco.Core/Events/RollbackEventArgs.cs +++ b/src/Umbraco.Core/Events/RollbackEventArgs.cs @@ -1,12 +1,25 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for rollback operations. +/// +/// The type of the entity being rolled back. public class RollbackEventArgs : CancellableObjectEventArgs { + /// + /// Initializes a new instance of the class. + /// + /// The entity being rolled back. + /// A value indicating whether the event can be cancelled. public RollbackEventArgs(TEntity eventObject, bool canCancel) : base(eventObject, canCancel) { } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The entity being rolled back. public RollbackEventArgs(TEntity eventObject) : base(eventObject) { diff --git a/src/Umbraco.Core/Events/SaveEventArgs.cs b/src/Umbraco.Core/Events/SaveEventArgs.cs index 319a0726f299..b6feb3c97d30 100644 --- a/src/Umbraco.Core/Events/SaveEventArgs.cs +++ b/src/Umbraco.Core/Events/SaveEventArgs.cs @@ -1,5 +1,9 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for save operations. +/// +/// The type of the entity being saved. public class SaveEventArgs : CancellableEnumerableObjectEventArgs { /// diff --git a/src/Umbraco.Core/Events/ScopedNotificationPublisher.cs b/src/Umbraco.Core/Events/ScopedNotificationPublisher.cs index 0dc8b9605489..e2d926c0ef34 100644 --- a/src/Umbraco.Core/Events/ScopedNotificationPublisher.cs +++ b/src/Umbraco.Core/Events/ScopedNotificationPublisher.cs @@ -5,13 +5,24 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Default implementation of that publishes notifications within a scope. +/// public class ScopedNotificationPublisher : ScopedNotificationPublisher { + /// + /// Initializes a new instance of the class. + /// + /// The event aggregator. public ScopedNotificationPublisher(IEventAggregator eventAggregator) : base(eventAggregator) { } } +/// +/// Implementation of that publishes notifications within a scope for a specific handler type. +/// +/// The type of notification handler. public class ScopedNotificationPublisher : IScopedNotificationPublisher where TNotificationHandler : INotificationHandler { @@ -21,12 +32,18 @@ public class ScopedNotificationPublisher : IScopedNotifica private readonly Lock _locker = new(); private bool _isSuppressed; + /// + /// Initializes a new instance of the class. + /// + /// The event aggregator. + /// A value indicating whether cancelable notifications should be published on scope exit. public ScopedNotificationPublisher(IEventAggregator eventAggregator, bool publishCancelableNotificationOnScopeExit = false) { _eventAggregator = eventAggregator; _publishCancelableNotificationOnScopeExit |= publishCancelableNotificationOnScopeExit; } + /// public bool PublishCancelable(ICancelableNotification notification) { ArgumentNullException.ThrowIfNull(notification); @@ -48,6 +65,7 @@ public bool PublishCancelable(ICancelableNotification notification) return notification.Cancel; } + /// public async Task PublishCancelableAsync(ICancelableNotification notification) { ArgumentNullException.ThrowIfNull(notification); @@ -73,6 +91,7 @@ public async Task PublishCancelableAsync(ICancelableNotification notificat return notification.Cancel; } + /// public void Publish(INotification notification) { ArgumentNullException.ThrowIfNull(notification); @@ -85,6 +104,7 @@ public void Publish(INotification notification) _notificationOnScopeCompleted.Add(notification); } + /// public void ScopeExit(bool completed) { try @@ -100,6 +120,7 @@ public void ScopeExit(bool completed) } } + /// public IDisposable Suppress() { lock (_locker) @@ -113,22 +134,38 @@ public IDisposable Suppress() } } + /// + /// Publishes all pending scoped notifications. + /// + /// The notifications to publish. protected virtual void PublishScopedNotifications(IList notifications) => _eventAggregator.Publish(notifications); + /// + /// A disposable class that suppresses notifications until disposed. + /// private sealed class Suppressor : IDisposable { private readonly ScopedNotificationPublisher _scopedNotificationPublisher; private bool _disposedValue; + /// + /// Initializes a new instance of the class. + /// + /// The scoped notification publisher to suppress. public Suppressor(ScopedNotificationPublisher scopedNotificationPublisher) { _scopedNotificationPublisher = scopedNotificationPublisher; _scopedNotificationPublisher._isSuppressed = true; } + /// public void Dispose() => Dispose(true); + /// + /// Releases unmanaged and optionally managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. private void Dispose(bool disposing) { if (!_disposedValue) diff --git a/src/Umbraco.Core/Events/SendEmailEventArgs.cs b/src/Umbraco.Core/Events/SendEmailEventArgs.cs index 2e75d1b58391..af9ef87515e3 100644 --- a/src/Umbraco.Core/Events/SendEmailEventArgs.cs +++ b/src/Umbraco.Core/Events/SendEmailEventArgs.cs @@ -2,9 +2,19 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for send email operations. +/// public class SendEmailEventArgs : EventArgs { + /// + /// Initializes a new instance of the class. + /// + /// The email message being sent. public SendEmailEventArgs(EmailMessage message) => Message = message; + /// + /// Gets the email message being sent. + /// public EmailMessage Message { get; } } diff --git a/src/Umbraco.Core/Events/SendToPublishEventArgs.cs b/src/Umbraco.Core/Events/SendToPublishEventArgs.cs index a72cd8201293..7927595c7416 100644 --- a/src/Umbraco.Core/Events/SendToPublishEventArgs.cs +++ b/src/Umbraco.Core/Events/SendToPublishEventArgs.cs @@ -1,12 +1,25 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents event data for send to publish operations. +/// +/// The type of the entity being sent to publish. public class SendToPublishEventArgs : CancellableObjectEventArgs { + /// + /// Initializes a new instance of the class. + /// + /// The entity being sent to publish. + /// A value indicating whether the event can be cancelled. public SendToPublishEventArgs(TEntity eventObject, bool canCancel) : base(eventObject, canCancel) { } + /// + /// Initializes a new instance of the class with cancellation enabled. + /// + /// The entity being sent to publish. public SendToPublishEventArgs(TEntity eventObject) : base(eventObject) { diff --git a/src/Umbraco.Core/Events/SupersedeEventAttribute.cs b/src/Umbraco.Core/Events/SupersedeEventAttribute.cs index 21137968f0fb..0b754bc6c887 100644 --- a/src/Umbraco.Core/Events/SupersedeEventAttribute.cs +++ b/src/Umbraco.Core/Events/SupersedeEventAttribute.cs @@ -9,7 +9,14 @@ namespace Umbraco.Cms.Core.Events; [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class SupersedeEventAttribute : Attribute { + /// + /// Initializes a new instance of the class. + /// + /// The type of event arguments that this event supersedes. public SupersedeEventAttribute(Type supersededEventArgsType) => SupersededEventArgsType = supersededEventArgsType; + /// + /// Gets the type of event arguments that this event supersedes. + /// public Type SupersededEventArgsType { get; } } diff --git a/src/Umbraco.Core/Events/TransientEventMessagesFactory.cs b/src/Umbraco.Core/Events/TransientEventMessagesFactory.cs index 8495da25b001..02fa49816596 100644 --- a/src/Umbraco.Core/Events/TransientEventMessagesFactory.cs +++ b/src/Umbraco.Core/Events/TransientEventMessagesFactory.cs @@ -5,7 +5,9 @@ namespace Umbraco.Cms.Core.Events; /// public class TransientEventMessagesFactory : IEventMessagesFactory { + /// public EventMessages Get() => new EventMessages(); + /// public EventMessages? GetOrDefault() => null; } diff --git a/src/Umbraco.Core/Events/TypedEventHandler.cs b/src/Umbraco.Core/Events/TypedEventHandler.cs index e359bd47f9e1..c7d7b8595249 100644 --- a/src/Umbraco.Core/Events/TypedEventHandler.cs +++ b/src/Umbraco.Core/Events/TypedEventHandler.cs @@ -1,4 +1,11 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents a typed event handler delegate with a specific sender and event arguments type. +/// +/// The type of the event sender. +/// The type of the event arguments. +/// The source of the event. +/// The event arguments. [Serializable] public delegate void TypedEventHandler(TSender sender, TEventArgs e); diff --git a/src/Umbraco.Core/Events/UserGroupWithUsers.cs b/src/Umbraco.Core/Events/UserGroupWithUsers.cs index f3a77e22e6db..b6c24fe8ed3e 100644 --- a/src/Umbraco.Core/Events/UserGroupWithUsers.cs +++ b/src/Umbraco.Core/Events/UserGroupWithUsers.cs @@ -2,8 +2,17 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Represents a user group along with the users that were added to or removed from it. +/// public class UserGroupWithUsers { + /// + /// Initializes a new instance of the class. + /// + /// The user group. + /// The users that were added to the group. + /// The users that were removed from the group. public UserGroupWithUsers(IUserGroup userGroup, IUser[] addedUsers, IUser[] removedUsers) { UserGroup = userGroup; @@ -11,9 +20,18 @@ public UserGroupWithUsers(IUserGroup userGroup, IUser[] addedUsers, IUser[] remo RemovedUsers = removedUsers; } + /// + /// Gets the user group. + /// public IUserGroup UserGroup { get; } + /// + /// Gets the users that were added to the group. + /// public IUser[] AddedUsers { get; } + /// + /// Gets the users that were removed from the group. + /// public IUser[] RemovedUsers { get; } } diff --git a/src/Umbraco.Core/Events/UserNotificationsHandler.cs b/src/Umbraco.Core/Events/UserNotificationsHandler.cs index 6356046963a0..4d8fd66d89e3 100644 --- a/src/Umbraco.Core/Events/UserNotificationsHandler.cs +++ b/src/Umbraco.Core/Events/UserNotificationsHandler.cs @@ -17,6 +17,9 @@ namespace Umbraco.Cms.Core.Events; +/// +/// Handles content-related notifications to send user notifications. +/// public sealed class UserNotificationsHandler : INotificationHandler, INotificationHandler, @@ -33,6 +36,12 @@ public sealed class UserNotificationsHandler : private readonly IContentService _contentService; private readonly Notifier _notifier; + /// + /// Initializes a new instance of the class. + /// + /// The notifier service. + /// The action collection. + /// The content service. public UserNotificationsHandler(Notifier notifier, ActionCollection actions, IContentService contentService) { _notifier = notifier; @@ -40,6 +49,7 @@ public UserNotificationsHandler(Notifier notifier, ActionCollection actions, ICo _contentService = contentService; } + /// public void Handle(AssignedUserGroupPermissionsNotification notification) { IContent[]? entities = _contentService.GetByIds(notification.EntityPermissions.Select(e => e.EntityId)).ToArray(); @@ -51,9 +61,11 @@ public void Handle(AssignedUserGroupPermissionsNotification notification) _notifier.Notify(_actions.GetAction(), entities!); } + /// public void Handle(ContentCopiedNotification notification) => _notifier.Notify(_actions.GetAction(), notification.Original); + /// public void Handle(ContentMovedNotification notification) { // notify about the move for all moved items @@ -72,15 +84,19 @@ public void Handle(ContentMovedNotification notification) } } + /// public void Handle(ContentMovedToRecycleBinNotification notification) => _notifier.Notify( _actions.GetAction(), notification.MoveInfoCollection.Select(m => m.Entity).ToArray()); + /// public void Handle(ContentPublishedNotification notification) => _notifier.Notify(_actions.GetAction(), notification.PublishedEntities.ToArray()); + /// public void Handle(ContentRolledBackNotification notification) => _notifier.Notify(_actions.GetAction(), notification.Entity); + /// public void Handle(ContentSavedNotification notification) { var newEntities = new List(); @@ -106,6 +122,7 @@ public void Handle(ContentSavedNotification notification) _notifier.Notify(_actions.GetAction(), updatedEntities.ToArray()); } + /// public void Handle(ContentSortedNotification notification) { var parentId = notification.SortedEntities.Select(x => x.ParentId).Distinct().ToList(); @@ -130,9 +147,11 @@ public void Handle(ContentSortedNotification notification) _notifier.Notify(_actions.GetAction(), parent); } + /// public void Handle(ContentUnpublishedNotification notification) => _notifier.Notify(_actions.GetAction(), notification.UnpublishedEntities.ToArray()); + /// public void Handle(PublicAccessEntrySavedNotification notification) { IContent[] entities = _contentService.GetByIds(notification.SavedEntities.Select(e => e.ProtectedNodeId)).ToArray(); @@ -180,6 +199,11 @@ public Notifier( globalSettings.OnChange(x => _globalSettings = x); } + /// + /// Sends notifications for the specified action and entities. + /// + /// The action that was performed. + /// The entities that were affected. public void Notify(IAction? action, params IContent[] entities) { IUser? user = _backOfficeSecurityAccessor?.BackOfficeSecurity?.CurrentUser; @@ -205,6 +229,13 @@ public void Notify(IAction? action, params IContent[] entities) SendNotification(user, entities, action, _hostingEnvironment.ApplicationMainUrl); } + /// + /// Sends notification emails for the specified entities. + /// + /// The user who performed the action. + /// The entities that were affected. + /// The action that was performed. + /// The site URI. private void SendNotification(IUser sender, IEnumerable entities, IAction? action, Uri? siteUri) { if (sender == null) diff --git a/src/Umbraco.Core/ExpressionHelper.cs b/src/Umbraco.Core/ExpressionHelper.cs index 4d437e809f3e..c39ad90c86fc 100644 --- a/src/Umbraco.Core/ExpressionHelper.cs +++ b/src/Umbraco.Core/ExpressionHelper.cs @@ -11,6 +11,9 @@ namespace Umbraco.Cms.Core; /// public static class ExpressionHelper { + /// + /// Cache for storing objects retrieved from expressions. + /// private static readonly ConcurrentDictionary PropertyInfoCache = new(); /// @@ -87,6 +90,13 @@ public static PropertyInfo return propInfo; }); + /// + /// Finds the property or member referenced by a lambda expression. + /// + /// The lambda expression to analyze. + /// A tuple containing the and an optional alias string. + /// The expression does not resolve to a top-level member. + /// The expression configuration is invalid. public static (MemberInfo, string?) FindProperty(LambdaExpression lambda) { void Throw() @@ -139,6 +149,16 @@ void Throw() throw new Exception("Configuration for members is only supported for top-level individual members on a type."); } + /// + /// Gets the method parameters from an expression as a dictionary. + /// + /// The input type of the expression. + /// The return type of the expression. + /// The expression containing the method call. + /// + /// A dictionary mapping parameter names to their values, an empty dictionary if the expression is not a method call, + /// or null if the expression is null. + /// public static IDictionary? GetMethodParams(Expression> fromExpression) { if (fromExpression == null) diff --git a/src/Umbraco.Core/Extensions/AssemblyExtensions.cs b/src/Umbraco.Core/Extensions/AssemblyExtensions.cs index 5cd48d6fb4e8..c62dfaf7e299 100644 --- a/src/Umbraco.Core/Extensions/AssemblyExtensions.cs +++ b/src/Umbraco.Core/Extensions/AssemblyExtensions.cs @@ -7,6 +7,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class AssemblyExtensions { private static string _rootDir = string.Empty; diff --git a/src/Umbraco.Core/Extensions/ClaimsIdentityExtensions.cs b/src/Umbraco.Core/Extensions/ClaimsIdentityExtensions.cs index 0a0daeda5a97..bc0b91ec0a82 100644 --- a/src/Umbraco.Core/Extensions/ClaimsIdentityExtensions.cs +++ b/src/Umbraco.Core/Extensions/ClaimsIdentityExtensions.cs @@ -13,6 +13,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for and . +/// public static class ClaimsIdentityExtensions { private static string? _authenticationType; @@ -37,6 +40,12 @@ public static class ClaimsIdentityExtensions ClaimTypes.Locality, Constants.Security.SecurityStampClaimType, }; + /// + /// Gets the user ID from the identity, converted to the specified type. + /// + /// The type to convert the user ID to. + /// The identity. + /// The user ID converted to the specified type, or the default value if not found or conversion fails. public static T? GetUserId(this IIdentity identity) { var strId = identity.GetUserId(); @@ -119,6 +128,12 @@ public static class ClaimsIdentityExtensions return username; } + /// + /// Gets the email address from the identity. + /// + /// The identity. + /// The email address if found; otherwise, null. + /// Thrown when identity is null. public static string? GetEmail(this IIdentity identity) { if (identity == null) diff --git a/src/Umbraco.Core/Extensions/ConfigurationExtensions.cs b/src/Umbraco.Core/Extensions/ConfigurationExtensions.cs index 0f9f3a372565..d113854f7b87 100644 --- a/src/Umbraco.Core/Extensions/ConfigurationExtensions.cs +++ b/src/Umbraco.Core/Extensions/ConfigurationExtensions.cs @@ -93,5 +93,10 @@ public static class ConfigurationExtensions public static RuntimeMode GetRuntimeMode(this IConfiguration configuration) => configuration.GetValue(Constants.Configuration.ConfigRuntimeMode); + /// + /// Gets the configured ModelsBuilder mode. + /// + /// The configuration. + /// The ModelsBuilder mode string. public static string GetModelsMode(this IConfiguration configuration) => (configuration.GetSection(Constants.Configuration.ConfigModelsBuilder).Get() ?? new ModelsBuilderSettings()).ModelsMode; } diff --git a/src/Umbraco.Core/Extensions/ContentExtensions.cs b/src/Umbraco.Core/Extensions/ContentExtensions.cs index 35b9d945d8cf..32e8a54f826c 100644 --- a/src/Umbraco.Core/Extensions/ContentExtensions.cs +++ b/src/Umbraco.Core/Extensions/ContentExtensions.cs @@ -13,6 +13,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for , , and types. +/// public static class ContentExtensions { /// @@ -50,10 +53,29 @@ public static bool TryGetMediaPath( return true; } + /// + /// Determines whether any user property of the content base is dirty (has been modified). + /// + /// The content entity to check. + /// true if any property is dirty; otherwise, false. public static bool IsAnyUserPropertyDirty(this IContentBase entity) => entity.Properties.Any(x => x.IsDirty()); + /// + /// Determines whether any user property of the content base was dirty (was modified before the last save). + /// + /// The content entity to check. + /// true if any property was dirty; otherwise, false. public static bool WasAnyUserPropertyDirty(this IContentBase entity) => entity.Properties.Any(x => x.WasDirty()); + /// + /// Determines whether the content entity is being moved as part of a bulk move operation. + /// + /// The content entity to check. + /// true if the entity is being moved; otherwise, false. + /// + /// When moving, only Path, Level, and UpdateDate properties are changed. + /// This allows bypassing version creation operations since the move cannot be rolled back. + /// public static bool IsMoving(this IContentBase entity) { // Check if this entity is being moved as a descendant as part of a bulk moving operations. @@ -184,6 +206,11 @@ public static IEnumerable #region Dirty + /// + /// Gets the aliases of all dirty (modified) user properties. + /// + /// The content entity. + /// A collection of property aliases that are dirty. public static IEnumerable GetDirtyUserProperties(this IContentBase entity) => entity.Properties.Where(x => x.IsDirty()).Select(x => x.Alias); diff --git a/src/Umbraco.Core/Extensions/CoreCacheHelperExtensions.cs b/src/Umbraco.Core/Extensions/CoreCacheHelperExtensions.cs index 1af0b8c47a21..a9e1552d0473 100644 --- a/src/Umbraco.Core/Extensions/CoreCacheHelperExtensions.cs +++ b/src/Umbraco.Core/Extensions/CoreCacheHelperExtensions.cs @@ -10,6 +10,9 @@ namespace Umbraco.Extensions; /// public static class CoreCacheHelperExtensions { + /// + /// The cache key used for partial view caching. + /// public const string PartialViewCacheKey = "Umbraco.Web.PartialViewCacheKey"; /// diff --git a/src/Umbraco.Core/Extensions/DeliveryApiSettingsExtensions.cs b/src/Umbraco.Core/Extensions/DeliveryApiSettingsExtensions.cs index 2f49086cea57..fabdda266758 100644 --- a/src/Umbraco.Core/Extensions/DeliveryApiSettingsExtensions.cs +++ b/src/Umbraco.Core/Extensions/DeliveryApiSettingsExtensions.cs @@ -9,10 +9,22 @@ namespace Umbraco.Extensions; /// public static class DeliveryApiSettingsExtensions { + /// + /// Determines whether a content item is allowed to be exposed through the Delivery API. + /// + /// The Delivery API settings. + /// The content item to check. + /// true if the content type is allowed; otherwise, false. [Obsolete("Please use the overload of IsAllowedContentType taking a content type alias. Scheduled for removal in Umbraco 19.")] public static bool IsAllowedContentType(this DeliveryApiSettings settings, IPublishedContent content) => settings.IsAllowedContentType(content.ContentType.Alias); + /// + /// Determines whether a content item is disallowed from being exposed through the Delivery API. + /// + /// The Delivery API settings. + /// The content item to check. + /// true if the content type is disallowed; otherwise, false. [Obsolete("Please use IsAllowedContentType and negate the result instead. Scheduled for removal in Umbraco 19.")] public static bool IsDisallowedContentType(this DeliveryApiSettings settings, IPublishedContent content) => settings.IsDisallowedContentType(content.ContentType.Alias); @@ -42,6 +54,12 @@ public static bool IsAllowedContentType(this DeliveryApiSettings settings, strin return settings.DisallowedContentTypeAliases.InvariantContains(contentTypeAlias) is false; } + /// + /// Determines whether a content type alias is disallowed from being exposed through the Delivery API. + /// + /// The Delivery API settings. + /// The content type alias to check. + /// true if the content type is disallowed; otherwise, false. [Obsolete("Please use IsAllowedContentType and negate the result instead. Scheduled for removal in Umbraco 19.")] public static bool IsDisallowedContentType(this DeliveryApiSettings settings, string contentTypeAlias) => settings.IsAllowedContentType(contentTypeAlias) is false; diff --git a/src/Umbraco.Core/Extensions/DictionaryExtensions.cs b/src/Umbraco.Core/Extensions/DictionaryExtensions.cs index a0e0e17371fd..ffc5c73a56e2 100644 --- a/src/Umbraco.Core/Extensions/DictionaryExtensions.cs +++ b/src/Umbraco.Core/Extensions/DictionaryExtensions.cs @@ -306,6 +306,16 @@ public static TValue GetValueIgnoreCase(this IDictionary : defaultValue; } + /// + /// Asynchronously converts an enumerable to a dictionary using an async value selector. + /// + /// The type of the input elements. + /// The type of the dictionary keys. + /// The type of the dictionary values. + /// The source enumerable. + /// A function to extract the key from each element. + /// An async function to extract the value from each element. + /// A task that represents the asynchronous operation, containing the resulting dictionary. public static async Task> ToDictionaryAsync( this IEnumerable enumerable, Func syncKeySelector, diff --git a/src/Umbraco.Core/Extensions/EnumerableExtensions.cs b/src/Umbraco.Core/Extensions/EnumerableExtensions.cs index 7bbb010e2da9..bc5995540cdd 100644 --- a/src/Umbraco.Core/Extensions/EnumerableExtensions.cs +++ b/src/Umbraco.Core/Extensions/EnumerableExtensions.cs @@ -11,6 +11,12 @@ namespace Umbraco.Extensions; /// public static class EnumerableExtensions { + /// + /// Determines whether the collection is null or empty. + /// + /// The type of items in the collection. + /// The collection to check. + /// true if the collection is null or empty; otherwise, false. public static bool IsCollectionEmpty(this IReadOnlyCollection? list) => list == null || list.Count == 0; /// @@ -25,6 +31,13 @@ public static IEnumerable Yield(this T item) yield return item; } + /// + /// Determines whether the enumerable contains duplicate items. + /// + /// The type of items in the enumerable. + /// The items to check. + /// If true, null values are considered when checking for duplicates. + /// true if duplicates exist; otherwise, false. internal static bool HasDuplicates(this IEnumerable items, bool includeNull) { var hs = new HashSet(); @@ -39,6 +52,15 @@ internal static bool HasDuplicates(this IEnumerable items, bool includeNul return false; } + /// + /// Splits the enumerable into groups of the specified size. + /// + /// The type of items in the enumerable. + /// The source enumerable. + /// The size of each group. + /// An enumerable of groups, each containing up to the specified number of items. + /// Thrown when source is null. + /// Thrown when groupSize is less than or equal to zero. public static IEnumerable> InGroupsOf(this IEnumerable? source, int groupSize) { if (source == null) @@ -79,6 +101,15 @@ public static IEnumerable> InGroupsOf(this IEnumerable? sou } } + /// + /// Selects items by processing the source in groups of the specified size. + /// + /// The type of the result items. + /// The type of the source items. + /// The source enumerable. + /// The selector function to apply to each group. + /// The size of each group. + /// An enumerable of results from processing each group. public static IEnumerable SelectByGroups( this IEnumerable source, Func, IEnumerable> selector, @@ -193,6 +224,15 @@ public static void RemoveAll(this ICollection list, Func predicat } } + /// + /// Recursively selects items from the source using the specified selector. + /// + /// The type of the source items. + /// The source enumerable. + /// A function that returns child elements for each item. + /// The maximum recursion depth to prevent stack overflow. + /// A flattened enumerable of all items and their recursive children. + /// Thrown when the maximum recursion depth is exceeded. public static IEnumerable SelectRecursive( this IEnumerable source, Func> recursiveSelector, @@ -245,6 +285,14 @@ public static IEnumerable WhereNotNull(this IEnumerable coll) => coll.Where(x => x != null)!; + /// + /// Applies a projection action to all items in the sequence that are of the specified actual type. + /// + /// The base type of items in the sequence. + /// The actual type to filter and apply the projection to. + /// The source sequence. + /// The action to apply to each item of the actual type. + /// The original sequence, allowing chaining. public static IEnumerable ForAllThatAre( this IEnumerable sequence, Action projection) @@ -371,11 +419,25 @@ public static IEnumerable Transform( /// public static IEnumerable EmptyNull(this IEnumerable? items) => items ?? Enumerable.Empty(); - // the .OfType() filter is nice when there's only one type - // this is to support filtering with multiple types + /// + /// Filters a sequence to include only items whose type is in the specified list of types. + /// + /// The type of items in the sequence. + /// The source sequence. + /// The types to include. + /// A filtered sequence containing only items of the specified types. + /// + /// This is similar to .OfType<T>() but supports filtering with multiple types. + /// public static IEnumerable OfTypes(this IEnumerable contents, params Type[] types) => contents.Where(x => types.Contains(x?.GetType())); + /// + /// Returns all elements of the sequence except the last one. + /// + /// The type of items in the enumerable. + /// The source enumerable. + /// An enumerable containing all elements except the last. public static IEnumerable SkipLast(this IEnumerable source) { using (IEnumerator e = source.GetEnumerator()) @@ -392,6 +454,15 @@ public static IEnumerable SkipLast(this IEnumerable source) } } + /// + /// Orders the elements of a sequence according to a key and the specified sort direction. + /// + /// The type of the elements of source. + /// The type of the key returned by keySelector. + /// A sequence of values to order. + /// A function to extract a key from an element. + /// The direction to sort (ascending or descending). + /// An ordered enumerable. public static IOrderedEnumerable OrderBy( this IEnumerable source, Func keySelector, diff --git a/src/Umbraco.Core/Extensions/GuidExtensions.cs b/src/Umbraco.Core/Extensions/GuidExtensions.cs index b7eb302c474d..8101093011d8 100644 --- a/src/Umbraco.Core/Extensions/GuidExtensions.cs +++ b/src/Umbraco.Core/Extensions/GuidExtensions.cs @@ -1,7 +1,19 @@ -namespace Umbraco.Cms.Core.Extensions; +namespace Umbraco.Cms.Core.Extensions; +/// +/// Provides extension methods for . +/// public static class GuidExtensions { + /// + /// Determines whether the GUID was created from an integer using . + /// + /// The GUID to check. + /// true if the GUID was created from an integer; otherwise, false. + /// + /// A "fake" GUID is one where only the first 4 bytes contain data (from the original integer) + /// and all remaining bytes are zero. + /// public static bool IsFakeGuid(this Guid guid) { var bytes = guid.ToByteArray(); @@ -11,6 +23,14 @@ public static bool IsFakeGuid(this Guid guid) return bytes[4..].All(x => x == 0); } + /// + /// Converts a GUID that was created from an integer back to its original integer value. + /// + /// The GUID to convert. + /// The integer value. + /// + /// This method should only be used on GUIDs that were created using . + /// public static int ToInt(this Guid guid) { var bytes = guid.ToByteArray(); diff --git a/src/Umbraco.Core/Extensions/HtmlEncodedStringExtensions.cs b/src/Umbraco.Core/Extensions/HtmlEncodedStringExtensions.cs index 9af5b25d27d1..de789826b590 100644 --- a/src/Umbraco.Core/Extensions/HtmlEncodedStringExtensions.cs +++ b/src/Umbraco.Core/Extensions/HtmlEncodedStringExtensions.cs @@ -3,6 +3,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class HtmlEncodedStringExtensions { /// diff --git a/src/Umbraco.Core/Extensions/IntExtensions.cs b/src/Umbraco.Core/Extensions/IntExtensions.cs index 5b744e26e2c1..f857512f93ee 100644 --- a/src/Umbraco.Core/Extensions/IntExtensions.cs +++ b/src/Umbraco.Core/Extensions/IntExtensions.cs @@ -5,6 +5,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class IntExtensions { /// diff --git a/src/Umbraco.Core/Extensions/LineEndingsExtensions.cs b/src/Umbraco.Core/Extensions/LineEndingsExtensions.cs index f074c2777613..0efe1046ea74 100644 --- a/src/Umbraco.Core/Extensions/LineEndingsExtensions.cs +++ b/src/Umbraco.Core/Extensions/LineEndingsExtensions.cs @@ -1,7 +1,10 @@ -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; namespace Umbraco.Cms.Core.Extensions; +/// +/// Provides extension methods for ensuring consistent line endings in strings. +/// public static class LineEndingsExtensions { /// diff --git a/src/Umbraco.Core/Extensions/MediaTypeExtensions.cs b/src/Umbraco.Core/Extensions/MediaTypeExtensions.cs index f9aec08a6194..d49e96249d8d 100644 --- a/src/Umbraco.Core/Extensions/MediaTypeExtensions.cs +++ b/src/Umbraco.Core/Extensions/MediaTypeExtensions.cs @@ -6,8 +6,16 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class MediaTypeExtensions { + /// + /// Determines whether the media type is a built-in system media type (File, Folder, or Image). + /// + /// The media type to check. + /// true if the media type is a system media type; otherwise, false. public static bool IsSystemMediaType(this IMediaType mediaType) => mediaType.Alias == Constants.Conventions.MediaTypes.File || mediaType.Alias == Constants.Conventions.MediaTypes.Folder diff --git a/src/Umbraco.Core/Extensions/MemberTypeExtensions.cs b/src/Umbraco.Core/Extensions/MemberTypeExtensions.cs index 6c3209a52ea8..efd0564b9dce 100644 --- a/src/Umbraco.Core/Extensions/MemberTypeExtensions.cs +++ b/src/Umbraco.Core/Extensions/MemberTypeExtensions.cs @@ -1,12 +1,25 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Extensions; +/// +/// Provides extension methods for . +/// public static class MemberTypeExtensions { + /// + /// Gets all property types that are marked as sensitive. + /// + /// The member type. + /// An enumerable of sensitive property types. public static IEnumerable GetSensitivePropertyTypes(this IMemberType memberType) => memberType.CompositionPropertyTypes.Where(p => memberType.IsSensitiveProperty(p.Alias)); + /// + /// Gets the aliases of all property types that are marked as sensitive. + /// + /// The member type. + /// An enumerable of sensitive property type aliases. public static IEnumerable GetSensitivePropertyTypeAliases(this IMemberType memberType) => memberType.GetSensitivePropertyTypes().Select(p => p.Alias); } diff --git a/src/Umbraco.Core/Extensions/PasswordConfigurationExtensions.cs b/src/Umbraco.Core/Extensions/PasswordConfigurationExtensions.cs index 30cbe8a83139..38c34a481465 100644 --- a/src/Umbraco.Core/Extensions/PasswordConfigurationExtensions.cs +++ b/src/Umbraco.Core/Extensions/PasswordConfigurationExtensions.cs @@ -5,6 +5,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class PasswordConfigurationExtensions { /// @@ -29,6 +32,11 @@ public static IDictionary GetConfiguration( { "allowManuallyChangingPassword", allowManuallyChangingPassword }, }; + /// + /// Gets the minimum number of non-alphanumeric characters required for a password. + /// + /// The password configuration. + /// 1 if non-letter or digit characters are required; otherwise, 0. public static int GetMinNonAlphaNumericChars(this IPasswordConfiguration passwordConfiguration) => passwordConfiguration.RequireNonLetterOrDigit ? 1 : 0; } diff --git a/src/Umbraco.Core/Extensions/PublishedElementExtensions.cs b/src/Umbraco.Core/Extensions/PublishedElementExtensions.cs index c85178c85c49..9ee2cb4aa173 100644 --- a/src/Umbraco.Core/Extensions/PublishedElementExtensions.cs +++ b/src/Umbraco.Core/Extensions/PublishedElementExtensions.cs @@ -14,8 +14,17 @@ public static class PublishedElementExtensions { #region OfTypes - // the .OfType() filter is nice when there's only one type - // this is to support filtering with multiple types + /// + /// Filters published elements by their content type alias. + /// + /// The type of published elements. + /// The elements to filter. + /// The content type aliases to include. + /// Elements whose content type alias matches any of the specified types. + /// + /// The .OfType<T>() filter is nice when there's only one type. + /// This method supports filtering with multiple types. + /// public static IEnumerable OfTypes(this IEnumerable contents, params string[] types) where T : IPublishedElement { @@ -195,6 +204,12 @@ public static bool HasValue(this IPublishedElement content, string alias, string #region ToIndexedArray + /// + /// Converts an enumerable of published elements to an indexed array with positional information. + /// + /// The type of published elements. + /// The source enumerable. + /// An array of indexed items containing positional information. public static IndexedArrayItem[] ToIndexedArray(this IEnumerable source) where TContent : class, IPublishedElement { diff --git a/src/Umbraco.Core/Extensions/PublishedPropertyExtension.cs b/src/Umbraco.Core/Extensions/PublishedPropertyExtension.cs index 267157cf7acf..264d945ddaa1 100644 --- a/src/Umbraco.Core/Extensions/PublishedPropertyExtension.cs +++ b/src/Umbraco.Core/Extensions/PublishedPropertyExtension.cs @@ -13,6 +13,16 @@ public static class PublishedPropertyExtension { #region Value + /// + /// Gets the value of a published property with fallback support. + /// + /// The published property. + /// The published value fallback implementation. + /// The variation language. + /// The variation segment. + /// The fallback strategy. + /// The default value if no value is found. + /// The property value, or the fallback/default value if not found. public static object? Value(this IPublishedProperty property, IPublishedValueFallback publishedValueFallback, string? culture = null, string? segment = null, Fallback fallback = default, object? defaultValue = default) { if (property.HasValue(culture, segment)) @@ -29,6 +39,17 @@ public static class PublishedPropertyExtension #region Value + /// + /// Gets the value of a published property converted to the specified type, with fallback support. + /// + /// The target type to convert the value to. + /// The published property. + /// The published value fallback implementation. + /// The variation language. + /// The variation segment. + /// The fallback strategy. + /// The default value if no value is found. + /// The property value converted to the specified type, or the fallback/default value if not found. public static T? Value(this IPublishedProperty property, IPublishedValueFallback publishedValueFallback, string? culture = null, string? segment = null, Fallback fallback = default, T? defaultValue = default) { if (property.HasValue(culture, segment)) diff --git a/src/Umbraco.Core/Extensions/RuntimeStateExtensions.cs b/src/Umbraco.Core/Extensions/RuntimeStateExtensions.cs index 219b73c39f25..b6d80f14e41e 100644 --- a/src/Umbraco.Core/Extensions/RuntimeStateExtensions.cs +++ b/src/Umbraco.Core/Extensions/RuntimeStateExtensions.cs @@ -3,6 +3,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class RuntimeStateExtensions { /// diff --git a/src/Umbraco.Core/Extensions/SemVersionExtensions.cs b/src/Umbraco.Core/Extensions/SemVersionExtensions.cs index afdd49612ee0..17edcd910c43 100644 --- a/src/Umbraco.Core/Extensions/SemVersionExtensions.cs +++ b/src/Umbraco.Core/Extensions/SemVersionExtensions.cs @@ -5,11 +5,24 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class SemVersionExtensions { + /// + /// Converts the semantic version to a properly formatted semantic version string. + /// + /// The semantic version. + /// The semantic version string with corrected formatting. public static string ToSemanticString(this SemVersion semVersion) => semVersion.ToString().Replace("--", "-").Replace("-+", "+"); + /// + /// Converts the semantic version to a string without the build metadata. + /// + /// The semantic version. + /// The semantic version string without build metadata. public static string ToSemanticStringWithoutBuild(this SemVersion semVersion) { var version = semVersion.ToSemanticString(); diff --git a/src/Umbraco.Core/Extensions/TemporaryFileServiceExtensions.cs b/src/Umbraco.Core/Extensions/TemporaryFileServiceExtensions.cs index b2ebb3930402..00ee4843b36c 100644 --- a/src/Umbraco.Core/Extensions/TemporaryFileServiceExtensions.cs +++ b/src/Umbraco.Core/Extensions/TemporaryFileServiceExtensions.cs @@ -4,8 +4,18 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class TemporaryFileServiceExtensions { + /// + /// Enlists a temporary file for deletion when the current scope completes successfully. + /// + /// The temporary file service. + /// The key of the temporary file to delete. + /// The core scope provider. + /// The name of the calling member (automatically populated). public static void EnlistDeleteIfScopeCompletes(this ITemporaryFileService temporaryFileService, Guid temporaryFileKey, ICoreScopeProvider scopeProvider, [CallerMemberName] string memberName = "") { scopeProvider.Context?.Enlist( diff --git a/src/Umbraco.Core/Extensions/TreeEntityExtensions.cs b/src/Umbraco.Core/Extensions/TreeEntityExtensions.cs index d39d8efa1936..277d4f88fbd8 100644 --- a/src/Umbraco.Core/Extensions/TreeEntityExtensions.cs +++ b/src/Umbraco.Core/Extensions/TreeEntityExtensions.cs @@ -1,10 +1,18 @@ -using System.Globalization; +using System.Globalization; using Umbraco.Cms.Core.Models.Entities; namespace Umbraco.Cms.Core.Extensions; +/// +/// Provides extension methods for . +/// public static class TreeEntityExtensions { + /// + /// Gets the ancestor IDs of the tree entity. + /// + /// The tree entity. + /// An array of ancestor IDs, excluding the root and the entity itself. public static int[] AncestorIds(this ITreeEntity entity) { string[] commaSeparatedValues = entity.Path.Split(Constants.CharArrays.Comma); diff --git a/src/Umbraco.Core/Extensions/TypeExtensions.cs b/src/Umbraco.Core/Extensions/TypeExtensions.cs index 6be68ae0a4b2..c93647d61c10 100644 --- a/src/Umbraco.Core/Extensions/TypeExtensions.cs +++ b/src/Umbraco.Core/Extensions/TypeExtensions.cs @@ -11,8 +11,16 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class TypeExtensions { + /// + /// Gets the default value for the specified type. + /// + /// The type to get the default value for. + /// The default value for the type (null for reference types, the default instance for value types). public static object? GetDefaultValue(this Type t) => t.IsValueType ? Activator.CreateInstance(t) @@ -39,6 +47,12 @@ public static bool IsAnonymousType(this Type type) && (type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic; } + /// + /// Gets all base types of the specified type. + /// + /// The type to get base types for. + /// If true, includes the type itself in the results. + /// An enumerable of base types. public static IEnumerable GetBaseTypes(this Type? type, bool andSelf) { if (andSelf) @@ -52,6 +66,13 @@ public static bool IsAnonymousType(this Type type) } } + /// + /// Gets a generic method by name and parameter types. + /// + /// The type to search for the method. + /// The name of the method. + /// The parameter types of the method. + /// The method info if found; otherwise, null. internal static MethodInfo? GetGenericMethod(this Type type, string name, params Type[] parameterTypes) { IEnumerable methods = type.GetMethods().Where(method => method.Name == name); @@ -68,10 +89,11 @@ public static bool IsAnonymousType(this Type type) } /// - /// Determines whether the specified type is enumerable. + /// Determines whether the method has the specified parameter types. /// - /// The type. - /// + /// The method to check. + /// The expected parameter types. + /// true if the method has the specified parameter types; otherwise, false. internal static bool HasParameters(this MethodInfo method, params Type[] parameterTypes) { Type[] methodParameters = method.GetParameters().Select(parameter => parameter.ParameterType).ToArray(); @@ -92,6 +114,11 @@ internal static bool HasParameters(this MethodInfo method, params Type[] paramet return true; } + /// + /// Gets all methods from the type and its interfaces. + /// + /// The type to get methods from. + /// An enumerable of all methods. public static IEnumerable AllMethods(this Type target) { // var allTypes = target.AllInterfaces().ToList(); @@ -101,6 +128,10 @@ public static IEnumerable AllMethods(this Type target) return allTypes.SelectMany(t => t.GetMethods()); } + /// + /// Determines whether the specified type implements . + /// + /// The type to check. /// /// true if the specified type is enumerable; otherwise, false. /// @@ -269,32 +300,89 @@ public static MethodInfo[] GetAllMethods(this Type type) /// public static bool IsType(this Type actualType) => TypeHelper.IsTypeAssignableFrom(actualType); + /// + /// Determines whether the type inherits from the specified base type. + /// + /// The base type to check. + /// The type to check. + /// true if the type inherits from the base type; otherwise, false. public static bool Inherits(this Type type) => typeof(TBase).IsAssignableFrom(type); + /// + /// Determines whether the type inherits from the specified base type. + /// + /// The type to check. + /// The base type to check. + /// true if the type inherits from the base type; otherwise, false. public static bool Inherits(this Type type, Type tbase) => tbase.IsAssignableFrom(type); + /// + /// Determines whether the type implements the specified interface. + /// + /// The interface type to check. + /// The type to check. + /// true if the type implements the interface; otherwise, false. public static bool Implements(this Type type) => typeof(TInterface).IsAssignableFrom(type); + /// + /// Gets the first attribute of the specified type from the type. + /// + /// The type of attribute to get. + /// The type to get the attribute from. + /// The first attribute of the specified type, or null if not found. public static TAttribute? FirstAttribute(this Type type) => type.FirstAttribute(true); + /// + /// Gets the first attribute of the specified type from the type. + /// + /// The type of attribute to get. + /// The type to get the attribute from. + /// Whether to search the inheritance chain. + /// The first attribute of the specified type, or null if not found. public static TAttribute? FirstAttribute(this Type type, bool inherit) { var attrs = type.GetCustomAttributes(typeof(TAttribute), inherit); return (TAttribute?)(attrs.Length > 0 ? attrs[0] : null); } + /// + /// Gets the first attribute of the specified type from the property. + /// + /// The type of attribute to get. + /// The property to get the attribute from. + /// The first attribute of the specified type, or null if not found. public static TAttribute? FirstAttribute(this PropertyInfo propertyInfo) => propertyInfo.FirstAttribute(true); + /// + /// Gets the first attribute of the specified type from the property. + /// + /// The type of attribute to get. + /// The property to get the attribute from. + /// Whether to search the inheritance chain. + /// The first attribute of the specified type, or null if not found. public static TAttribute? FirstAttribute(this PropertyInfo propertyInfo, bool inherit) { var attrs = propertyInfo.GetCustomAttributes(typeof(TAttribute), inherit); return (TAttribute?)(attrs.Length > 0 ? attrs[0] : null); } + /// + /// Gets all attributes of the specified type from the property. + /// + /// The type of attribute to get. + /// The property to get the attributes from. + /// An enumerable of attributes, or null if none found. public static IEnumerable? MultipleAttribute(this PropertyInfo propertyInfo) => propertyInfo.MultipleAttribute(true); + /// + /// Gets all attributes of the specified type from the property. + /// + /// The type of attribute to get. + /// The property to get the attributes from. + /// Whether to search the inheritance chain. + /// An enumerable of attributes, or null if none found. public static IEnumerable? MultipleAttribute(this PropertyInfo propertyInfo, bool inherit) { var attrs = propertyInfo.GetCustomAttributes(typeof(TAttribute), inherit); @@ -322,6 +410,46 @@ public static string GetFullNameWithAssembly(this Type type) return string.Concat(type.FullName, ", ", assemblyName.FullName.StartsWith("App_Code.") ? "App_Code" : assemblyName.Name); } + /// + /// Gets a custom attribute of the specified type from the type. + /// + /// The type of attribute to get. + /// The type to get the attribute from. + /// Whether to search the inheritance chain. + /// The custom attribute, or null if not found. + public static T? GetCustomAttribute(this Type type, bool inherit) + where T : Attribute => + type.GetCustomAttributes(inherit).SingleOrDefault(); + + /// + /// Gets all custom attributes of the specified type from the type. + /// + /// The type of attributes to get. + /// The type to get the attributes from. + /// Whether to search the inheritance chain. + /// An enumerable of custom attributes. + public static IEnumerable GetCustomAttributes(this Type? type, bool inherited) + where T : Attribute + { + if (type == null) + { + return Enumerable.Empty(); + } + + return type.GetCustomAttributes(typeof(T), inherited).OfType(); + } + + /// + /// Determines whether the type has a custom attribute of the specified type. + /// + /// The type of attribute to check for. + /// The type to check. + /// Whether to search the inheritance chain. + /// true if the type has the attribute; otherwise, false. + public static bool HasCustomAttribute(this Type type, bool inherit) + where T : Attribute => + type.GetCustomAttribute(inherit) != null; + /// /// Determines whether an instance of a specified type can be assigned to the current type instance. /// @@ -389,25 +517,6 @@ public static bool IsAssignableFromGtd(this Type type, Type c) return null; } - public static T? GetCustomAttribute(this Type type, bool inherit) - where T : Attribute => - type.GetCustomAttributes(inherit).SingleOrDefault(); - - public static IEnumerable GetCustomAttributes(this Type? type, bool inherited) - where T : Attribute - { - if (type == null) - { - return Enumerable.Empty(); - } - - return type.GetCustomAttributes(typeof(T), inherited).OfType(); - } - - public static bool HasCustomAttribute(this Type type, bool inherit) - where T : Attribute => - type.GetCustomAttribute(inherit) != null; - /// /// Tries to return a value based on a property name for an object but ignores case sensitivity /// diff --git a/src/Umbraco.Core/Extensions/TypeLoaderExtensions.cs b/src/Umbraco.Core/Extensions/TypeLoaderExtensions.cs index 1ea73af00910..599e63a84950 100644 --- a/src/Umbraco.Core/Extensions/TypeLoaderExtensions.cs +++ b/src/Umbraco.Core/Extensions/TypeLoaderExtensions.cs @@ -8,6 +8,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class TypeLoaderExtensions { /// diff --git a/src/Umbraco.Core/Extensions/UmbracoBuilderExtensions.cs b/src/Umbraco.Core/Extensions/UmbracoBuilderExtensions.cs index 53e86109c3f6..61adb20bc23e 100644 --- a/src/Umbraco.Core/Extensions/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Core/Extensions/UmbracoBuilderExtensions.cs @@ -4,6 +4,9 @@ namespace Umbraco.Cms.Core.Extensions; +/// +/// Provides extension methods for related to notification handler registration. +/// public static class UmbracoBuilderExtensions { /// diff --git a/src/Umbraco.Core/Extensions/UmbracoContextAccessorExtensions.cs b/src/Umbraco.Core/Extensions/UmbracoContextAccessorExtensions.cs index b0256ad9e625..e81374d29277 100644 --- a/src/Umbraco.Core/Extensions/UmbracoContextAccessorExtensions.cs +++ b/src/Umbraco.Core/Extensions/UmbracoContextAccessorExtensions.cs @@ -5,8 +5,18 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class UmbracoContextAccessorExtensions { + /// + /// Gets the Umbraco context, throwing an exception if it is not available. + /// + /// The Umbraco context accessor. + /// The current Umbraco context. + /// Thrown when the accessor is null. + /// Thrown when the Umbraco context is not available. public static IUmbracoContext GetRequiredUmbracoContext(this IUmbracoContextAccessor umbracoContextAccessor) { if (umbracoContextAccessor == null) diff --git a/src/Umbraco.Core/Extensions/UmbracoContextExtensions.cs b/src/Umbraco.Core/Extensions/UmbracoContextExtensions.cs index e5ec62530d66..edcc235e3f7f 100644 --- a/src/Umbraco.Core/Extensions/UmbracoContextExtensions.cs +++ b/src/Umbraco.Core/Extensions/UmbracoContextExtensions.cs @@ -5,6 +5,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class UmbracoContextExtensions { /// diff --git a/src/Umbraco.Core/Extensions/UserServiceExtensions.cs b/src/Umbraco.Core/Extensions/UserServiceExtensions.cs index 0946891b31d5..29ee3c4721d5 100644 --- a/src/Umbraco.Core/Extensions/UserServiceExtensions.cs +++ b/src/Umbraco.Core/Extensions/UserServiceExtensions.cs @@ -1,10 +1,20 @@ -using Umbraco.Cms.Core.Models.Membership; +using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Services; namespace Umbraco.Cms.Core.Extensions; +/// +/// Provides extension methods for . +/// public static class UserServiceExtensions { + /// + /// Gets a user by key, throwing an exception if not found. + /// + /// The user service. + /// The unique key of the user. + /// The user with the specified key. + /// Thrown when the user with the specified key cannot be found. public static async Task GetRequiredUserAsync(this IUserService userService, Guid key) => await userService.GetAsync(key) ?? throw new InvalidOperationException($"Could not find user with key: {key}"); diff --git a/src/Umbraco.Core/Extensions/VersionExtensions.cs b/src/Umbraco.Core/Extensions/VersionExtensions.cs index 4e9309da4586..89f587e31a65 100644 --- a/src/Umbraco.Core/Extensions/VersionExtensions.cs +++ b/src/Umbraco.Core/Extensions/VersionExtensions.cs @@ -6,8 +6,17 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for and . +/// public static class VersionExtensions { + /// + /// Converts a to a . + /// + /// The semantic version to convert. + /// The maximum number of version parts to include (2, 3, or 4). Defaults to 4. + /// A instance representing the semantic version. public static Version GetVersion(this SemVersion semVersion, int maxParts = 4) { int.TryParse(semVersion.Build, NumberStyles.Integer, CultureInfo.InvariantCulture, out int build); @@ -25,6 +34,12 @@ public static Version GetVersion(this SemVersion semVersion, int maxParts = 4) return new Version(semVersion.Major, semVersion.Minor); } + /// + /// Subtracts one from the revision number of a version. + /// + /// The version to modify. + /// A new version with the revision decremented by one. + /// Thrown when attempting to subtract from a zero version. public static Version SubtractRevision(this Version version) { var parts = new List(new[] { version.Major, version.Minor, version.Build, version.Revision }); @@ -79,6 +94,11 @@ public static Version SubtractRevision(this Version version) return FromList(parts); } + /// + /// Creates a version from a list of integer parts. + /// + /// The list of version parts. + /// A instance. private static Version FromList(IList parts) { while (parts.Count < 4) diff --git a/src/Umbraco.Core/Extensions/WaitHandleExtensions.cs b/src/Umbraco.Core/Extensions/WaitHandleExtensions.cs index add643415c2b..b8407524a86a 100644 --- a/src/Umbraco.Core/Extensions/WaitHandleExtensions.cs +++ b/src/Umbraco.Core/Extensions/WaitHandleExtensions.cs @@ -3,12 +3,21 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class WaitHandleExtensions { - // http://stackoverflow.com/questions/25382583/waiting-on-a-named-semaphore-with-waitone100-vs-waitone0-task-delay100 - // http://blog.nerdbank.net/2011/07/c-await-for-waithandle.html - // F# has a AwaitWaitHandle method that accepts a time out... and seems pretty complex... - // version below should be OK + /// + /// Asynchronously waits for the wait handle to be signaled. + /// + /// The wait handle to wait on. + /// The timeout in milliseconds. Defaults to . + /// A task that completes when the wait handle is signaled or the timeout elapses. + /// + /// Based on http://stackoverflow.com/questions/25382583/waiting-on-a-named-semaphore-with-waitone100-vs-waitone0-task-delay100 + /// and http://blog.nerdbank.net/2011/07/c-await-for-waithandle.html. + /// public static Task WaitOneAsync(this WaitHandle handle, int millisecondsTimeout = Timeout.Infinite) { var tcs = new TaskCompletionSource(); diff --git a/src/Umbraco.Core/Extensions/XmlExtensions.cs b/src/Umbraco.Core/Extensions/XmlExtensions.cs index e879907592a6..41dfc157cdfa 100644 --- a/src/Umbraco.Core/Extensions/XmlExtensions.cs +++ b/src/Umbraco.Core/Extensions/XmlExtensions.cs @@ -13,6 +13,12 @@ namespace Umbraco.Extensions; /// public static class XmlExtensions { + /// + /// Determines whether the attribute collection contains an attribute with the specified name. + /// + /// The XML attribute collection. + /// The name of the attribute to check for. + /// true if the collection contains the attribute; otherwise, false. public static bool HasAttribute(this XmlAttributeCollection attributes, string attributeName) => attributes.Cast().Any(x => x.Name == attributeName); @@ -46,11 +52,11 @@ public static XDocument ToXDocument(this XmlDocument xmlDocument) } } - ///// - ///// Converts from an XElement to an XmlElement - ///// - ///// - ///// + /// + /// Converts from an to an . + /// + /// The XContainer to convert. + /// The document element as an XmlNode, or null if the document has no root element. public static XmlNode? ToXmlElement(this XContainer xElement) { var xmlDocument = new XmlDocument(); @@ -76,6 +82,15 @@ public static XElement ToXElement(this XmlNode xmlElement) } } + /// + /// Gets the required attribute value from an XML element, converted to the specified type. + /// + /// The type to convert the attribute value to. + /// The XML element. + /// The name of the attribute. + /// The attribute value converted to the specified type. + /// Thrown when the xml parameter is null. + /// Thrown when the attribute is not found or cannot be converted. public static T? RequiredAttributeValue(this XElement xml, string attributeName) { if (xml == null) @@ -103,6 +118,14 @@ public static XElement ToXElement(this XmlNode xmlElement) throw new InvalidOperationException($"{attribute.Value} attribute value cannot be converted to {typeof(T)}"); } + /// + /// Gets an attribute value from an XML element, converted to the specified type. + /// + /// The type to convert the attribute value to. + /// The XML element. + /// The name of the attribute. + /// The attribute value converted to the specified type, or the default value if not found or conversion fails. + /// Thrown when the xml parameter is null. public static T? AttributeValue(this XElement xml, string attributeName) { if (xml == null) @@ -125,6 +148,14 @@ public static XElement ToXElement(this XmlNode xmlElement) return default; } + /// + /// Gets an attribute value from an XML node, converted to the specified type. + /// + /// The type to convert the attribute value to. + /// The XML node. + /// The name of the attribute. + /// The attribute value converted to the specified type, or the default value if not found or conversion fails. + /// Thrown when the xml parameter is null. public static T? AttributeValue(this XmlNode xml, string attributeName) { if (xml == null) @@ -152,6 +183,11 @@ public static XElement ToXElement(this XmlNode xmlElement) return default; } + /// + /// Converts an to an . + /// + /// The XML node to convert. + /// The converted XElement, or null if the node has no root element. public static XElement? GetXElement(this XmlNode node) { var xDoc = new XDocument(); @@ -163,6 +199,11 @@ public static XElement ToXElement(this XmlNode xmlElement) return xDoc.Root; } + /// + /// Converts an to an . + /// + /// The XContainer to convert. + /// The converted XmlNode, or null if conversion fails. public static XmlNode? GetXmlNode(this XContainer element) { using (XmlReader xmlReader = element.CreateReader()) @@ -173,6 +214,12 @@ public static XElement ToXElement(this XmlNode xmlElement) } } + /// + /// Converts an to an and imports it into the specified document. + /// + /// The XContainer to convert. + /// The XML document to import the node into. + /// The imported XmlNode, or null if conversion fails. public static XmlNode? GetXmlNode(this XContainer element, XmlDocument xmlDoc) { XmlNode? node = element.GetXmlNode(); @@ -184,11 +231,15 @@ public static XElement ToXElement(this XmlNode xmlElement) return null; } - // this exists because - // new XElement("root", "a\nb").Value is "a\nb" but - // .ToString(SaveOptions.*) is "a\r\nb" and cannot figure out how to get rid of "\r" - // and when saving data we want nothing to change - // this method will produce a string that respects the \r and \n in the data value + /// + /// Converts an to a string while preserving the exact line endings in text values. + /// + /// The XML element to convert. + /// A string representation of the XML element with preserved line endings. + /// + /// This method exists because with SaveOptions changes line endings. + /// When saving data, we want the exact characters to be preserved. + /// public static string ToDataString(this XElement xml) { var settings = new XmlWriterSettings diff --git a/src/Umbraco.Core/Factories/IInstallSettingsFactory.cs b/src/Umbraco.Core/Factories/IInstallSettingsFactory.cs index fbec5b80169a..94af7a110bcd 100644 --- a/src/Umbraco.Core/Factories/IInstallSettingsFactory.cs +++ b/src/Umbraco.Core/Factories/IInstallSettingsFactory.cs @@ -2,7 +2,14 @@ namespace Umbraco.Cms.Core.Factories; +/// +/// Factory interface for creating instances. +/// public interface IInstallSettingsFactory { + /// + /// Gets the installation settings model containing database and user settings. + /// + /// An containing installation settings. InstallSettingsModel GetInstallSettings(); } diff --git a/src/Umbraco.Core/Factories/IUpgradeSettingsFactory.cs b/src/Umbraco.Core/Factories/IUpgradeSettingsFactory.cs index b60b067f2408..6fdb9f0d709e 100644 --- a/src/Umbraco.Core/Factories/IUpgradeSettingsFactory.cs +++ b/src/Umbraco.Core/Factories/IUpgradeSettingsFactory.cs @@ -1,8 +1,15 @@ -using Umbraco.Cms.Core.Models.Installer; +using Umbraco.Cms.Core.Models.Installer; namespace Umbraco.Cms.Core.Factories; +/// +/// Factory interface for creating instances. +/// public interface IUpgradeSettingsFactory { + /// + /// Gets the upgrade settings model containing version and migration state information. + /// + /// An containing upgrade-related settings. UpgradeSettingsModel GetUpgradeSettings(); } diff --git a/src/Umbraco.Core/Factories/IUserSettingsFactory.cs b/src/Umbraco.Core/Factories/IUserSettingsFactory.cs index b517f2437cdc..ba4a05f04b6c 100644 --- a/src/Umbraco.Core/Factories/IUserSettingsFactory.cs +++ b/src/Umbraco.Core/Factories/IUserSettingsFactory.cs @@ -2,7 +2,14 @@ namespace Umbraco.Cms.Core.Factories; +/// +/// Factory interface for creating instances. +/// public interface IUserSettingsFactory { + /// + /// Gets the user settings model containing password settings and consent levels. + /// + /// A containing user-related settings. UserSettingsModel GetUserSettings(); } diff --git a/src/Umbraco.Core/Factories/InstallSettingsFactory.cs b/src/Umbraco.Core/Factories/InstallSettingsFactory.cs index f0fbe4aba79c..f271a9f58e91 100644 --- a/src/Umbraco.Core/Factories/InstallSettingsFactory.cs +++ b/src/Umbraco.Core/Factories/InstallSettingsFactory.cs @@ -2,11 +2,19 @@ namespace Umbraco.Cms.Core.Factories; +/// +/// Factory for creating instances containing installation settings. +/// public class InstallSettingsFactory : IInstallSettingsFactory { private readonly IUserSettingsFactory _userSettingsFactory; private readonly IDatabaseSettingsFactory _databaseSettingsFactory; + /// + /// Initializes a new instance of the class. + /// + /// The factory for user settings. + /// The factory for database settings. public InstallSettingsFactory( IUserSettingsFactory userSettingsFactory, IDatabaseSettingsFactory databaseSettingsFactory) @@ -15,6 +23,7 @@ public InstallSettingsFactory( _databaseSettingsFactory = databaseSettingsFactory; } + /// public InstallSettingsModel GetInstallSettings() => new() { diff --git a/src/Umbraco.Core/Factories/MachineInfoFactory.cs b/src/Umbraco.Core/Factories/MachineInfoFactory.cs index f8edf0a197c8..15101e30a1df 100644 --- a/src/Umbraco.Core/Factories/MachineInfoFactory.cs +++ b/src/Umbraco.Core/Factories/MachineInfoFactory.cs @@ -1,12 +1,19 @@ -using System.Diagnostics; +using System.Diagnostics; using Umbraco.Cms.Core.Hosting; namespace Umbraco.Cms.Core.Factories; +/// +/// Default implementation of that fetches information about the host machine. +/// internal sealed class MachineInfoFactory : IMachineInfoFactory { private readonly IHostingEnvironment _hostingEnvironment; + /// + /// Initializes a new instance of the class. + /// + /// The hosting environment. public MachineInfoFactory(IHostingEnvironment hostingEnvironment) { _hostingEnvironment = hostingEnvironment; diff --git a/src/Umbraco.Core/Factories/UpgradeSettingsFactory.cs b/src/Umbraco.Core/Factories/UpgradeSettingsFactory.cs index 007219da3617..82a0ec372d1f 100644 --- a/src/Umbraco.Core/Factories/UpgradeSettingsFactory.cs +++ b/src/Umbraco.Core/Factories/UpgradeSettingsFactory.cs @@ -1,15 +1,23 @@ -using Umbraco.Cms.Core.Configuration; +using Umbraco.Cms.Core.Configuration; using Umbraco.Cms.Core.Semver; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Models.Installer; namespace Umbraco.Cms.Core.Factories; +/// +/// Factory for creating instances containing upgrade-related settings. +/// public class UpgradeSettingsFactory : IUpgradeSettingsFactory { private readonly IRuntimeState _runtimeState; private readonly IUmbracoVersion _umbracoVersion; + /// + /// Initializes a new instance of the class. + /// + /// The runtime state providing migration information. + /// The Umbraco version information. public UpgradeSettingsFactory( IRuntimeState runtimeState, IUmbracoVersion umbracoVersion) @@ -18,7 +26,7 @@ public UpgradeSettingsFactory( _umbracoVersion = umbracoVersion; } - + /// public UpgradeSettingsModel GetUpgradeSettings() { var model = new UpgradeSettingsModel diff --git a/src/Umbraco.Core/Factories/UserSettingsFactory.cs b/src/Umbraco.Core/Factories/UserSettingsFactory.cs index 99da578eaab4..1b36b3793cc0 100644 --- a/src/Umbraco.Core/Factories/UserSettingsFactory.cs +++ b/src/Umbraco.Core/Factories/UserSettingsFactory.cs @@ -7,11 +7,19 @@ namespace Umbraco.Cms.Core.Factories; +/// +/// Factory for creating instances containing user-related settings for installation. +/// public class UserSettingsFactory : IUserSettingsFactory { private readonly ILocalizedTextService _localizedTextService; private readonly UserPasswordConfigurationSettings _passwordConfiguration; + /// + /// Initializes a new instance of the class. + /// + /// The user password configuration settings. + /// The localized text service for retrieving localized descriptions. public UserSettingsFactory( IOptions securitySettings, ILocalizedTextService localizedTextService) @@ -20,6 +28,7 @@ public UserSettingsFactory( _passwordConfiguration = securitySettings.Value; } + /// public UserSettingsModel GetUserSettings() => new() { @@ -27,6 +36,10 @@ public UserSettingsModel GetUserSettings() => ConsentLevels = CreateConsentLevelModels(), }; + /// + /// Creates the password settings model from the current password configuration. + /// + /// A containing password requirements. private PasswordSettingsModel CreatePasswordSettingsModel() => new() { @@ -34,6 +47,10 @@ private PasswordSettingsModel CreatePasswordSettingsModel() => MinNonAlphaNumericLength = _passwordConfiguration.GetMinNonAlphaNumericChars() }; + /// + /// Creates consent level models for all available telemetry levels. + /// + /// A collection of for each telemetry level. private IEnumerable CreateConsentLevelModels() => Enum.GetValues() .Select(level => new ConsentLevelModel @@ -42,6 +59,12 @@ private IEnumerable CreateConsentLevelModels() => Description = GetTelemetryLevelDescription(level), }); + /// + /// Gets the localized description for a telemetry level. + /// + /// The telemetry level to get the description for. + /// The localized description string. + /// Thrown when an unexpected telemetry level is provided. private string GetTelemetryLevelDescription(TelemetryLevel telemetryLevel) => telemetryLevel switch { TelemetryLevel.Minimal => _localizedTextService.Localize("analytics", "minimalLevelDescription"), diff --git a/src/Umbraco.Core/FireAndForgetRunner.cs b/src/Umbraco.Core/FireAndForgetRunner.cs index 8c466bd43976..e87cbc1828dd 100644 --- a/src/Umbraco.Core/FireAndForgetRunner.cs +++ b/src/Umbraco.Core/FireAndForgetRunner.cs @@ -1,14 +1,24 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; namespace Umbraco.Cms.Core; - +/// +/// Default implementation of that runs tasks on background threads. +/// +/// +/// This implementation suppresses the execution context flow to prevent AsyncLocal values from leaking to child threads. +/// public class FireAndForgetRunner : IFireAndForgetRunner { private readonly ILogger _logger; + /// + /// Initializes a new instance of the class. + /// + /// The logger for recording exceptions from background tasks. public FireAndForgetRunner(ILogger logger) => _logger = logger; + /// public void RunFireAndForget(Func task) => ExecuteBackgroundTask(task); private Task ExecuteBackgroundTask(Func fn) diff --git a/src/Umbraco.Core/GuidUdi.cs b/src/Umbraco.Core/GuidUdi.cs index 7f95299fd842..679a1939c959 100644 --- a/src/Umbraco.Core/GuidUdi.cs +++ b/src/Umbraco.Core/GuidUdi.cs @@ -41,6 +41,7 @@ public GuidUdi(Uri uriValue) /// public override bool IsRoot => Guid == Guid.Empty; + /// public override bool Equals(object? obj) { if (obj is not GuidUdi other) @@ -51,8 +52,14 @@ public override bool Equals(object? obj) return EntityType == other.EntityType && Guid == other.Guid; } + /// public override int GetHashCode() => base.GetHashCode(); + /// + /// Ensures that this GuidUdi is not a root Udi. + /// + /// This GuidUdi. + /// When this Udi is a root Udi. public GuidUdi EnsureClosed() { EnsureNotRoot(); diff --git a/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs b/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs index 889f95fec467..af7a856e3020 100644 --- a/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs +++ b/src/Umbraco.Core/Handlers/AuditNotificationsHandler.cs @@ -16,6 +16,19 @@ namespace Umbraco.Cms.Core.Handlers; +/// +/// Handles audit logging for member and user related notifications. +/// +/// +/// +/// This handler creates audit trail entries for various member and user operations including +/// saving, deleting, role assignments, exports, and permission changes. +/// +/// +/// The audit entries record the performing user, affected entity, IP address, and event details +/// to provide a comprehensive audit trail for security and compliance purposes. +/// +/// public sealed class AuditNotificationsHandler : INotificationHandler, INotificationAsyncHandler, @@ -44,6 +57,16 @@ public sealed class AuditNotificationsHandler : private readonly IUserGroupService _userGroupService; private readonly IUserService _userService; + /// + /// Initializes a new instance of the class. + /// + /// The audit entry service for writing audit records. + /// The user service. + /// The entity service. + /// The IP address resolver. + /// The back office security accessor. + /// The member service. + /// The user group service. public AuditNotificationsHandler( IAuditEntryService auditEntryService, IUserService userService, @@ -62,6 +85,17 @@ public AuditNotificationsHandler( _userGroupService = userGroupService; } + /// + /// Initializes a new instance of the class. + /// + /// The audit service (no longer used). + /// The user service. + /// The entity service. + /// The IP address resolver. + /// The global settings (no longer used). + /// The back office security accessor. + /// The member service. + /// The user group service. [Obsolete("Use the non-obsolete constructor instead. Scheduled for removal in V19.")] public AuditNotificationsHandler( IAuditService auditService, @@ -83,6 +117,18 @@ public AuditNotificationsHandler( { } + /// + /// Initializes a new instance of the class. + /// + /// The audit entry service for writing audit records. + /// The audit service (no longer used). + /// The user service. + /// The entity service. + /// The IP address resolver. + /// The global settings (no longer used). + /// The back office security accessor. + /// The member service. + /// The user group service. [Obsolete("Use the non-obsolete constructor instead. Scheduled for removal in V19.")] public AuditNotificationsHandler( IAuditEntryService auditEntryService, @@ -105,11 +151,18 @@ public AuditNotificationsHandler( { } + /// + /// Gets the current user performing the action from the back office security context. + /// + /// The current user, or null if no user is authenticated. private async Task GetCurrentPerformingUser() => _backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser is { } identity ? await _userService.GetAsync(identity.Key) : null; + /// + /// Gets the IP address of the current request. + /// private string PerformingIp => _ipResolver.GetCurrentRequestIpAddress(); /// @@ -131,6 +184,7 @@ await Audit( } } + /// [Obsolete("Use HandleAsync() instead. Scheduled for removal in V19.")] public void Handle(AssignedMemberRolesNotification notification) => HandleAsync(notification, CancellationToken.None).GetAwaiter().GetResult(); @@ -157,6 +211,7 @@ await Audit( } } + /// [Obsolete("Use HandleAsync() instead. Scheduled for removal in V19.")] public void Handle(AssignedUserGroupPermissionsNotification notification) => HandleAsync(notification, CancellationToken.None).GetAwaiter().GetResult(); @@ -175,10 +230,12 @@ await Audit( "exported member data"); } + /// [Obsolete("Use HandleAsync() instead. Scheduled for removal in V19.")] public void Handle(ExportedMemberNotification notification) => HandleAsync(notification, CancellationToken.None).GetAwaiter().GetResult(); + /// public async Task HandleAsync(MemberDeletedNotification notification, CancellationToken cancellationToken) { IUser? performingUser = await GetCurrentPerformingUser(); @@ -194,6 +251,7 @@ await Audit( } } + /// [Obsolete("Use HandleAsync() instead. Scheduled for removal in V19.")] public void Handle(MemberDeletedNotification notification) => HandleAsync(notification, CancellationToken.None).GetAwaiter().GetResult(); @@ -216,6 +274,7 @@ await Audit( } } + /// [Obsolete("Use HandleAsync() instead. Scheduled for removal in V19.")] public void Handle(MemberSavedNotification notification) => HandleAsync(notification, CancellationToken.None).GetAwaiter().GetResult(); @@ -239,6 +298,7 @@ await Audit( } } + /// [Obsolete("Use HandleAsync() instead. Scheduled for removal in V19.")] public void Handle(RemovedMemberRolesNotification notification) => HandleAsync(notification, CancellationToken.None).GetAwaiter().GetResult(); @@ -259,10 +319,12 @@ await Audit( } } + /// [Obsolete("Use HandleAsync() instead. Scheduled for removal in V19.")] public void Handle(UserDeletedNotification notification) => HandleAsync(notification, CancellationToken.None).GetAwaiter().GetResult(); + /// public async Task HandleAsync(UserGroupWithUsersSavedNotification notification, CancellationToken cancellationToken) { IUser? performingUser = await GetCurrentPerformingUser(); @@ -325,6 +387,7 @@ await Audit( } } + /// [Obsolete("Use HandleAsync() instead. Scheduled for removal in V19.")] public void Handle(UserGroupWithUsersSavedNotification notification) => HandleAsync(notification, CancellationToken.None).GetAwaiter().GetResult(); @@ -351,10 +414,20 @@ await Audit( } } + /// [Obsolete("Use HandleAsync() instead. Scheduled for removal in V19.")] public void Handle(UserSavedNotification notification) => HandleAsync(notification, CancellationToken.None).GetAwaiter().GetResult(); + /// + /// Writes an audit entry for the specified action. + /// + /// The user performing the action. + /// The user affected by the action, if applicable. + /// Details about the affected entity. + /// The type of event being audited. + /// Additional details about the event. + /// A task representing the asynchronous operation. private async Task Audit( IUser? performingUser, IUser? affectedUser, @@ -374,6 +447,12 @@ await _auditEntryService.WriteAsync( eventDetails); } + /// + /// Formats user details for audit logging. + /// + /// The user to format details for. + /// If true, prepends "User" to the output. + /// A formatted string containing user details. private static string FormatDetails(IUser? user, bool appendType = false) { var userName = user?.Name ?? Constants.Security.UnknownUserName; @@ -385,9 +464,22 @@ private static string FormatDetails(IUser? user, bool appendType = false) : details; } + /// + /// Formats member details for audit logging. + /// + /// The member to format details for. + /// If true, prepends "Member" to the output. + /// A formatted string containing member details. private static string FormatDetails(IMember member, bool appendType = false) => FormatDetails(member.Id, member, appendType); + /// + /// Formats member details for audit logging using the member ID and optional member instance. + /// + /// The member ID. + /// The member instance, or null if not available. + /// If true, prepends "Member" to the output. + /// A formatted string containing member details. private static string FormatDetails(int id, IMember? member, bool appendType = false) { var userName = member?.Name ?? "(unknown)"; @@ -399,7 +491,17 @@ private static string FormatDetails(int id, IMember? member, bool appendType = f : details; } + /// + /// Formats user group details for audit logging. + /// + /// The user group to format details for. + /// A formatted string containing user group details. private static string FormatDetails(IUserGroup group) => $"{group.Id} \"{group.Name}\" ({group.Alias})"; + /// + /// Formats an email address for display in audit logs. + /// + /// The email address to format. + /// The email wrapped in angle brackets, or null if the email is empty. private static string? FormatEmail(string? email) => !email.IsNullOrWhiteSpace() ? $"<{email}>" : null; } diff --git a/src/Umbraco.Core/Handlers/PublicAccessHandler.cs b/src/Umbraco.Core/Handlers/PublicAccessHandler.cs index 3262e225e00c..1a3c0e59d44c 100644 --- a/src/Umbraco.Core/Handlers/PublicAccessHandler.cs +++ b/src/Umbraco.Core/Handlers/PublicAccessHandler.cs @@ -6,6 +6,19 @@ namespace Umbraco.Cms.Core.Handlers; +/// +/// Handles public access rule updates when member groups are renamed or deleted. +/// +/// +/// +/// This handler monitors member group saving and deleting notifications to ensure that +/// public access rules referencing member groups are updated when group names change. +/// +/// +/// When a member group is renamed, this handler updates all public access rules that +/// reference the group's previous name to use the new name. +/// +/// public sealed class PublicAccessHandler : INotificationAsyncHandler, INotificationHandler, @@ -15,22 +28,37 @@ public sealed class PublicAccessHandler : private readonly IPublicAccessService _publicAccessService; private readonly IMemberGroupService _memberGroupService; + /// + /// Initializes a new instance of the class. + /// + /// The public access service for managing access rules. + /// The member group service. public PublicAccessHandler(IPublicAccessService publicAccessService, IMemberGroupService memberGroupService) { _publicAccessService = publicAccessService; _memberGroupService = memberGroupService; } + /// public async Task HandleAsync(MemberGroupSavingNotification notification, CancellationToken cancellationToken) => await SaveStateAsync(notification.SavedEntities, notification); + /// public async Task HandleAsync(MemberGroupDeletingNotification notification, CancellationToken cancellationToken) => await SaveStateAsync(notification.DeletedEntities, notification); + /// public void Handle(MemberGroupDeletedNotification notification) => Handle(notification.DeletedEntities, notification); + /// public void Handle(MemberGroupSavedNotification notification) => Handle(notification.SavedEntities, notification); + /// + /// Saves the current member group names to the notification state for later comparison. + /// + /// The member groups being affected by the operation. + /// The notification containing the state dictionary. + /// A task representing the asynchronous operation. private async Task SaveStateAsync(IEnumerable affectedEntities, IStatefulNotification notification) { foreach (IMemberGroup memberGroup in affectedEntities) @@ -46,6 +74,11 @@ private async Task SaveStateAsync(IEnumerable affectedEntities, IS } } + /// + /// Handles the post-save or post-delete notification by updating public access rules if group names changed. + /// + /// The member groups that were affected. + /// The notification containing the saved state. private void Handle(IEnumerable affectedEntities, IStatefulNotification notification) { foreach (IMemberGroup grp in affectedEntities) @@ -63,5 +96,10 @@ private void Handle(IEnumerable affectedEntities, IStatefulNotific } } + /// + /// Generates a unique state key for tracking member group state changes. + /// + /// The member group to generate a key for. + /// A unique key string for the member group. private static string StateKey(IMemberGroup memberGroup) => $"{nameof(PublicAccessHandler)}:{memberGroup.Key}"; } diff --git a/src/Umbraco.Core/Handlers/WarnDocumentTypeElementSwitchNotificationHandler.cs b/src/Umbraco.Core/Handlers/WarnDocumentTypeElementSwitchNotificationHandler.cs index ab6b82c735e5..1a9ba654cb90 100644 --- a/src/Umbraco.Core/Handlers/WarnDocumentTypeElementSwitchNotificationHandler.cs +++ b/src/Umbraco.Core/Handlers/WarnDocumentTypeElementSwitchNotificationHandler.cs @@ -7,6 +7,20 @@ namespace Umbraco.Cms.Core.Handlers; +/// +/// Handles notifications for document type element switch validation and generates warnings +/// when the element flag change creates misalignment with ancestors or descendants. +/// +/// +/// +/// This handler monitors and +/// to detect when a document type's property changes. +/// +/// +/// When a change is detected, it validates that the element flag is consistent with ancestor +/// and descendant content types, generating warnings if misalignment is found. +/// +/// public class WarnDocumentTypeElementSwitchNotificationHandler : INotificationAsyncHandler, INotificationAsyncHandler @@ -18,6 +32,12 @@ public class WarnDocumentTypeElementSwitchNotificationHandler : private readonly IContentTypeService _contentTypeService; private readonly IElementSwitchValidator _elementSwitchValidator; + /// + /// Initializes a new instance of the class. + /// + /// The factory for creating event messages. + /// The content type service. + /// The validator for element switch operations. public WarnDocumentTypeElementSwitchNotificationHandler( IEventMessagesFactory eventMessagesFactory, IContentTypeService contentTypeService, @@ -28,7 +48,10 @@ public WarnDocumentTypeElementSwitchNotificationHandler( _elementSwitchValidator = elementSwitchValidator; } - // To figure out whether a warning should be generated, we need both the state before and after saving + /// + /// + /// To figure out whether a warning should be generated, we need both the state before and after saving. + /// public async Task HandleAsync(ContentTypeSavingNotification notification, CancellationToken cancellationToken) { IEnumerable updatedKeys = notification.SavedEntities @@ -44,6 +67,7 @@ public async Task HandleAsync(ContentTypeSavingNotification notification, Cancel notification.State[NotificationStateKey] = stateInformation; } + /// public async Task HandleAsync(ContentTypeSavedNotification notification, CancellationToken cancellationToken) { if (notification.State[NotificationStateKey] is not Dictionary @@ -72,6 +96,12 @@ public async Task HandleAsync(ContentTypeSavedNotification notification, Cancell } } + /// + /// Adds a warning event message if the content type's ancestors have misaligned element flags. + /// + /// The content type to validate. + /// The event messages collection to add warnings to. + /// A task representing the asynchronous operation. private async Task WarnIfAncestorsAreMisaligned(IContentType contentType, EventMessages eventMessages) { if (await _elementSwitchValidator.AncestorsAreAlignedAsync(contentType) == false) @@ -84,6 +114,12 @@ private async Task WarnIfAncestorsAreMisaligned(IContentType contentType, EventM } } + /// + /// Adds a warning event message if the content type's descendants have misaligned element flags. + /// + /// The content type to validate. + /// The event messages collection to add warnings to. + /// A task representing the asynchronous operation. private async Task WarnIfDescendantsAreMisaligned(IContentType contentType, EventMessages eventMessages) { if (await _elementSwitchValidator.DescendantsAreAlignedAsync(contentType) == false) @@ -96,8 +132,14 @@ private async Task WarnIfDescendantsAreMisaligned(IContentType contentType, Even } } + /// + /// Holds state information about a document type's element flag before saving. + /// private sealed class DocumentTypeElementSwitchInformation { + /// + /// Gets or sets a value indicating whether the document type was an element type before saving. + /// public bool WasElement { get; set; } } } diff --git a/src/Umbraco.Core/HashCodeCombiner.cs b/src/Umbraco.Core/HashCodeCombiner.cs index 3506d335b887..5014dd57ac02 100644 --- a/src/Umbraco.Core/HashCodeCombiner.cs +++ b/src/Umbraco.Core/HashCodeCombiner.cs @@ -17,12 +17,28 @@ public class HashCodeCombiner { private long _combinedHash = 5381L; + /// + /// Adds an integer value to the combined hash. + /// + /// The integer value to add. public void AddInt(int i) => _combinedHash = ((_combinedHash << 5) + _combinedHash) ^ i; + /// + /// Adds an object's hash code to the combined hash. + /// + /// The object to add. public void AddObject(object o) => AddInt(o.GetHashCode()); + /// + /// Adds a DateTime value to the combined hash. + /// + /// The DateTime value to add. public void AddDateTime(DateTime d) => AddInt(d.GetHashCode()); + /// + /// Adds a string value to the combined hash using invariant culture. + /// + /// The string value to add. public void AddString(string s) { if (s != null) @@ -31,6 +47,10 @@ public void AddString(string s) } } + /// + /// Adds a string value to the combined hash using case-insensitive comparison. + /// + /// The string value to add. public void AddCaseInsensitiveString(string s) { if (s != null) @@ -39,6 +59,14 @@ public void AddCaseInsensitiveString(string s) } } + /// + /// Adds a file system item (file or directory) to the combined hash. + /// + /// The file system item to add. + /// + /// This method adds the full name, creation time, last write time, and (for files) the length. + /// For directories, all contained files and subdirectories are recursively added. + /// public void AddFileSystemItem(FileSystemInfo f) { // if it doesn't exist, don't proceed. @@ -71,8 +99,16 @@ public void AddFileSystemItem(FileSystemInfo f) } } + /// + /// Adds a file to the combined hash. + /// + /// The file to add. public void AddFile(FileInfo f) => AddFileSystemItem(f); + /// + /// Adds a folder and all its contents to the combined hash. + /// + /// The directory to add. public void AddFolder(DirectoryInfo d) => AddFileSystemItem(d); /// diff --git a/src/Umbraco.Core/HashCodeHelper.cs b/src/Umbraco.Core/HashCodeHelper.cs index ecf209c53221..2f3540d072d0 100644 --- a/src/Umbraco.Core/HashCodeHelper.cs +++ b/src/Umbraco.Core/HashCodeHelper.cs @@ -5,6 +5,14 @@ namespace Umbraco.Cms.Core; /// public static class HashCodeHelper { + /// + /// Gets a combined hash code for two values. + /// + /// The type of the first value. + /// The type of the second value. + /// The first value. + /// The second value. + /// A combined hash code. public static int GetHashCode(T1 arg1, T2 arg2) { unchecked @@ -13,6 +21,16 @@ public static int GetHashCode(T1 arg1, T2 arg2) } } + /// + /// Gets a combined hash code for three values. + /// + /// The type of the first value. + /// The type of the second value. + /// The type of the third value. + /// The first value. + /// The second value. + /// The third value. + /// A combined hash code. public static int GetHashCode(T1 arg1, T2 arg2, T3 arg3) { unchecked @@ -23,6 +41,18 @@ public static int GetHashCode(T1 arg1, T2 arg2, T3 arg3) } } + /// + /// Gets a combined hash code for four values. + /// + /// The type of the first value. + /// The type of the second value. + /// The type of the third value. + /// The type of the fourth value. + /// The first value. + /// The second value. + /// The third value. + /// The fourth value. + /// A combined hash code. public static int GetHashCode(T1 arg1, T2 arg2, T3 arg3, T4 arg4) { unchecked @@ -34,6 +64,12 @@ public static int GetHashCode(T1 arg1, T2 arg2, T3 arg3, T4 arg4 } } + /// + /// Gets a combined hash code for an array of values. + /// + /// The type of the values. + /// The array of values. + /// A combined hash code. public static int GetHashCode(T[] list) { unchecked @@ -53,6 +89,12 @@ public static int GetHashCode(T[] list) } } + /// + /// Gets a combined hash code for an enumerable collection of values. + /// + /// The type of the values. + /// The collection of values. + /// A combined hash code. public static int GetHashCode(IEnumerable list) { unchecked diff --git a/src/Umbraco.Core/HealthChecks/AcceptableConfiguration.cs b/src/Umbraco.Core/HealthChecks/AcceptableConfiguration.cs index 42420b895432..9e61f746fb50 100644 --- a/src/Umbraco.Core/HealthChecks/AcceptableConfiguration.cs +++ b/src/Umbraco.Core/HealthChecks/AcceptableConfiguration.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.HealthChecks; +/// +/// Represents an acceptable configuration value for a health check. +/// public class AcceptableConfiguration { + /// + /// Gets or sets the acceptable configuration value. + /// public string? Value { get; set; } + /// + /// Gets or sets a value indicating whether this configuration value is the recommended setting. + /// public bool IsRecommended { get; set; } } diff --git a/src/Umbraco.Core/HealthChecks/Checks/Data/DatabaseIntegrityCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Data/DatabaseIntegrityCheck.cs index 8ee30d75ac52..dbb806df24d7 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Data/DatabaseIntegrityCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Data/DatabaseIntegrityCheck.cs @@ -35,9 +35,7 @@ public DatabaseIntegrityCheck( _mediaService = mediaService; } - /// - /// Get the status for this health check - /// + /// public override Task> GetStatusAsync() => Task.FromResult((IEnumerable)new[] { CheckDocuments(false), CheckMedia(false) }); diff --git a/src/Umbraco.Core/HealthChecks/Checks/Permissions/FolderAndFilePermissionsCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Permissions/FolderAndFilePermissionsCheck.cs index f530144b99e4..cc1f9c0b312a 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Permissions/FolderAndFilePermissionsCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Permissions/FolderAndFilePermissionsCheck.cs @@ -32,9 +32,7 @@ public FolderAndFilePermissionsCheck( _filePermissionHelper = filePermissionHelper; } - /// - /// Get the status for this health check - /// + /// public override Task> GetStatusAsync() { _filePermissionHelper.RunFilePermissionTestSuite( @@ -48,9 +46,7 @@ public override Task> GetStatusAsync() })); } - /// - /// Executes the action and returns it's status - /// + /// public override HealthCheckStatus ExecuteAction(HealthCheckAction action) => throw new InvalidOperationException("FolderAndFilePermissionsCheck has no executable actions"); diff --git a/src/Umbraco.Core/HealthChecks/Checks/ProvidedValueValidation.cs b/src/Umbraco.Core/HealthChecks/Checks/ProvidedValueValidation.cs index 041ace503f42..90697ae167c5 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/ProvidedValueValidation.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/ProvidedValueValidation.cs @@ -3,9 +3,23 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks; +/// +/// Specifies the type of validation to apply to a provided value in a health check action. +/// public enum ProvidedValueValidation { + /// + /// No validation is required for the provided value. + /// None = 1, + + /// + /// The provided value must be a valid email address. + /// Email = 2, + + /// + /// The provided value must match a specified regular expression. + /// Regex = 3, } diff --git a/src/Umbraco.Core/HealthChecks/Checks/Security/BaseHttpHeaderCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Security/BaseHttpHeaderCheck.cs index 5de27027d541..c9467a408a39 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Security/BaseHttpHeaderCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Security/BaseHttpHeaderCheck.cs @@ -9,7 +9,7 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Security; /// -/// Provides a base class for health checks of http header values. +/// Provides a base class for health checks of HTTP header values. /// public abstract class BaseHttpHeaderCheck : HealthCheck { @@ -20,6 +20,15 @@ public abstract class BaseHttpHeaderCheck : HealthCheck private readonly bool _metaTagOptionAvailable; private readonly bool _shouldNotExist; + /// + /// Initializes a new instance of the class. + /// + /// The hosting environment. + /// The localized text service. + /// The name of the HTTP header to check for. + /// The prefix for localized text keys. + /// A value indicating whether the header can also be set via a meta tag. + /// A value indicating whether the header should not exist (when true, the check passes if the header is absent). protected BaseHttpHeaderCheck( IHostingEnvironment hostingEnvironment, ILocalizedTextService textService, @@ -36,6 +45,9 @@ protected BaseHttpHeaderCheck( _shouldNotExist = shouldNotExist; } + /// + /// Gets the localized text service. + /// [Obsolete("Save ILocalizedTextService in a field on the super class instead of using this")] protected ILocalizedTextService LocalizedTextService { get; } @@ -46,21 +58,18 @@ protected BaseHttpHeaderCheck( private static HttpClient HttpClient => _httpClient ??= new HttpClient(); - /// - /// Get the status for this health check - /// + /// public override async Task> GetStatusAsync() => [await CheckForHeader()]; - /// - /// Executes the action and returns it's status - /// + /// public override HealthCheckStatus ExecuteAction(HealthCheckAction action) => throw new InvalidOperationException("HTTP Header action requested is either not executable or does not exist"); /// - /// The actual health check method. + /// Performs the actual health check by checking for the specified HTTP header. /// + /// A task that represents the asynchronous operation containing the health check status. protected async Task CheckForHeader() { string message; diff --git a/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs index 9bcee6f5d3ac..37d46d00e3e8 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Security/ExcessiveHeadersCheck.cs @@ -32,15 +32,11 @@ public ExcessiveHeadersCheck(ILocalizedTextService textService, IHostingEnvironm private static HttpClient HttpClient => httpClient ??= new HttpClient(); - /// - /// Get the status for this health check - /// + /// public override async Task> GetStatusAsync() => [await CheckForHeaders()]; - /// - /// Executes the action and returns it's status - /// + /// public override HealthCheckStatus ExecuteAction(HealthCheckAction action) => throw new InvalidOperationException("ExcessiveHeadersCheck has no executable actions"); diff --git a/src/Umbraco.Core/HealthChecks/Checks/Security/HstsCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Security/HstsCheck.cs index 0f5427f7c9ca..d9d07b30872d 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Security/HstsCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Security/HstsCheck.cs @@ -47,9 +47,9 @@ public override async Task> GetStatusAsync() => new HealthCheckStatus[] { await CheckForHeader() }; /// - /// The health check task. + /// The health check task that verifies the HSTS header. /// - /// A with the result type reversed on localhost. + /// A with the result type reversed on localhost. protected new async Task CheckForHeader() { HealthCheckStatus checkHeaderResult = await base.CheckForHeader(); diff --git a/src/Umbraco.Core/HealthChecks/Checks/Security/HttpsCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Security/HttpsCheck.cs index c1deb71a49fb..c13ade6ea1db 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Security/HttpsCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Security/HttpsCheck.cs @@ -57,6 +57,9 @@ await CheckForValidCertificate() public override HealthCheckStatus ExecuteAction(HealthCheckAction action) => throw new InvalidOperationException("HttpsCheck action requested is either not executable or does not exist"); + /// + /// Custom certificate validation callback that stores the certificate expiry information. + /// private static bool ServerCertificateCustomValidation( HttpRequestMessage requestMessage, X509Certificate2? certificate, diff --git a/src/Umbraco.Core/HealthChecks/Checks/Security/UmbracoApplicationUrlCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Security/UmbracoApplicationUrlCheck.cs index e64a036cb0c6..be770c748eb7 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Security/UmbracoApplicationUrlCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Security/UmbracoApplicationUrlCheck.cs @@ -8,6 +8,9 @@ namespace Umbraco.Cms.Core.HealthChecks.Checks.Security; +/// +/// Health check for the Umbraco application URL configuration. +/// [HealthCheck( "6708CA45-E96E-40B8-A40A-0607C1CA7F28", "Application URL Configuration", @@ -18,6 +21,11 @@ public class UmbracoApplicationUrlCheck : HealthCheck private readonly ILocalizedTextService _textService; private readonly IOptionsMonitor _webRoutingSettings; + /// + /// Initializes a new instance of the class. + /// + /// The localized text service. + /// The web routing settings monitor. public UmbracoApplicationUrlCheck( ILocalizedTextService textService, IOptionsMonitor webRoutingSettings) @@ -26,15 +34,11 @@ public UmbracoApplicationUrlCheck( _webRoutingSettings = webRoutingSettings; } - /// - /// Executes the action and returns its status - /// + /// public override HealthCheckStatus ExecuteAction(HealthCheckAction action) => throw new InvalidOperationException("UmbracoApplicationUrlCheck has no executable actions"); - /// - /// Get the status for this health check - /// + /// public override Task> GetStatusAsync() => Task.FromResult(CheckUmbracoApplicationUrl().Yield()); diff --git a/src/Umbraco.Core/HealthChecks/Checks/Services/SmtpCheck.cs b/src/Umbraco.Core/HealthChecks/Checks/Services/SmtpCheck.cs index 856424563dc3..efd08c582770 100644 --- a/src/Umbraco.Core/HealthChecks/Checks/Services/SmtpCheck.cs +++ b/src/Umbraco.Core/HealthChecks/Checks/Services/SmtpCheck.cs @@ -31,15 +31,11 @@ public SmtpCheck(ILocalizedTextService textService, IOptionsMonitor - /// Get the status for this health check - /// + /// public override Task> GetStatusAsync() => Task.FromResult(CheckSmtpSettings().Yield()); - /// - /// Executes the action and returns it's status - /// + /// public override HealthCheckStatus ExecuteAction(HealthCheckAction action) => throw new InvalidOperationException("SmtpCheck has no executable actions"); diff --git a/src/Umbraco.Core/HealthChecks/ConfigurationServiceResult.cs b/src/Umbraco.Core/HealthChecks/ConfigurationServiceResult.cs index 564bcc59a557..e1bff9362ec3 100644 --- a/src/Umbraco.Core/HealthChecks/ConfigurationServiceResult.cs +++ b/src/Umbraco.Core/HealthChecks/ConfigurationServiceResult.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.HealthChecks; +/// +/// Represents the result of a configuration service operation. +/// public class ConfigurationServiceResult { + /// + /// Gets or sets a value indicating whether the configuration operation was successful. + /// public bool Success { get; set; } + /// + /// Gets or sets the result message or value from the configuration operation. + /// public string? Result { get; set; } } diff --git a/src/Umbraco.Core/HealthChecks/HealthCheck.cs b/src/Umbraco.Core/HealthChecks/HealthCheck.cs index 58136a862ef5..839d7418724a 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheck.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheck.cs @@ -5,11 +5,15 @@ namespace Umbraco.Cms.Core.HealthChecks; /// -/// Provides a base class for health checks, filling in the healthcheck metadata on construction +/// Provides a base class for health checks, filling in the healthcheck metadata on construction. /// [DataContract(Name = "healthCheck", Namespace = "")] public abstract class HealthCheck : IDiscoverable { + /// + /// Initializes a new instance of the class. + /// + /// Thrown when the health check does not have a . protected HealthCheck() { Type thisType = GetType(); @@ -26,22 +30,34 @@ protected HealthCheck() Id = meta.Id; } + /// + /// Gets the unique identifier of the health check. + /// [DataMember(Name = "id")] public Guid Id { get; private set; } + /// + /// Gets the name of the health check. + /// [DataMember(Name = "name")] public string Name { get; private set; } + /// + /// Gets the description of the health check. + /// [DataMember(Name = "description")] public string? Description { get; private set; } + /// + /// Gets the group this health check belongs to. + /// [DataMember(Name = "group")] public string? Group { get; private set; } /// - /// Get the status for this health check + /// Gets the status for this health check. /// - /// + /// A task that represents the asynchronous operation containing the collection of health check statuses. /// /// If there are possible actions to take to rectify this check, this method must be overridden by a sub class /// in order to explicitly provide those actions. @@ -50,18 +66,18 @@ public virtual Task> GetStatusAsync() => Task.FromResult(Enumerable.Empty()); /// - /// Executes the action and returns it's status + /// Executes the action and returns its status. /// - /// - /// + /// The action to execute. + /// The health check status after executing the action. public virtual HealthCheckStatus ExecuteAction(HealthCheckAction action) => new HealthCheckStatus("Not implemented"); /// - /// Executes the action and returns it's status + /// Executes the action asynchronously and returns its status. /// - /// - /// + /// The action to execute. + /// A task that represents the asynchronous operation containing the health check status. public virtual Task ExecuteActionAsync(HealthCheckAction action) => Task.FromResult(ExecuteAction(action)); } diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckAction.cs b/src/Umbraco.Core/HealthChecks/HealthCheckAction.cs index 7593a54cc2cd..13fe8f9b4783 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckAction.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckAction.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.HealthChecks; +/// +/// Represents an action that can be taken to rectify a health check issue. +/// [DataContract(Name = "healthCheckAction", Namespace = "")] public class HealthCheckAction { @@ -51,6 +54,9 @@ public HealthCheckAction(string alias, Guid healthCheckId) [DataMember(Name = "actionParameters")] public Dictionary? ActionParameters { get; set; } + /// + /// Gets or sets the name of the action - this is used to name the fix button. + /// public string? Name { get => _name; diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckAttribute.cs b/src/Umbraco.Core/HealthChecks/HealthCheckAttribute.cs index 718a689caff6..21cd65005b2b 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckAttribute.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckAttribute.cs @@ -1,23 +1,40 @@ namespace Umbraco.Cms.Core.HealthChecks; /// -/// Metadata attribute for Health checks +/// Metadata attribute for Health checks. /// [AttributeUsage(AttributeTargets.Class)] public sealed class HealthCheckAttribute : Attribute { + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier for the health check as a GUID string. + /// The display name of the health check. public HealthCheckAttribute(string id, string name) { Id = new Guid(id); Name = name; } + /// + /// Gets the display name of the health check. + /// public string Name { get; } + /// + /// Gets or sets the description of the health check. + /// public string? Description { get; set; } + /// + /// Gets or sets the group this health check belongs to. + /// public string? Group { get; set; } + /// + /// Gets the unique identifier of the health check. + /// public Guid Id { get; } // TODO: Do we need more metadata? diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckCollection.cs b/src/Umbraco.Core/HealthChecks/HealthCheckCollection.cs index c2c47c194863..fa95742a6de0 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckCollection.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckCollection.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.HealthChecks; +/// +/// Represents a collection of instances. +/// public class HealthCheckCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection items. public HealthCheckCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckCollectionBuilder.cs b/src/Umbraco.Core/HealthChecks/HealthCheckCollectionBuilder.cs index 1c026248c80b..68c068a92086 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckCollectionBuilder.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckCollectionBuilder.cs @@ -3,13 +3,18 @@ namespace Umbraco.Cms.Core.HealthChecks; +/// +/// Builds a collection of instances for dependency injection. +/// public class HealthCheckCollectionBuilder : LazyCollectionBuilderBase { + /// protected override HealthCheckCollectionBuilder This => this; // note: in v7 they were per-request, not sure why? // the collection is injected into the controller & there's only 1 controller per request anyways + /// protected override ServiceLifetime CollectionLifetime => ServiceLifetime.Transient; // transient! } diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckGroup.cs b/src/Umbraco.Core/HealthChecks/HealthCheckGroup.cs index ae67c192f5d0..18a7adf25da5 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckGroup.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckGroup.cs @@ -2,12 +2,21 @@ namespace Umbraco.Cms.Core.HealthChecks; +/// +/// Represents a group of related health checks. +/// [DataContract(Name = "healthCheckGroup", Namespace = "")] public class HealthCheckGroup { + /// + /// Gets or sets the name of the health check group. + /// [DataMember(Name = "name")] public string? Name { get; set; } + /// + /// Gets or sets the list of health checks in this group. + /// [DataMember(Name = "checks")] public List? Checks { get; set; } } diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckNotificationMethodAttribute.cs b/src/Umbraco.Core/HealthChecks/HealthCheckNotificationMethodAttribute.cs index 128e6dabbe37..dd40f1a8fc8f 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckNotificationMethodAttribute.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckNotificationMethodAttribute.cs @@ -1,12 +1,19 @@ namespace Umbraco.Cms.Core.HealthChecks; /// -/// Metadata attribute for health check notification methods +/// Metadata attribute for health check notification methods. /// [AttributeUsage(AttributeTargets.Class)] public sealed class HealthCheckNotificationMethodAttribute : Attribute { + /// + /// Initializes a new instance of the class. + /// + /// The alias for the notification method. public HealthCheckNotificationMethodAttribute(string alias) => Alias = alias; + /// + /// Gets the alias for the notification method. + /// public string Alias { get; } } diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckNotificationMethodCollection.cs b/src/Umbraco.Core/HealthChecks/HealthCheckNotificationMethodCollection.cs index 1d681690db66..af4076adac46 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckNotificationMethodCollection.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckNotificationMethodCollection.cs @@ -3,8 +3,15 @@ namespace Umbraco.Cms.Core.HealthChecks; +/// +/// Represents a collection of instances. +/// public class HealthCheckNotificationMethodCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection items. public HealthCheckNotificationMethodCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckNotificationMethodCollectionBuilder.cs b/src/Umbraco.Core/HealthChecks/HealthCheckNotificationMethodCollectionBuilder.cs index 375ddc7e2e6b..767c3dc986ac 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckNotificationMethodCollectionBuilder.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckNotificationMethodCollectionBuilder.cs @@ -3,9 +3,13 @@ namespace Umbraco.Cms.Core.HealthChecks; +/// +/// Builds a collection of instances for dependency injection. +/// public class HealthCheckNotificationMethodCollectionBuilder : LazyCollectionBuilderBase< HealthCheckNotificationMethodCollectionBuilder, HealthCheckNotificationMethodCollection, IHealthCheckNotificationMethod> { + /// protected override HealthCheckNotificationMethodCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckNotificationVerbosity.cs b/src/Umbraco.Core/HealthChecks/HealthCheckNotificationVerbosity.cs index 1e7ea9053217..f32601e9c6a4 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckNotificationVerbosity.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckNotificationVerbosity.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.HealthChecks; +/// +/// Specifies the verbosity level for health check notifications. +/// public enum HealthCheckNotificationVerbosity { + /// + /// Provides a brief summary of the health check results. + /// Summary, + + /// + /// Provides detailed information about the health check results. + /// Detailed, } diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckResults.cs b/src/Umbraco.Core/HealthChecks/HealthCheckResults.cs index 0903a61ae706..c734a8f4b9c1 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckResults.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckResults.cs @@ -4,21 +4,40 @@ namespace Umbraco.Cms.Core.HealthChecks; +/// +/// Represents the results of executing a collection of health checks. +/// public class HealthCheckResults { // TODO (V18): Convert to property to comply with SA1401 (fields should be private) + /// + /// Indicates whether all health checks completed successfully. + /// public readonly bool AllChecksSuccessful; + /// + /// Initializes a new instance of the class. + /// + /// The dictionary of health check results keyed by check name. + /// A value indicating whether all checks were successful. private HealthCheckResults(Dictionary> results, bool allChecksSuccessful) { ResultsAsDictionary = results; AllChecksSuccessful = allChecksSuccessful; } + /// + /// Gets the health check results as a dictionary keyed by check name. + /// internal Dictionary> ResultsAsDictionary { get; } private static ILogger Logger => StaticApplicationLogging.Logger; // TODO: inject + /// + /// Creates a new instance by executing the specified health checks. + /// + /// The health checks to execute. + /// A task that represents the asynchronous operation containing the health check results. public static async Task Create(IEnumerable checks) { Dictionary> results = await checks.ToDictionaryAsync( @@ -54,8 +73,16 @@ public static async Task Create(IEnumerable che return new HealthCheckResults(results, allChecksSuccessful); } + /// + /// Creates a new instance by executing a single health check. + /// + /// The health check to execute. + /// A task that represents the asynchronous operation containing the health check results. public static async Task Create(HealthCheck check) => await Create(new List() { check }); + /// + /// Logs the health check results to the application logger. + /// public void LogResults() { Logger.LogInformation("Scheduled health check results:"); @@ -84,6 +111,11 @@ public void LogResults() } } + /// + /// Converts the health check results to a markdown-formatted string. + /// + /// The verbosity level for the output. + /// A markdown-formatted string representation of the results. public string ResultsAsMarkDown(HealthCheckNotificationVerbosity verbosity) { var newItem = "- "; @@ -129,6 +161,11 @@ public string ResultsAsMarkDown(HealthCheckNotificationVerbosity verbosity) return sb.ToString(); } + /// + /// Gets the health check results filtered by the specified status result type. + /// + /// The status result type to filter by. + /// A dictionary of health check results matching the specified status, or null if the result type is not recognized. public Dictionary>? GetResultsForStatus(StatusResultType resultType) { switch (resultType) diff --git a/src/Umbraco.Core/HealthChecks/HealthCheckStatus.cs b/src/Umbraco.Core/HealthChecks/HealthCheckStatus.cs index 7f04e5154159..afe3137933a1 100644 --- a/src/Umbraco.Core/HealthChecks/HealthCheckStatus.cs +++ b/src/Umbraco.Core/HealthChecks/HealthCheckStatus.cs @@ -3,12 +3,16 @@ namespace Umbraco.Cms.Core.HealthChecks; /// -/// The status returned for a health check when it performs it check -/// TODO: This model will be used in the WebApi result so needs attributes for JSON usage +/// The status returned for a health check when it performs its check. +/// TODO: This model will be used in the WebApi result so needs attributes for JSON usage. /// [DataContract(Name = "healthCheckStatus", Namespace = "")] public class HealthCheckStatus { + /// + /// Initializes a new instance of the class. + /// + /// The status message. public HealthCheckStatus(string message) { Message = message; diff --git a/src/Umbraco.Core/HealthChecks/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Core/HealthChecks/NotificationMethods/EmailNotificationMethod.cs index 6f373cb006c0..c5cc43ae6115 100644 --- a/src/Umbraco.Core/HealthChecks/NotificationMethods/EmailNotificationMethod.cs +++ b/src/Umbraco.Core/HealthChecks/NotificationMethods/EmailNotificationMethod.cs @@ -8,6 +8,9 @@ namespace Umbraco.Cms.Core.HealthChecks.NotificationMethods; +/// +/// A health check notification method that sends results via email. +/// [HealthCheckNotificationMethod("email")] public class EmailNotificationMethod : NotificationMethodBase { @@ -17,6 +20,15 @@ public class EmailNotificationMethod : NotificationMethodBase private readonly ILocalizedTextService? _textService; private ContentSettings? _contentSettings; + /// + /// Initializes a new instance of the class. + /// + /// The localized text service. + /// The hosting environment. + /// The email sender service. + /// The health checks settings monitor. + /// The content settings monitor. + /// The markdown to HTML converter. public EmailNotificationMethod( ILocalizedTextService textService, IHostingEnvironment hostingEnvironment, @@ -44,8 +56,12 @@ public EmailNotificationMethod( contentSettings.OnChange(x => _contentSettings = x); } + /// + /// Gets the recipient email address for health check notifications. + /// public string? RecipientEmail { get; } + /// public override async Task SendAsync(HealthCheckResults results) { if (ShouldSend(results) == false) diff --git a/src/Umbraco.Core/HealthChecks/NotificationMethods/IHealthCheckNotificationMethod.cs b/src/Umbraco.Core/HealthChecks/NotificationMethods/IHealthCheckNotificationMethod.cs index aa343ef608d0..485118bbd522 100644 --- a/src/Umbraco.Core/HealthChecks/NotificationMethods/IHealthCheckNotificationMethod.cs +++ b/src/Umbraco.Core/HealthChecks/NotificationMethods/IHealthCheckNotificationMethod.cs @@ -2,9 +2,20 @@ namespace Umbraco.Cms.Core.HealthChecks.NotificationMethods; +/// +/// Defines a method for sending health check notifications. +/// public interface IHealthCheckNotificationMethod : IDiscoverable { + /// + /// Gets a value indicating whether this notification method is enabled. + /// bool Enabled { get; } + /// + /// Sends the health check results via this notification method. + /// + /// The health check results to send. + /// A task representing the asynchronous operation. Task SendAsync(HealthCheckResults results); } diff --git a/src/Umbraco.Core/HealthChecks/NotificationMethods/IMarkdownToHtmlConverter.cs b/src/Umbraco.Core/HealthChecks/NotificationMethods/IMarkdownToHtmlConverter.cs index 87b6a6dbff67..1e80e635a2dd 100644 --- a/src/Umbraco.Core/HealthChecks/NotificationMethods/IMarkdownToHtmlConverter.cs +++ b/src/Umbraco.Core/HealthChecks/NotificationMethods/IMarkdownToHtmlConverter.cs @@ -1,6 +1,15 @@ namespace Umbraco.Cms.Core.HealthChecks.NotificationMethods; +/// +/// Defines a converter for transforming health check results from markdown to HTML. +/// public interface IMarkdownToHtmlConverter { + /// + /// Converts health check results to HTML format. + /// + /// The health check results to convert. + /// The verbosity level for the output. + /// An HTML-formatted string representation of the health check results. string ToHtml(HealthCheckResults results, HealthCheckNotificationVerbosity verbosity); } diff --git a/src/Umbraco.Core/HealthChecks/NotificationMethods/NotificationMethodBase.cs b/src/Umbraco.Core/HealthChecks/NotificationMethods/NotificationMethodBase.cs index acb9af7cac08..e1ccb3241fa1 100644 --- a/src/Umbraco.Core/HealthChecks/NotificationMethods/NotificationMethodBase.cs +++ b/src/Umbraco.Core/HealthChecks/NotificationMethods/NotificationMethodBase.cs @@ -4,8 +4,15 @@ namespace Umbraco.Cms.Core.HealthChecks.NotificationMethods; +/// +/// Provides a base class for health check notification methods. +/// public abstract class NotificationMethodBase : IHealthCheckNotificationMethod { + /// + /// Initializes a new instance of the class. + /// + /// The health check settings monitor. protected NotificationMethodBase(IOptionsMonitor healthCheckSettings) { Type type = GetType(); @@ -31,15 +38,31 @@ protected NotificationMethodBase(IOptionsMonitor healthChe Settings = notificationMethod.Settings; } + /// + /// Gets or sets a value indicating whether notifications should only be sent on failure. + /// public bool FailureOnly { get; protected set; } + /// + /// Gets or sets the verbosity level for the notification. + /// public HealthCheckNotificationVerbosity Verbosity { get; protected set; } + /// + /// Gets the settings dictionary for this notification method. + /// public IDictionary? Settings { get; } + /// public bool Enabled { get; protected set; } + /// public abstract Task SendAsync(HealthCheckResults results); + /// + /// Determines whether a notification should be sent based on the results and configuration. + /// + /// The health check results. + /// true if a notification should be sent; otherwise, false. protected bool ShouldSend(HealthCheckResults results) => Enabled && (!FailureOnly || !results.AllChecksSuccessful); } diff --git a/src/Umbraco.Core/HealthChecks/StatusResultType.cs b/src/Umbraco.Core/HealthChecks/StatusResultType.cs index 0516fc35448a..75ebcb186b5b 100644 --- a/src/Umbraco.Core/HealthChecks/StatusResultType.cs +++ b/src/Umbraco.Core/HealthChecks/StatusResultType.cs @@ -1,9 +1,27 @@ namespace Umbraco.Cms.Core.HealthChecks; +/// +/// Specifies the result type of a health check status. +/// public enum StatusResultType { + /// + /// The health check completed successfully without any issues. + /// Success, + + /// + /// The health check completed with a warning condition. + /// Warning, + + /// + /// The health check completed with an error condition. + /// Error, + + /// + /// The health check completed with informational status. + /// Info, } diff --git a/src/Umbraco.Core/HealthChecks/ValueComparisonType.cs b/src/Umbraco.Core/HealthChecks/ValueComparisonType.cs index 9269f905f4d7..0da6d40d2443 100644 --- a/src/Umbraco.Core/HealthChecks/ValueComparisonType.cs +++ b/src/Umbraco.Core/HealthChecks/ValueComparisonType.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.HealthChecks; +/// +/// Specifies the type of value comparison to perform in a health check. +/// public enum ValueComparisonType { + /// + /// The actual value should equal the expected value. + /// ShouldEqual, + + /// + /// The actual value should not equal the expected value. + /// ShouldNotEqual, } diff --git a/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs b/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs index 84b275714b03..c5bcccbd59d2 100644 --- a/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs +++ b/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs @@ -1,8 +1,23 @@ namespace Umbraco.Cms.Core.Hosting; +/// +/// Provides a registry for objects that need to be notified during application shutdown. +/// +/// +/// Registered objects receive callbacks when the application is stopping, allowing them +/// to perform cleanup operations before the application terminates. +/// public interface IApplicationShutdownRegistry { + /// + /// Registers an object to receive shutdown notifications. + /// + /// The object to register for shutdown notifications. void RegisterObject(IRegisteredObject registeredObject); + /// + /// Unregisters an object from receiving shutdown notifications. + /// + /// The object to unregister. void UnregisterObject(IRegisteredObject registeredObject); } diff --git a/src/Umbraco.Core/Hosting/IHostingEnvironment.cs b/src/Umbraco.Core/Hosting/IHostingEnvironment.cs index 15a7ef74e31a..f2b187b0443d 100644 --- a/src/Umbraco.Core/Hosting/IHostingEnvironment.cs +++ b/src/Umbraco.Core/Hosting/IHostingEnvironment.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Hosting; +/// +/// Provides information about the hosting environment in which the application is running. +/// +/// +/// This interface abstracts the hosting environment details, enabling access to paths, +/// URLs, and environment-specific settings without direct dependency on the web host. +/// public interface IHostingEnvironment { + /// + /// Gets the name of the site. + /// string? SiteName { get; } /// @@ -40,6 +50,9 @@ public interface IHostingEnvironment /// string ApplicationPhysicalPath { get; } + /// + /// Gets the local temporary path for the application. + /// string LocalTempPath { get; } /// @@ -57,6 +70,9 @@ public interface IHostingEnvironment /// string ApplicationVirtualPath { get; } + /// + /// Gets a value indicating whether the application is running in debug mode. + /// bool IsDebugMode { get; } /// diff --git a/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs index 493c3ab4dc1d..e475b724b807 100644 --- a/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Core/Hosting/IUmbracoApplicationLifetime.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Hosting; +/// +/// Provides methods to manage the Umbraco application lifetime, including restart functionality. +/// public interface IUmbracoApplicationLifetime { /// diff --git a/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs b/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs index 824ce3249a50..04734f23fb92 100644 --- a/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs +++ b/src/Umbraco.Core/Hosting/NoopApplicationShutdownRegistry.cs @@ -1,11 +1,20 @@ namespace Umbraco.Cms.Core.Hosting; +/// +/// A no-operation implementation of that performs no actions. +/// +/// +/// This implementation is used when shutdown registration is not required or supported, +/// such as in certain testing scenarios. +/// internal sealed class NoopApplicationShutdownRegistry : IApplicationShutdownRegistry { + /// public void RegisterObject(IRegisteredObject registeredObject) { } + /// public void UnregisterObject(IRegisteredObject registeredObject) { } diff --git a/src/Umbraco.Core/HybridAccessorBase.cs b/src/Umbraco.Core/HybridAccessorBase.cs index fdee8e4ec5dc..53824bdeb515 100644 --- a/src/Umbraco.Core/HybridAccessorBase.cs +++ b/src/Umbraco.Core/HybridAccessorBase.cs @@ -21,11 +21,22 @@ public abstract class HybridAccessorBase private readonly IRequestCache _requestCache; private string? _itemKey; + /// + /// Initializes a new instance of the class. + /// + /// The request cache for storing the value in the HTTP context. + /// The request cache is null. protected HybridAccessorBase(IRequestCache requestCache) => _requestCache = requestCache ?? throw new ArgumentNullException(nameof(requestCache)); + /// + /// Gets the unique key used to store the value in the request cache. + /// protected string ItemKey => _itemKey ??= GetType().FullName!; + /// + /// Gets or sets the current value, storing it either in the HTTP context or the ambient context. + /// protected T? Value { get diff --git a/src/Umbraco.Core/HybridEventMessagesAccessor.cs b/src/Umbraco.Core/HybridEventMessagesAccessor.cs index d129b9a117e1..f3edf24ebfc8 100644 --- a/src/Umbraco.Core/HybridEventMessagesAccessor.cs +++ b/src/Umbraco.Core/HybridEventMessagesAccessor.cs @@ -3,13 +3,21 @@ namespace Umbraco.Cms.Core; +/// +/// A hybrid accessor for that stores messages in either HTTP context or ambient context. +/// public class HybridEventMessagesAccessor : HybridAccessorBase, IEventMessagesAccessor { + /// + /// Initializes a new instance of the class. + /// + /// The request cache for storing the value in the HTTP context. public HybridEventMessagesAccessor(IRequestCache requestCache) : base(requestCache) { } + /// public EventMessages? EventMessages { get => Value; diff --git a/src/Umbraco.Core/IBackOfficeInfo.cs b/src/Umbraco.Core/IBackOfficeInfo.cs index bc27eb7f1649..198ce6e87d3a 100644 --- a/src/Umbraco.Core/IBackOfficeInfo.cs +++ b/src/Umbraco.Core/IBackOfficeInfo.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core; +/// +/// Provides information about the Umbraco backoffice. +/// public interface IBackOfficeInfo { /// diff --git a/src/Umbraco.Core/ICompletable.cs b/src/Umbraco.Core/ICompletable.cs index b13000de22b1..fcbee5e09bf0 100644 --- a/src/Umbraco.Core/ICompletable.cs +++ b/src/Umbraco.Core/ICompletable.cs @@ -1,6 +1,16 @@ namespace Umbraco.Cms.Core; +/// +/// Defines an object that represents a completable operation, typically used for unit of work patterns. +/// +/// +/// The operation should be marked as complete by calling before disposing. +/// If the object is disposed without calling , the operation should be rolled back. +/// public interface ICompletable : IDisposable { + /// + /// Marks the operation as complete, indicating that any changes should be committed. + /// void Complete(); } diff --git a/src/Umbraco.Core/IFireAndForgetRunner.cs b/src/Umbraco.Core/IFireAndForgetRunner.cs index b28a77799070..ec7012ccaed4 100644 --- a/src/Umbraco.Core/IFireAndForgetRunner.cs +++ b/src/Umbraco.Core/IFireAndForgetRunner.cs @@ -1,6 +1,16 @@ -namespace Umbraco.Cms.Core; +namespace Umbraco.Cms.Core; +/// +/// Provides a mechanism to run tasks in a fire-and-forget manner without blocking the calling thread. +/// public interface IFireAndForgetRunner { + /// + /// Runs the specified task in the background without waiting for it to complete. + /// + /// A function that returns the task to execute. + /// + /// The task will be executed on a background thread. Exceptions will be logged but not propagated to the caller. + /// void RunFireAndForget(Func task); } diff --git a/src/Umbraco.Core/IO/CleanFolderResult.cs b/src/Umbraco.Core/IO/CleanFolderResult.cs index 76d1767eabd2..04d6707f0835 100644 --- a/src/Umbraco.Core/IO/CleanFolderResult.cs +++ b/src/Umbraco.Core/IO/CleanFolderResult.cs @@ -1,33 +1,72 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Represents the result of a folder cleaning operation. +/// public class CleanFolderResult { + /// + /// Initializes a new instance of the class. + /// private CleanFolderResult() { } + /// + /// Gets the status of the clean folder operation. + /// public CleanFolderResultStatus Status { get; private set; } + /// + /// Gets the collection of errors that occurred during the clean folder operation. + /// public IReadOnlyCollection? Errors { get; private set; } + /// + /// Creates a successful clean folder result. + /// + /// A indicating success. public static CleanFolderResult Success() => new CleanFolderResult { Status = CleanFolderResultStatus.Success }; + /// + /// Creates a failed clean folder result indicating the folder does not exist. + /// + /// A indicating the folder does not exist. public static CleanFolderResult FailedAsDoesNotExist() => new CleanFolderResult { Status = CleanFolderResultStatus.FailedAsDoesNotExist }; + /// + /// Creates a failed clean folder result with the specified errors. + /// + /// The list of errors that occurred during the operation. + /// A containing the errors. public static CleanFolderResult FailedWithErrors(List errors) => new CleanFolderResult { Status = CleanFolderResultStatus.FailedWithException, Errors = errors.AsReadOnly() }; + /// + /// Represents an error that occurred while cleaning a folder. + /// public class Error { + /// + /// Initializes a new instance of the class. + /// + /// The exception that occurred. + /// The file that caused the error. public Error(Exception exception, FileInfo erroringFile) { Exception = exception; ErroringFile = erroringFile; } + /// + /// Gets or sets the exception that occurred. + /// public Exception Exception { get; set; } + /// + /// Gets or sets the file that caused the error. + /// public FileInfo ErroringFile { get; set; } } } diff --git a/src/Umbraco.Core/IO/CleanFolderResultStatus.cs b/src/Umbraco.Core/IO/CleanFolderResultStatus.cs index 73d32982aa78..dc3eca3a2b33 100644 --- a/src/Umbraco.Core/IO/CleanFolderResultStatus.cs +++ b/src/Umbraco.Core/IO/CleanFolderResultStatus.cs @@ -1,8 +1,22 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Represents the status of a folder cleaning operation. +/// public enum CleanFolderResultStatus { + /// + /// The folder was cleaned successfully. + /// Success, + + /// + /// The operation failed because the folder does not exist. + /// FailedAsDoesNotExist, + + /// + /// The operation failed with one or more exceptions. + /// FailedWithException, } diff --git a/src/Umbraco.Core/IO/DefaultViewContentProvider.cs b/src/Umbraco.Core/IO/DefaultViewContentProvider.cs index 5e0c10d80d9c..7c6009f9d15e 100644 --- a/src/Umbraco.Core/IO/DefaultViewContentProvider.cs +++ b/src/Umbraco.Core/IO/DefaultViewContentProvider.cs @@ -3,8 +3,12 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Provides default content for Razor view files. +/// public class DefaultViewContentProvider : IDefaultViewContentProvider { + /// public string GetDefaultFileContent(string? layoutPageAlias = null, string? modelClassName = null, string? modelNamespace = null, string? modelNamespaceAlias = null) { var content = new StringBuilder(); diff --git a/src/Umbraco.Core/IO/FileSystemExtensions.cs b/src/Umbraco.Core/IO/FileSystemExtensions.cs index 44bc1ac2ad5b..f23547db2373 100644 --- a/src/Umbraco.Core/IO/FileSystemExtensions.cs +++ b/src/Umbraco.Core/IO/FileSystemExtensions.cs @@ -6,8 +6,16 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for file system operations. +/// public static class FileSystemExtensions { + /// + /// Computes the SHA1 hash of a stream. + /// + /// The stream to hash. + /// The hexadecimal string representation of the hash. public static string GetStreamHash(this Stream fileStream) { if (fileStream.CanSeek) @@ -58,6 +66,12 @@ public static FileStream OpenReadWithRetry(this FileInfo file, int maxRetries = throw new ArgumentException("Retries must be greater than zero"); } + /// + /// Copies a file from one path to another within the file system. + /// + /// The file system. + /// The source file path. + /// The destination file path. public static void CopyFile(this IFileSystem fs, string path, string newPath) { using (Stream stream = fs.OpenFile(path)) @@ -66,11 +80,28 @@ public static void CopyFile(this IFileSystem fs, string path, string newPath) } } + /// + /// Gets the file extension from a path. + /// + /// The file system. + /// The file path. + /// The file extension including the period. public static string GetExtension(this IFileSystem fs, string path) => Path.GetExtension(fs.GetFullPath(path)); + /// + /// Gets the file name from a path. + /// + /// The file system. + /// The file path. + /// The file name including extension. public static string GetFileName(this IFileSystem fs, string path) => Path.GetFileName(fs.GetFullPath(path)); // TODO: Currently this is the only way to do this + /// + /// Creates a folder at the specified path. + /// + /// The file system. + /// The folder path to create. public static void CreateFolder(this IFileSystem fs, string folderPath) { var path = fs.GetRelativePath(folderPath); diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index 5e27250cb421..e707395c5594 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -35,7 +35,13 @@ public sealed class FileSystems private static string? _shadowCurrentId; // static - unique!! #region Constructor - // DI wants a public ctor + /// + /// Initializes a new instance of the class. + /// + /// The logger factory. + /// The IO helper. + /// The global settings. + /// The hosting environment. public FileSystems( ILoggerFactory loggerFactory, IIOHelper ioHelper, @@ -49,7 +55,18 @@ public FileSystems( _hostingEnvironment = hostingEnvironment; } - // Ctor for tests, allows you to set the various filesystems + /// + /// Initializes a new instance of the class for testing. + /// + /// The logger factory. + /// The IO helper. + /// The global settings. + /// The hosting environment. + /// The partial views file system. + /// The stylesheet file system. + /// The scripts file system. + /// The MVC view file system. + /// This constructor allows setting the various filesystems for testing purposes. internal FileSystems( ILoggerFactory loggerFactory, IIOHelper ioHelper, @@ -186,10 +203,16 @@ public void SetStylesheetFilesystem(IFileSystem fileSystem) _stylesheetsFileSystem = CreateShadowWrapperInternal(fileSystem, "css"); } + /// + /// Ensures that the well-known file systems are initialized. + /// private void EnsureWellKnownFileSystems() => LazyInitializer.EnsureInitialized(ref _wkfsObject, ref _wkfsInitialized, ref _wkfsLock, CreateWellKnownFileSystems); - // need to return something to LazyInitializer.EnsureInitialized - // but it does not really matter what we return - here, null + /// + /// Creates the well-known file systems. + /// + /// Always returns null; the return value is required by LazyInitializer. + /// Need to return something to LazyInitializer.EnsureInitialized but it does not really matter what we return. private object? CreateWellKnownFileSystems() { ILogger logger = _loggerFactory.CreateLogger(); @@ -237,7 +260,7 @@ public void SetStylesheetFilesystem(IFileSystem fileSystem) /// /// Shadows the filesystem, should never be used outside the Scope class. /// - /// + /// An representing the shadow scope. [EditorBrowsable(EditorBrowsableState.Never)] public ICompletable Shadow() { @@ -250,6 +273,11 @@ public ICompletable Shadow() return new ShadowFileSystems(this, id); // will invoke BeginShadow and EndShadow } + /// + /// Begins shadowing with the specified identifier. + /// + /// The shadow identifier. + /// Thrown when already shadowing. internal void BeginShadow(string id) { lock (_shadowLocker) @@ -273,6 +301,13 @@ internal void BeginShadow(string id) } } + /// + /// Ends shadowing with the specified identifier. + /// + /// The shadow identifier. + /// Whether the shadow operation completed successfully. + /// Thrown when not currently shadowing or when the identifier doesn't match. + /// Thrown when some changes could not be applied or aborted. internal void EndShadow(string id, bool completed) { lock (_shadowLocker) @@ -316,14 +351,20 @@ internal void EndShadow(string id, bool completed) } /// - /// Creates a shadow wrapper for a filesystem, should never be used outside UmbracoBuilder or testing + /// Creates a shadow wrapper for a filesystem, should never be used outside UmbracoBuilder or testing. /// - /// - /// - /// + /// The file system to wrap. + /// The shadow path. + /// A shadow-wrapped file system. [EditorBrowsable(EditorBrowsableState.Never)] public IFileSystem CreateShadowWrapper(IFileSystem filesystem, string shadowPath) => CreateShadowWrapperInternal(filesystem, shadowPath); + /// + /// Creates a shadow wrapper for a filesystem. + /// + /// The file system to wrap. + /// The shadow path. + /// A shadow-wrapped file system. private ShadowWrapper CreateShadowWrapperInternal(IFileSystem filesystem, string shadowPath) { lock (_shadowLocker) diff --git a/src/Umbraco.Core/IO/IDefaultViewContentProvider.cs b/src/Umbraco.Core/IO/IDefaultViewContentProvider.cs index 3ca1fadbff10..0cb5701db1c0 100644 --- a/src/Umbraco.Core/IO/IDefaultViewContentProvider.cs +++ b/src/Umbraco.Core/IO/IDefaultViewContentProvider.cs @@ -1,6 +1,17 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Provides default content for Razor view files. +/// public interface IDefaultViewContentProvider { + /// + /// Gets the default file content for a Razor view. + /// + /// The optional alias of the layout page to inherit from. + /// The optional class name of the model. + /// The optional namespace of the model. + /// The optional alias for the model namespace (defaults to "ContentModels"). + /// The default Razor view content as a string. string GetDefaultFileContent(string? layoutPageAlias = null, string? modelClassName = null, string? modelNamespace = null, string? modelNamespaceAlias = null); } diff --git a/src/Umbraco.Core/IO/IIOHelper.cs b/src/Umbraco.Core/IO/IIOHelper.cs index 53376dd48b2f..bcf91a246182 100644 --- a/src/Umbraco.Core/IO/IIOHelper.cs +++ b/src/Umbraco.Core/IO/IIOHelper.cs @@ -1,9 +1,22 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Provides helper methods for IO operations. +/// public interface IIOHelper { + /// + /// Finds a file by its virtual path and returns the resolved path. + /// + /// The virtual path to find. + /// The resolved file path. string FindFile(string virtualPath); + /// + /// Resolves a virtual path to an absolute URL. + /// + /// The virtual path to resolve. + /// The absolute URL. [Obsolete("Use IHostingEnvironment.ToAbsolute instead")] string ResolveUrl(string virtualPath); @@ -39,8 +52,19 @@ public interface IIOHelper /// A value indicating whether the filepath is valid. bool VerifyFileExtension(string filePath, IEnumerable validFileExtensions); + /// + /// Determines whether a path starts with the specified root path. + /// + /// The path to check. + /// The root path to compare against. + /// The directory separator characters to use. + /// true if the path starts with the root; otherwise, false. bool PathStartsWith(string path, string root, params char[] separators); + /// + /// Ensures that the specified path exists by creating it if necessary. + /// + /// The path to ensure exists. void EnsurePathExists(string path); /// diff --git a/src/Umbraco.Core/IO/IOHelper.cs b/src/Umbraco.Core/IO/IOHelper.cs index 3d82d527b310..cb95ca703375 100644 --- a/src/Umbraco.Core/IO/IOHelper.cs +++ b/src/Umbraco.Core/IO/IOHelper.cs @@ -6,17 +6,25 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Provides base implementation for IO helper operations. +/// public abstract class IOHelper : IIOHelper { private readonly IHostingEnvironment _hostingEnvironment; + /// + /// Initializes a new instance of the class. + /// + /// The hosting environment. + /// Thrown when is null. public IOHelper(IHostingEnvironment hostingEnvironment) => _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); // static compiled regex for faster performance // private static readonly Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - // helper to try and match the old path to a new virtual one + /// public string FindFile(string virtualPath) { var retval = virtualPath; @@ -36,6 +44,7 @@ public string FindFile(string virtualPath) } // TODO: This is the same as IHostingEnvironment.ToAbsolute - marked as obsolete in IIOHelper for now + /// public string ResolveUrl(string virtualPath) { if (string.IsNullOrWhiteSpace(virtualPath)) @@ -46,6 +55,7 @@ public string ResolveUrl(string virtualPath) return _hostingEnvironment.ToAbsolute(virtualPath); } + /// public string MapPath(string path) { if (path == null) @@ -142,8 +152,10 @@ public bool VerifyFileExtension(string filePath, IEnumerable validFileEx return ext != null && validFileExtensions.Contains(ext.TrimStart(Constants.CharArrays.Period)); } + /// public abstract bool PathStartsWith(string path, string root, params char[] separators); + /// public void EnsurePathExists(string path) { var absolutePath = MapPath(path); diff --git a/src/Umbraco.Core/IO/IOHelperExtensions.cs b/src/Umbraco.Core/IO/IOHelperExtensions.cs index 52e1bbe0cd65..ccb478302aff 100644 --- a/src/Umbraco.Core/IO/IOHelperExtensions.cs +++ b/src/Umbraco.Core/IO/IOHelperExtensions.cs @@ -3,6 +3,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for for common IO operations. +/// public static class IOHelperExtensions { /// @@ -51,6 +54,11 @@ public static bool TryCreateDirectory(this IIOHelper ioHelper, string dir) } } + /// + /// Creates a random temporary file name for testing purposes. + /// + /// The IO helper. + /// A random file name in the format "umbraco-test.{8-char-guid}". public static string CreateRandomFileName(this IIOHelper ioHelper) => "umbraco-test." + Guid.NewGuid().ToString("N").Substring(0, 8); } diff --git a/src/Umbraco.Core/IO/IOHelperLinux.cs b/src/Umbraco.Core/IO/IOHelperLinux.cs index 239d43a6057e..13bfdceaf15e 100644 --- a/src/Umbraco.Core/IO/IOHelperLinux.cs +++ b/src/Umbraco.Core/IO/IOHelperLinux.cs @@ -2,13 +2,21 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Provides IO helper implementations for Linux operating systems. +/// public class IOHelperLinux : IOHelper { + /// + /// Initializes a new instance of the class. + /// + /// The hosting environment. public IOHelperLinux(IHostingEnvironment hostingEnvironment) : base(hostingEnvironment) { } + /// public override bool PathStartsWith(string path, string root, params char[] separators) { // either it is identical to root, diff --git a/src/Umbraco.Core/IO/IOHelperOSX.cs b/src/Umbraco.Core/IO/IOHelperOSX.cs index d939e0f14623..6e73679aa9bc 100644 --- a/src/Umbraco.Core/IO/IOHelperOSX.cs +++ b/src/Umbraco.Core/IO/IOHelperOSX.cs @@ -2,13 +2,21 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Provides IO helper implementations for macOS (OSX) operating systems. +/// public class IOHelperOSX : IOHelper { + /// + /// Initializes a new instance of the class. + /// + /// The hosting environment. public IOHelperOSX(IHostingEnvironment hostingEnvironment) : base(hostingEnvironment) { } + /// public override bool PathStartsWith(string path, string root, params char[] separators) { // either it is identical to root, diff --git a/src/Umbraco.Core/IO/IOHelperWindows.cs b/src/Umbraco.Core/IO/IOHelperWindows.cs index 4325b5610841..2141303f6d0d 100644 --- a/src/Umbraco.Core/IO/IOHelperWindows.cs +++ b/src/Umbraco.Core/IO/IOHelperWindows.cs @@ -2,13 +2,21 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Provides IO helper implementations for Windows operating systems. +/// public class IOHelperWindows : IOHelper { + /// + /// Initializes a new instance of the class. + /// + /// The hosting environment. public IOHelperWindows(IHostingEnvironment hostingEnvironment) : base(hostingEnvironment) { } + /// public override bool PathStartsWith(string path, string root, params char[] separators) { // either it is identical to root, diff --git a/src/Umbraco.Core/IO/IViewHelper.cs b/src/Umbraco.Core/IO/IViewHelper.cs index f84a1ba25655..e85c03e1716c 100644 --- a/src/Umbraco.Core/IO/IViewHelper.cs +++ b/src/Umbraco.Core/IO/IViewHelper.cs @@ -2,15 +2,45 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Provides helper methods for working with template view files. +/// public interface IViewHelper { + /// + /// Determines whether a view file exists for the specified template. + /// + /// The template to check. + /// true if the view file exists; otherwise, false. bool ViewExists(ITemplate t); + /// + /// Gets the file contents of the specified template's view file. + /// + /// The template to get contents for. + /// The contents of the view file, or an empty string if the file does not exist. string GetFileContents(ITemplate t); + /// + /// Creates a view file for the specified template. + /// + /// The template to create a view for. + /// Whether to overwrite an existing view file. + /// The contents of the view file. string CreateView(ITemplate t, bool overWrite = false); + /// + /// Updates the view file for the specified template. + /// + /// The template to update the view for. + /// The current alias of the template, used to rename the file if the alias has changed. + /// The content of the updated view file. string? UpdateViewFile(ITemplate t, string? currentAlias = null); + /// + /// Gets the relative path to a view file based on the template alias. + /// + /// The template alias. + /// The relative path to the view file. string ViewPath(string alias); } diff --git a/src/Umbraco.Core/IO/MediaFileManager.cs b/src/Umbraco.Core/IO/MediaFileManager.cs index 0633251a5ddd..490a438af5ab 100644 --- a/src/Umbraco.Core/IO/MediaFileManager.cs +++ b/src/Umbraco.Core/IO/MediaFileManager.cs @@ -9,6 +9,9 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Manages media files and their storage in the file system. +/// public sealed class MediaFileManager { private readonly ILogger _logger; @@ -18,6 +21,14 @@ public sealed class MediaFileManager private readonly IShortStringHelper _shortStringHelper; private MediaUrlGeneratorCollection? _mediaUrlGenerators; + /// + /// Initializes a new instance of the class. + /// + /// The file system for media storage. + /// The media path scheme. + /// The logger. + /// The short string helper. + /// The service provider. [Obsolete("Please use the constructor taking all arguments, scheduled for removal in Umbraco 19")] public MediaFileManager( IFileSystem fileSystem, @@ -35,6 +46,15 @@ public MediaFileManager( { } + /// + /// Initializes a new instance of the class. + /// + /// The file system for media storage. + /// The media path scheme. + /// The logger. + /// The short string helper. + /// The service provider. + /// The core scope provider. public MediaFileManager( IFileSystem fileSystem, IMediaPathScheme mediaPathScheme, @@ -111,6 +131,12 @@ public void RemoveSuffixFromMediaFiles(IEnumerable files, string suffix) }, "Failed to rename media file '{File}'."); + /// + /// Performs a file operation on multiple media files in parallel. + /// + /// The files to operate on. + /// The operation to perform on each file. + /// The error message template to log on failure. private void PerformMediaFileOperation(IEnumerable files, Action fileOperation, string errorMessage) { using ICoreScope scope = _coreScopeProvider.Value.CreateCoreScope(); diff --git a/src/Umbraco.Core/IO/ShadowFileSystem.cs b/src/Umbraco.Core/IO/ShadowFileSystem.cs index db39fe74f4f4..3a36391cdc01 100644 --- a/src/Umbraco.Core/IO/ShadowFileSystem.cs +++ b/src/Umbraco.Core/IO/ShadowFileSystem.cs @@ -2,24 +2,43 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Represents a file system that shadows another file system, tracking changes without modifying the original. +/// +/// +/// This file system captures all file operations in memory and can later apply them to the inner file system. +/// internal sealed partial class ShadowFileSystem : IFileSystem { private readonly IFileSystem _sfs; private Dictionary? _nodes; + /// + /// Initializes a new instance of the class. + /// + /// The inner file system being shadowed. + /// The shadow file system for storing temporary files. public ShadowFileSystem(IFileSystem fs, IFileSystem sfs) { Inner = fs; _sfs = sfs; } + /// + /// Gets the inner file system being shadowed. + /// public IFileSystem Inner { get; } + /// public bool CanAddPhysical => true; + /// + /// Gets the dictionary of shadow nodes tracking file and directory changes. + /// private Dictionary Nodes => _nodes ??= new Dictionary(); + /// public IEnumerable GetDirectories(string path) { var normPath = NormPath(path); @@ -33,8 +52,10 @@ public IEnumerable GetDirectories(string path) .Distinct(); } + /// public void DeleteDirectory(string path) => DeleteDirectory(path, false); + /// public void DeleteDirectory(string path, bool recursive) { if (DirectoryExists(path) == false) @@ -74,6 +95,7 @@ public void DeleteDirectory(string path, bool recursive) } } + /// public bool DirectoryExists(string path) { if (Nodes.TryGetValue(NormPath(path), out ShadowNode? sf)) @@ -84,8 +106,10 @@ public bool DirectoryExists(string path) return Inner.DirectoryExists(path); } + /// public void AddFile(string path, Stream stream) => AddFile(path, stream, true); + /// public void AddFile(string path, Stream stream, bool overrideIfExists) { var normPath = NormPath(path); @@ -130,8 +154,10 @@ public void AddFile(string path, Stream stream, bool overrideIfExists) Nodes[normPath] = new ShadowNode(false, false); } + /// public IEnumerable GetFiles(string path) => GetFiles(path, null); + /// public IEnumerable GetFiles(string path, string? filter) { var normPath = NormPath(path); @@ -147,6 +173,7 @@ public IEnumerable GetFiles(string path, string? filter) .Distinct(); } + /// public Stream OpenFile(string path) { if (Nodes.TryGetValue(NormPath(path), out ShadowNode? sf)) @@ -157,6 +184,7 @@ public Stream OpenFile(string path) return Inner.OpenFile(path); } + /// public void DeleteFile(string path) { if (FileExists(path) == false) @@ -167,6 +195,7 @@ public void DeleteFile(string path) Nodes[NormPath(path)] = new ShadowNode(true, false); } + /// public void MoveFile(string source, string target, bool overrideIfExists = true) { var normSource = NormPath(source); @@ -221,6 +250,7 @@ public void MoveFile(string source, string target, bool overrideIfExists = true) Nodes[normTarget] = new ShadowNode(false, false); } + /// public bool FileExists(string path) { if (Nodes.TryGetValue(NormPath(path), out ShadowNode? sf)) @@ -231,8 +261,10 @@ public bool FileExists(string path) return Inner.FileExists(path); } + /// public string GetRelativePath(string fullPathOrUrl) => Inner.GetRelativePath(fullPathOrUrl); + /// public string GetFullPath(string path) { if (Nodes.TryGetValue(NormPath(path), out ShadowNode? sf)) @@ -243,8 +275,10 @@ public string GetFullPath(string path) return Inner.GetFullPath(path); } + /// public string GetUrl(string? path) => Inner.GetUrl(path); + /// public DateTimeOffset GetLastModified(string path) { if (Nodes.TryGetValue(NormPath(path), out ShadowNode? sf) == false) @@ -260,6 +294,7 @@ public DateTimeOffset GetLastModified(string path) return _sfs.GetLastModified(path); } + /// public DateTimeOffset GetCreated(string path) { if (Nodes.TryGetValue(NormPath(path), out ShadowNode? sf) == false) @@ -275,6 +310,7 @@ public DateTimeOffset GetCreated(string path) return _sfs.GetCreated(path); } + /// public long GetSize(string path) { if (Nodes.TryGetValue(NormPath(path), out ShadowNode? sf) == false) @@ -290,6 +326,7 @@ public long GetSize(string path) return _sfs.GetSize(path); } + /// public void AddFile(string path, string physicalPath, bool overrideIfExists = true, bool copy = false) { var normPath = NormPath(path); @@ -334,6 +371,10 @@ public void AddFile(string path, string physicalPath, bool overrideIfExists = tr Nodes[normPath] = new ShadowNode(false, false); } + /// + /// Applies all shadow changes to the inner file system. + /// + /// Thrown when one or more changes could not be applied. public void Complete() { if (_nodes == null) @@ -399,9 +440,20 @@ public void Complete() throw new AggregateException("Failed to apply all changes (see exceptions).", exceptions); } + /// + /// Normalizes a path to lowercase with forward slashes. + /// + /// The path to normalize. + /// The normalized path. private static string NormPath(string path) => path.ToLowerInvariant().Replace("\\", "/"); - // values can be "" (root), "foo", "foo/bar"... + /// + /// Determines whether the input path is a direct child of the specified path. + /// + /// The parent path. + /// The input path to check. + /// true if input is a direct child of path; otherwise, false. + /// Values can be "" (root), "foo", "foo/bar"... private static bool IsChild(string path, string input) { if (input.StartsWith(path) == false || input.Length < path.Length + 2) @@ -418,6 +470,12 @@ private static bool IsChild(string path, string input) return pos < 0; } + /// + /// Determines whether the input path is a descendant (direct or indirect) of the specified path. + /// + /// The ancestor path. + /// The input path to check. + /// true if input is a descendant of path; otherwise, false. private static bool IsDescendant(string path, string input) { if (input.StartsWith(path) == false || input.Length < path.Length + 2) @@ -428,6 +486,11 @@ private static bool IsDescendant(string path, string input) return path.Length == 0 || input[path.Length] == '/'; } + /// + /// Marks files and directories for deletion in the shadow. + /// + /// The path to delete. + /// If true, recursively mark descendants for deletion. private void Delete(string path, bool recurse) { foreach (var file in Inner.GetFiles(path)) @@ -445,7 +508,10 @@ private void Delete(string path, bool recurse) } } - // copied from System.Web.Util.Wildcard internal + /// + /// Represents a wildcard expression for matching file names. + /// + /// Copied from System.Web.Util.Wildcard internal. internal sealed partial class WildcardExpression { private static readonly Regex MetaRegex = GetMetaRegex(); @@ -472,18 +538,32 @@ internal sealed partial class WildcardExpression private readonly string _pattern; private Regex? _regex; + /// + /// Initializes a new instance of the class. + /// + /// The wildcard pattern (e.g., "*.txt"). + /// Whether matching should be case-insensitive. public WildcardExpression(string pattern, bool caseInsensitive = true) { _pattern = pattern; _caseInsensitive = caseInsensitive; } + /// + /// Determines whether the input string matches the wildcard pattern. + /// + /// The input string to match. + /// true if the input matches the pattern; otherwise, false. public bool IsMatch(string input) { EnsureRegex(_pattern); return _regex?.IsMatch(input) ?? false; } + /// + /// Ensures that the regex is compiled from the pattern. + /// + /// The wildcard pattern to compile. private void EnsureRegex(string pattern) { if (_regex != null) @@ -522,20 +602,40 @@ private void EnsureRegex(string pattern) } } + /// + /// Represents a node in the shadow file system tracking the state of a file or directory. + /// private sealed class ShadowNode { + /// + /// Initializes a new instance of the class. + /// + /// Whether this node represents a deletion. + /// Whether this node represents a directory. public ShadowNode(bool isDelete, bool isdir) { IsDelete = isDelete; IsDir = isdir; } + /// + /// Gets a value indicating whether this node represents a deletion. + /// public bool IsDelete { get; } + /// + /// Gets a value indicating whether this node represents a directory. + /// public bool IsDir { get; } + /// + /// Gets a value indicating whether this node represents an existing item (not deleted). + /// public bool IsExist => IsDelete == false; + /// + /// Gets a value indicating whether this node represents a file (not a directory). + /// public bool IsFile => IsDir == false; } } diff --git a/src/Umbraco.Core/IO/ShadowFileSystems.cs b/src/Umbraco.Core/IO/ShadowFileSystems.cs index 6e3ce7ca1968..2755a5ac54ce 100644 --- a/src/Umbraco.Core/IO/ShadowFileSystems.cs +++ b/src/Umbraco.Core/IO/ShadowFileSystems.cs @@ -1,12 +1,23 @@ namespace Umbraco.Cms.Core.IO; -// shadow filesystems is definitively ... too convoluted +/// +/// Represents a shadow file systems scope that can be completed or disposed. +/// +/// +/// Shadow filesystems are used to temporarily capture file system changes within a scope, +/// and either apply or discard them when the scope completes. +/// internal sealed class ShadowFileSystems : ICompletable { private readonly FileSystems _fileSystems; private bool _completed; - // invoked by the filesystems when shadowing + /// + /// Initializes a new instance of the class. + /// + /// The file systems to shadow. + /// The unique identifier for this shadow scope. + /// Invoked by the filesystems when shadowing. public ShadowFileSystems(FileSystems fileSystems, string id) { _fileSystems = fileSystems; @@ -15,12 +26,20 @@ public ShadowFileSystems(FileSystems fileSystems, string id) _fileSystems.BeginShadow(id); } - // for tests + /// + /// Gets the unique identifier for this shadow scope. + /// public string Id { get; } - // invoked by the scope when exiting, if completed + /// + /// Marks the shadow scope as completed, indicating that changes should be applied. + /// + /// Invoked by the scope when exiting, if completed. public void Complete() => _completed = true; - // invoked by the scope when exiting + /// + /// Disposes the shadow scope, applying or discarding changes based on completion status. + /// + /// Invoked by the scope when exiting. public void Dispose() => _fileSystems.EndShadow(Id, _completed); } diff --git a/src/Umbraco.Core/IO/ShadowWrapper.cs b/src/Umbraco.Core/IO/ShadowWrapper.cs index 9f4abc916085..3385180562a0 100644 --- a/src/Umbraco.Core/IO/ShadowWrapper.cs +++ b/src/Umbraco.Core/IO/ShadowWrapper.cs @@ -5,6 +5,13 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Wraps a file system to support shadow mode for transactional file operations. +/// +/// +/// When in shadow mode, all file operations are captured and can be applied or discarded +/// when the shadow scope ends. +/// internal sealed class ShadowWrapper : IFileSystem, IFileProviderFactory { private const string ShadowFsPath = "ShadowFs"; @@ -18,6 +25,15 @@ internal sealed class ShadowWrapper : IFileSystem, IFileProviderFactory private string? _shadowDir; private ShadowFileSystem? _shadowFileSystem; + /// + /// Initializes a new instance of the class. + /// + /// The inner file system to wrap. + /// The IO helper. + /// The hosting environment. + /// The logger factory. + /// The shadow path for temporary files. + /// A function that returns whether the file system is currently scoped. public ShadowWrapper(IFileSystem innerFileSystem, IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILoggerFactory loggerFactory, string shadowPath, Func? isScoped = null) { InnerFileSystem = innerFileSystem; @@ -29,10 +45,17 @@ public ShadowWrapper(IFileSystem innerFileSystem, IIOHelper ioHelper, IHostingEn _isScoped = isScoped; } + /// + /// Gets the inner file system being wrapped. + /// public IFileSystem InnerFileSystem { get; } + /// public bool CanAddPhysical => FileSystem.CanAddPhysical; + /// + /// Gets the current file system, which may be the shadow or inner file system depending on scope. + /// private IFileSystem FileSystem { get @@ -61,42 +84,70 @@ private IFileSystem FileSystem /// public IFileProvider? Create() => InnerFileSystem.TryCreateFileProvider(out IFileProvider? fileProvider) ? fileProvider : null; + /// public IEnumerable GetDirectories(string path) => FileSystem.GetDirectories(path); + /// public void DeleteDirectory(string path) => FileSystem.DeleteDirectory(path); + /// public void DeleteDirectory(string path, bool recursive) => FileSystem.DeleteDirectory(path, recursive); + /// public bool DirectoryExists(string path) => FileSystem.DirectoryExists(path); + /// public void AddFile(string path, Stream stream) => FileSystem.AddFile(path, stream); + /// public void AddFile(string path, Stream stream, bool overrideExisting) => FileSystem.AddFile(path, stream, overrideExisting); + /// public IEnumerable GetFiles(string path) => FileSystem.GetFiles(path); + /// public IEnumerable GetFiles(string path, string filter) => FileSystem.GetFiles(path, filter); + /// public Stream OpenFile(string path) => FileSystem.OpenFile(path); + /// public void DeleteFile(string path) => FileSystem.DeleteFile(path); + /// + /// Moves a file from the source path to the target path. + /// + /// The source file path. + /// The target file path. public void MoveFile(string source, string target) => FileSystem.MoveFile(source, target); + /// public bool FileExists(string path) => FileSystem.FileExists(path); + /// public string GetRelativePath(string fullPathOrUrl) => FileSystem.GetRelativePath(fullPathOrUrl); + /// public string GetFullPath(string path) => FileSystem.GetFullPath(path); + /// public string GetUrl(string? path) => FileSystem.GetUrl(path); + /// public DateTimeOffset GetLastModified(string path) => FileSystem.GetLastModified(path); + /// public DateTimeOffset GetCreated(string path) => FileSystem.GetCreated(path); + /// public long GetSize(string path) => FileSystem.GetSize(path); + /// + /// Creates a unique shadow identifier for a shadow scope. + /// + /// The hosting environment. + /// A unique identifier for the shadow scope. + /// Thrown when unable to create a unique identifier after multiple retries. public static string CreateShadowId(IHostingEnvironment hostingEnvironment) { const int retries = 50; // avoid infinite loop @@ -123,9 +174,14 @@ public static string CreateShadowId(IHostingEnvironment hostingEnvironment) throw new Exception($"Could not get a shadow identifier (tried {retries} times)"); } + /// public void AddFile(string path, string physicalPath, bool overrideIfExists = true, bool copy = false) => FileSystem.AddFile(path, physicalPath, overrideIfExists, copy); + /// + /// Enters shadow mode with the specified identifier. + /// + /// The shadow identifier. internal void Shadow(string id) { // note: no thread-safety here, because ShadowFs is thread-safe due to the check @@ -138,6 +194,10 @@ internal void Shadow(string id) _shadowFileSystem = new ShadowFileSystem(InnerFileSystem, tempfs); } + /// + /// Exits shadow mode, optionally applying the changes. + /// + /// If true, apply the shadow changes to the inner file system; otherwise, discard them. internal void UnShadow(bool complete) { ShadowFileSystem? shadowFileSystem = _shadowFileSystem; diff --git a/src/Umbraco.Core/IO/ViewHelper.cs b/src/Umbraco.Core/IO/ViewHelper.cs index 49c608ce7c57..707e3b897c0c 100644 --- a/src/Umbraco.Core/IO/ViewHelper.cs +++ b/src/Umbraco.Core/IO/ViewHelper.cs @@ -7,19 +7,30 @@ namespace Umbraco.Cms.Core.IO; +/// +/// Provides helper methods for working with template view files. +/// public class ViewHelper : IViewHelper { private readonly IDefaultViewContentProvider _defaultViewContentProvider; private readonly IFileSystem _viewFileSystem; - public ViewHelper(FileSystems fileSystems, IDefaultViewContentProvider defaultViewContentProvider) + /// + /// Initializes a new instance of the class. + /// + /// The file systems provider. + /// The default view content provider. + /// Thrown when any required parameter is null. + public ViewHelper(FileSystems fileSystems, IDefaultViewContentProvider defaultViewContentProvider) { _viewFileSystem = fileSystems.MvcViewsFileSystem ?? throw new ArgumentNullException(nameof(fileSystems)); _defaultViewContentProvider = defaultViewContentProvider ?? throw new ArgumentNullException(nameof(defaultViewContentProvider)); } + /// public bool ViewExists(ITemplate t) => t.Alias is not null && _viewFileSystem.FileExists(ViewPath(t.Alias)); + /// public string GetFileContents(ITemplate t) { var viewContent = string.Empty; @@ -37,6 +48,7 @@ public string GetFileContents(ITemplate t) return viewContent; } + /// public string CreateView(ITemplate t, bool overWrite = false) { string viewContent; @@ -58,6 +70,7 @@ public string CreateView(ITemplate t, bool overWrite = false) return viewContent; } + /// public string? UpdateViewFile(ITemplate t, string? currentAlias = null) { var path = ViewPath(t.Alias); @@ -83,8 +96,14 @@ public string CreateView(ITemplate t, bool overWrite = false) return t.Content; } + /// public string ViewPath(string alias) => _viewFileSystem.GetRelativePath(alias.Replace(" ", string.Empty) + ".cshtml"); + /// + /// Saves the template content to a view file. + /// + /// The template to save. + /// The content that was saved to the file. private string SaveTemplateToFile(ITemplate template) { var design = template.Content.IsNullOrWhiteSpace() ? EnsureInheritedLayout(template) : template.Content!; @@ -101,6 +120,11 @@ private string SaveTemplateToFile(ITemplate template) return design; } + /// + /// Ensures that the template has an inherited layout set. + /// + /// The template to check. + /// The template content with an inherited layout. private string EnsureInheritedLayout(ITemplate template) { var design = template.Content; diff --git a/src/Umbraco.Core/IRegisteredObject.cs b/src/Umbraco.Core/IRegisteredObject.cs index 103e10dab162..2cf8799b3139 100644 --- a/src/Umbraco.Core/IRegisteredObject.cs +++ b/src/Umbraco.Core/IRegisteredObject.cs @@ -1,6 +1,16 @@ namespace Umbraco.Cms.Core; +/// +/// Defines an object that can be registered with the application and notified when the application shuts down. +/// public interface IRegisteredObject { + /// + /// Requests the object to stop processing. + /// + /// + /// true to indicate the registered object should stop immediately; + /// false to indicate the registered object should complete any pending work before stopping. + /// void Stop(bool immediate); } diff --git a/src/Umbraco.Core/Install/FilePermissionTest.cs b/src/Umbraco.Core/Install/FilePermissionTest.cs index 21c6d4f0c7da..a41e38f97fb7 100644 --- a/src/Umbraco.Core/Install/FilePermissionTest.cs +++ b/src/Umbraco.Core/Install/FilePermissionTest.cs @@ -1,9 +1,27 @@ namespace Umbraco.Cms.Core.Install; +/// +/// Defines the types of file permission tests performed during Umbraco installation. +/// public enum FilePermissionTest { + /// + /// Test for the ability to create folders. + /// FolderCreation, + + /// + /// Test for the ability to write files required for packages. + /// FileWritingForPackages, + + /// + /// Test for general file writing ability. + /// FileWriting, + + /// + /// Test for the ability to create folders in the media directory. + /// MediaFolderCreation, } diff --git a/src/Umbraco.Core/Install/Models/DatabaseModel.cs b/src/Umbraco.Core/Install/Models/DatabaseModel.cs index 1c632081cebd..1a84d999797c 100644 --- a/src/Umbraco.Core/Install/Models/DatabaseModel.cs +++ b/src/Umbraco.Core/Install/Models/DatabaseModel.cs @@ -1,36 +1,75 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using System.Runtime.Serialization; namespace Umbraco.Cms.Core.Install.Models; +/// +/// Represents the database configuration model used during installation. +/// [DataContract(Name = "database", Namespace = "")] public class DatabaseModel { + /// + /// Gets or sets the unique identifier for the database provider metadata. + /// [DataMember(Name = "databaseProviderMetadataId")] public Guid DatabaseProviderMetadataId { get; set; } + /// + /// Gets or sets the name of the database provider. + /// [DataMember(Name = "providerName")] public string? ProviderName { get; set; } // TODO: Make this nullable in V11 // Server can be null, for instance when installing a SQLite database. + /// + /// Gets or sets the database server address. + /// + /// + /// This value can be null for certain database providers, such as SQLite. + /// [DataMember(Name = "server")] public string Server { get; set; } = null!; + /// + /// Gets or sets the name of the database. + /// [DataMember(Name = "databaseName")] public string DatabaseName { get; set; } = null!; + /// + /// Gets or sets the login username for database authentication. + /// [DataMember(Name = "login")] public string? Login { get; set; } + /// + /// Gets or sets the password for database authentication. + /// [DataMember(Name = "password")] public string? Password { get; set; } + /// + /// Gets or sets a value indicating whether to use integrated (Windows) authentication. + /// [DataMember(Name = "integratedAuth")] public bool IntegratedAuth { get; set; } + /// + /// Gets or sets a value indicating whether to trust the server certificate. + /// [DataMember(Name = "trustServerCertificate")] public bool TrustServerCertificate { get; set; } + /// + /// Gets or sets the full connection string for the database. + /// + /// + /// When provided, this connection string is used directly instead of building one from the other properties. + /// [DataMember(Name = "connectionString")] public string? ConnectionString { get; set; } } diff --git a/src/Umbraco.Core/InstallLog.cs b/src/Umbraco.Core/InstallLog.cs index d0bec2097fd5..22402f2c1292 100644 --- a/src/Umbraco.Core/InstallLog.cs +++ b/src/Umbraco.Core/InstallLog.cs @@ -1,7 +1,24 @@ namespace Umbraco.Cms.Core; +/// +/// Represents an installation or upgrade log entry. +/// public class InstallLog { + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier for this installation. + /// Whether this is an upgrade from a previous version. + /// Whether the installation completed successfully. + /// The timestamp of the installation. + /// The major version number. + /// The minor version number. + /// The patch version number. + /// A comment about the version (e.g., pre-release tag). + /// Any error message from the installation. + /// The user agent string from the browser performing the installation. + /// The database provider being used. public InstallLog( Guid installId, bool isUpgrade, @@ -28,25 +45,58 @@ public InstallLog( DbProvider = dbProvider; } + /// + /// Gets the unique identifier for this installation. + /// public Guid InstallId { get; } + /// + /// Gets or sets a value indicating whether this is an upgrade from a previous version. + /// public bool IsUpgrade { get; set; } + /// + /// Gets or sets a value indicating whether the installation completed successfully. + /// public bool InstallCompleted { get; set; } + /// + /// Gets or sets the timestamp of the installation. + /// public DateTime Timestamp { get; set; } + /// + /// Gets the major version number of the installed version. + /// public int VersionMajor { get; } + /// + /// Gets the minor version number of the installed version. + /// public int VersionMinor { get; } + /// + /// Gets the patch version number of the installed version. + /// public int VersionPatch { get; } + /// + /// Gets a comment about the version (e.g., pre-release tag like "beta"). + /// public string VersionComment { get; } + /// + /// Gets any error message from the installation, or an empty string if no error occurred. + /// public string Error { get; } + /// + /// Gets the user agent string from the browser performing the installation. + /// public string? UserAgent { get; } + /// + /// Gets or sets the database provider being used. + /// public string DbProvider { get; set; } } diff --git a/src/Umbraco.Core/Installer/NewInstallStepCollection.cs b/src/Umbraco.Core/Installer/NewInstallStepCollection.cs index 36ba95f5276e..b7ddc0c9d03e 100644 --- a/src/Umbraco.Core/Installer/NewInstallStepCollection.cs +++ b/src/Umbraco.Core/Installer/NewInstallStepCollection.cs @@ -1,9 +1,16 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.Installer; +/// +/// Represents a collection of instances used during new Umbraco installations. +/// public class NewInstallStepCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection of install steps. public NewInstallStepCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/Installer/NewInstallStepCollectionBuilder.cs b/src/Umbraco.Core/Installer/NewInstallStepCollectionBuilder.cs index afc84052c0be..f240d2a07d3b 100644 --- a/src/Umbraco.Core/Installer/NewInstallStepCollectionBuilder.cs +++ b/src/Umbraco.Core/Installer/NewInstallStepCollectionBuilder.cs @@ -1,11 +1,16 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.Installer; +/// +/// A builder for creating a with ordered instances. +/// public class NewInstallStepCollectionBuilder : OrderedCollectionBuilderBase { + /// protected override NewInstallStepCollectionBuilder This => this; + /// protected override ServiceLifetime CollectionLifetime => ServiceLifetime.Scoped; } diff --git a/src/Umbraco.Core/Installer/StepBase.cs b/src/Umbraco.Core/Installer/StepBase.cs index 4ad7983e7647..fb7283f071ca 100644 --- a/src/Umbraco.Core/Installer/StepBase.cs +++ b/src/Umbraco.Core/Installer/StepBase.cs @@ -1,12 +1,24 @@ -using Umbraco.Cms.Core.Models.Installer; +using Umbraco.Cms.Core.Models.Installer; namespace Umbraco.Cms.Core.Installer; +/// +/// Provides a base class for installation and upgrade steps with common helper methods. +/// public abstract class StepBase { + /// + /// Creates a failed with the specified error message. + /// + /// The error message to include in the result. + /// A failed containing the error message. protected Attempt FailWithMessage(string message) => Attempt.Fail(new InstallationResult { ErrorMessage = message }); + /// + /// Creates a successful . + /// + /// A successful . protected Attempt Success() => Attempt.Succeed(new InstallationResult()); } diff --git a/src/Umbraco.Core/Installer/Steps/FilePermissionsStep.cs b/src/Umbraco.Core/Installer/Steps/FilePermissionsStep.cs index a36d30d64095..732ff2541888 100644 --- a/src/Umbraco.Core/Installer/Steps/FilePermissionsStep.cs +++ b/src/Umbraco.Core/Installer/Steps/FilePermissionsStep.cs @@ -1,15 +1,23 @@ -using Umbraco.Cms.Core.Install; +using Umbraco.Cms.Core.Install; using Umbraco.Cms.Core.Services; using Umbraco.Extensions; using Umbraco.Cms.Core.Models.Installer; namespace Umbraco.Cms.Core.Installer.Steps; +/// +/// An installation and upgrade step that validates file system permissions required by Umbraco. +/// public class FilePermissionsStep : StepBase, IInstallStep, IUpgradeStep { private readonly IFilePermissionHelper _filePermissionHelper; private readonly ILocalizedTextService _localizedTextService; + /// + /// Initializes a new instance of the class. + /// + /// The file permission helper used to run permission tests. + /// The localized text service for translating error messages. public FilePermissionsStep( IFilePermissionHelper filePermissionHelper, ILocalizedTextService localizedTextService) @@ -18,10 +26,16 @@ public FilePermissionsStep( _localizedTextService = localizedTextService; } + /// public Task> ExecuteAsync(InstallData _) => Execute(); + /// public Task> ExecuteAsync() => Execute(); + /// + /// Executes the file permissions validation. + /// + /// A task containing an attempt with the installation result. private Task> Execute() { // validate file permissions @@ -40,9 +54,15 @@ private Task> Execute() return Task.FromResult(Success()); } + /// public Task RequiresExecutionAsync(InstallData model) => ShouldExecute(); + /// public Task RequiresExecutionAsync() => ShouldExecute(); + /// + /// Determines whether this step should be executed. + /// + /// A task containing true if the step should execute; otherwise, false. private static Task ShouldExecute() => Task.FromResult(true); } diff --git a/src/Umbraco.Core/Installer/Steps/RestartRuntimeStep.cs b/src/Umbraco.Core/Installer/Steps/RestartRuntimeStep.cs index 5e65175430ba..fae7f84a00aa 100644 --- a/src/Umbraco.Core/Installer/Steps/RestartRuntimeStep.cs +++ b/src/Umbraco.Core/Installer/Steps/RestartRuntimeStep.cs @@ -1,27 +1,46 @@ -using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Services; using Umbraco.Cms.Core.Models.Installer; namespace Umbraco.Cms.Core.Installer.Steps; +/// +/// An installation and upgrade step that restarts the Umbraco runtime. +/// public class RestartRuntimeStep : StepBase, IInstallStep, IUpgradeStep { private readonly IRuntime _runtime; + /// + /// Initializes a new instance of the class. + /// + /// The runtime service used to restart Umbraco. public RestartRuntimeStep(IRuntime runtime) => _runtime = runtime; + /// public async Task> ExecuteAsync(InstallData _) => await Execute(); + /// public async Task> ExecuteAsync() => await Execute(); + /// + /// Executes the runtime restart operation. + /// + /// A task containing an attempt with the installation result. private async Task> Execute() { await _runtime.RestartAsync(); return Success(); } + /// public Task RequiresExecutionAsync(InstallData _) => ShouldExecute(); + /// public Task RequiresExecutionAsync() => ShouldExecute(); + /// + /// Determines whether this step should be executed. + /// + /// A task containing true if the step should execute; otherwise, false. private Task ShouldExecute() => Task.FromResult(true); } diff --git a/src/Umbraco.Core/Installer/Steps/TelemetryIdentifierStep.cs b/src/Umbraco.Core/Installer/Steps/TelemetryIdentifierStep.cs index 18a00e4a0796..ebe1ee83a268 100644 --- a/src/Umbraco.Core/Installer/Steps/TelemetryIdentifierStep.cs +++ b/src/Umbraco.Core/Installer/Steps/TelemetryIdentifierStep.cs @@ -1,15 +1,23 @@ -using Microsoft.Extensions.Options; +using Microsoft.Extensions.Options; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Telemetry; using Umbraco.Cms.Core.Models.Installer; namespace Umbraco.Cms.Core.Installer.Steps; +/// +/// An installation and upgrade step that creates a unique telemetry site identifier. +/// public class TelemetryIdentifierStep : StepBase, IInstallStep, IUpgradeStep { private readonly IOptions _globalSettings; private readonly ISiteIdentifierService _siteIdentifierService; + /// + /// Initializes a new instance of the class. + /// + /// The global settings containing the current site identifier. + /// The service used to create site identifiers. public TelemetryIdentifierStep( IOptions globalSettings, ISiteIdentifierService siteIdentifierService) @@ -18,20 +26,32 @@ public TelemetryIdentifierStep( _siteIdentifierService = siteIdentifierService; } + /// public Task> ExecuteAsync(InstallData _) => Execute(); + /// public Task> ExecuteAsync() => Execute(); + /// + /// Executes the telemetry identifier creation. + /// + /// A task containing an attempt with the installation result. private Task> Execute() { _siteIdentifierService.TryCreateSiteIdentifier(out _); return Task.FromResult(Success()); } + /// public Task RequiresExecutionAsync(InstallData _) => ShouldExecute(); + /// public Task RequiresExecutionAsync() => ShouldExecute(); + /// + /// Determines whether this step should be executed based on whether a site identifier already exists. + /// + /// A task containing true if no site identifier exists; otherwise, false. private Task ShouldExecute() { // Verify that Json value is not empty string diff --git a/src/Umbraco.Core/Installer/UpgradeStepCollection.cs b/src/Umbraco.Core/Installer/UpgradeStepCollection.cs index 304b9e7a6f75..e0b8aeeed7de 100644 --- a/src/Umbraco.Core/Installer/UpgradeStepCollection.cs +++ b/src/Umbraco.Core/Installer/UpgradeStepCollection.cs @@ -1,9 +1,16 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.Installer; +/// +/// Represents a collection of instances used during Umbraco upgrades. +/// public class UpgradeStepCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection of upgrade steps. public UpgradeStepCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/Installer/UpgradeStepCollectionBuilder.cs b/src/Umbraco.Core/Installer/UpgradeStepCollectionBuilder.cs index 9338ba694605..ed667144f157 100644 --- a/src/Umbraco.Core/Installer/UpgradeStepCollectionBuilder.cs +++ b/src/Umbraco.Core/Installer/UpgradeStepCollectionBuilder.cs @@ -1,11 +1,16 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.Installer; +/// +/// A builder for creating an with ordered instances. +/// public class UpgradeStepCollectionBuilder : OrderedCollectionBuilderBase { + /// protected override UpgradeStepCollectionBuilder This => this; + /// protected override ServiceLifetime CollectionLifetime => ServiceLifetime.Scoped; } diff --git a/src/Umbraco.Core/LambdaExpressionCacheKey.cs b/src/Umbraco.Core/LambdaExpressionCacheKey.cs index 31ebcf688f5c..0c7e329825ff 100644 --- a/src/Umbraco.Core/LambdaExpressionCacheKey.cs +++ b/src/Umbraco.Core/LambdaExpressionCacheKey.cs @@ -13,6 +13,12 @@ public struct LambdaExpressionCacheKey /// public readonly HashSet ArgTypes; + /// + /// Initializes a new instance of the struct. + /// + /// The return type of the lambda expression. + /// The string representation of the lambda expression. + /// The argument type names of the lambda expression. public LambdaExpressionCacheKey(string returnType, string expression, params string[] argTypes) { ReturnType = returnType; @@ -21,6 +27,10 @@ public LambdaExpressionCacheKey(string returnType, string expression, params str _toString = null; } + /// + /// Initializes a new instance of the struct from a . + /// + /// The lambda expression to create a cache key from. public LambdaExpressionCacheKey(LambdaExpression obj) { ReturnType = obj.ReturnType.FullName; diff --git a/src/Umbraco.Core/Logging/DisposableTimer.cs b/src/Umbraco.Core/Logging/DisposableTimer.cs index 7db20a006852..59587b98a7ef 100644 --- a/src/Umbraco.Core/Logging/DisposableTimer.cs +++ b/src/Umbraco.Core/Logging/DisposableTimer.cs @@ -22,7 +22,20 @@ public class DisposableTimer : DisposableObjectSlim private Exception? _failException; private string? _failMessage; - // internal - created by profiling logger + /// + /// Initializes a new instance of the class. + /// + /// The logger to write messages to. + /// The log level for the messages. + /// The profiler to use for timing. + /// The type to use as the logger category. + /// The message to log when the timer starts. + /// The message to log when the timer ends successfully. + /// The message to log if the operation fails. + /// Arguments for the start message template. + /// Arguments for the end message template. + /// Arguments for the fail message template. + /// Minimum elapsed time in milliseconds before logging the end message. internal DisposableTimer( ILogger logger, LogLevel level, @@ -95,6 +108,9 @@ internal DisposableTimer( _profilerStep = profiler?.Step(loggerType, startMessage); } + /// + /// Gets the stopwatch used to measure elapsed time. + /// public Stopwatch Stopwatch { get; } = Stopwatch.StartNew(); /// diff --git a/src/Umbraco.Core/Logging/ILoggingConfiguration.cs b/src/Umbraco.Core/Logging/ILoggingConfiguration.cs index db379201bf8e..757fed5a5c60 100644 --- a/src/Umbraco.Core/Logging/ILoggingConfiguration.cs +++ b/src/Umbraco.Core/Logging/ILoggingConfiguration.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Logging; +/// +/// Defines the configuration settings for the logging system. +/// public interface ILoggingConfiguration { /// diff --git a/src/Umbraco.Core/Logging/IMessageTemplates.cs b/src/Umbraco.Core/Logging/IMessageTemplates.cs index 252f91aaa532..53500e301a49 100644 --- a/src/Umbraco.Core/Logging/IMessageTemplates.cs +++ b/src/Umbraco.Core/Logging/IMessageTemplates.cs @@ -5,5 +5,11 @@ namespace Umbraco.Cms.Core.Logging; /// public interface IMessageTemplates { + /// + /// Renders a message template with the provided arguments. + /// + /// The message template containing placeholders. + /// The arguments to substitute into the template placeholders. + /// The rendered message with placeholders replaced by argument values. string Render(string messageTemplate, params object[] args); } diff --git a/src/Umbraco.Core/Logging/IProfilingLogger.cs b/src/Umbraco.Core/Logging/IProfilingLogger.cs index 77c4c869f6ea..88f5e8ceaf6a 100644 --- a/src/Umbraco.Core/Logging/IProfilingLogger.cs +++ b/src/Umbraco.Core/Logging/IProfilingLogger.cs @@ -8,11 +8,23 @@ public interface IProfilingLogger /// /// Profiles an action and log as information messages. /// + /// The type to use as the logger category. + /// The message to log when the timer starts. + /// Arguments for the start message template. + /// A that logs completion when disposed. DisposableTimer TraceDuration(string startMessage, object[]? startMessageArgs = null); /// /// Profiles an action and log as information messages. /// + /// The type to use as the logger category. + /// The message to log when the timer starts. + /// The message to log when the timer ends successfully. + /// The message to log if the operation fails. + /// Arguments for the start message template. + /// Arguments for the end message template. + /// Arguments for the fail message template. + /// A that logs completion when disposed. DisposableTimer TraceDuration( string startMessage, string completeMessage, @@ -24,6 +36,14 @@ DisposableTimer TraceDuration( /// /// Profiles an action and log as information messages. /// + /// The type to use as the logger category. + /// The message to log when the timer starts. + /// The message to log when the timer ends successfully. + /// The message to log if the operation fails. + /// Arguments for the start message template. + /// Arguments for the end message template. + /// Arguments for the fail message template. + /// A that logs completion when disposed. DisposableTimer TraceDuration( Type loggerType, string startMessage, @@ -36,11 +56,24 @@ DisposableTimer TraceDuration( /// /// Profiles an action and log as debug messages. /// + /// The type to use as the logger category. + /// The message to log when the timer starts. + /// Arguments for the start message template. + /// A that logs completion when disposed, or null if debug logging is disabled. DisposableTimer? DebugDuration(string startMessage, object[]? startMessageArgs = null); /// /// Profiles an action and log as debug messages. /// + /// The type to use as the logger category. + /// The message to log when the timer starts. + /// The message to log when the timer ends successfully. + /// The message to log if the operation fails. + /// Minimum elapsed time in milliseconds before logging the end message. + /// Arguments for the start message template. + /// Arguments for the end message template. + /// Arguments for the fail message template. + /// A that logs completion when disposed, or null if debug logging is disabled. DisposableTimer? DebugDuration( string startMessage, string completeMessage, @@ -53,6 +86,15 @@ DisposableTimer TraceDuration( /// /// Profiles an action and log as debug messages. /// + /// The type to use as the logger category. + /// The message to log when the timer starts. + /// The message to log when the timer ends successfully. + /// The message to log if the operation fails. + /// Minimum elapsed time in milliseconds before logging the end message. + /// Arguments for the start message template. + /// Arguments for the end message template. + /// Arguments for the fail message template. + /// A that logs completion when disposed, or null if debug logging is disabled. DisposableTimer? DebugDuration( Type loggerType, string startMessage, @@ -64,9 +106,9 @@ DisposableTimer TraceDuration( object[]? failMessageArgs = null); /// - /// Checks if the given logLevel is enabled. + /// Checks if the given logLevel is enabled. /// /// Level to be checked. - /// true if enabled. + /// true if enabled; otherwise, false. bool IsEnabled(LogLevel logLevel) => true; } diff --git a/src/Umbraco.Core/Logging/LogHttpRequest.cs b/src/Umbraco.Core/Logging/LogHttpRequest.cs index 2981dd598708..05f07c7e34cd 100644 --- a/src/Umbraco.Core/Logging/LogHttpRequest.cs +++ b/src/Umbraco.Core/Logging/LogHttpRequest.cs @@ -2,6 +2,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for retrieving HTTP request identifiers for logging purposes. +/// public static class LogHttpRequest { private static readonly string RequestIdItemName = typeof(LogHttpRequest).Name + "+RequestId"; diff --git a/src/Umbraco.Core/Logging/LogLevel.cs b/src/Umbraco.Core/Logging/LogLevel.cs index b7271ecf043a..b19448eeaa37 100644 --- a/src/Umbraco.Core/Logging/LogLevel.cs +++ b/src/Umbraco.Core/Logging/LogLevel.cs @@ -5,10 +5,33 @@ namespace Umbraco.Cms.Core.Logging; /// public enum LogLevel { + /// + /// Verbose level for the most detailed tracing information. + /// Verbose, + + /// + /// Debug level for internal system events useful for debugging. + /// Debug, + + /// + /// Information level for general informational messages. + /// Information, + + /// + /// Warning level for potentially harmful situations. + /// Warning, + + /// + /// Error level for error events that might still allow the application to continue running. + /// Error, + + /// + /// Fatal level for very severe error events that will presumably lead the application to abort. + /// Fatal, } diff --git a/src/Umbraco.Core/Logging/LogProfiler.cs b/src/Umbraco.Core/Logging/LogProfiler.cs index 50ecd93f4bce..0aff6ac71765 100644 --- a/src/Umbraco.Core/Logging/LogProfiler.cs +++ b/src/Umbraco.Core/Logging/LogProfiler.cs @@ -10,6 +10,10 @@ public class LogProfiler : IProfiler { private readonly ILogger _logger; + /// + /// Initializes a new instance of the class. + /// + /// The logger to write profiling results to. public LogProfiler(ILogger logger) => _logger = logger; /// @@ -38,17 +42,24 @@ public void Stop(bool discardResults = false) /// public bool IsEnabled => _logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug); - // a lightweight disposable timer + /// + /// A lightweight disposable timer that invokes a callback with the elapsed time upon disposal. + /// private sealed class LightDisposableTimer : DisposableObjectSlim { private readonly Action _callback; private readonly Stopwatch _stopwatch = Stopwatch.StartNew(); + /// + /// Initializes a new instance of the class. + /// + /// The callback to invoke with the elapsed milliseconds when disposed. internal LightDisposableTimer(Action callback) { _callback = callback ?? throw new ArgumentNullException(nameof(callback)); } + /// protected override void DisposeResources() { _stopwatch.Stop(); diff --git a/src/Umbraco.Core/Logging/LoggingTaskExtension.cs b/src/Umbraco.Core/Logging/LoggingTaskExtension.cs index 950e9bb8f46d..4eef9c196b95 100644 --- a/src/Umbraco.Core/Logging/LoggingTaskExtension.cs +++ b/src/Umbraco.Core/Logging/LoggingTaskExtension.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Logging; +/// +/// Provides extension methods for to handle and log exceptions. +/// internal static class LoggingTaskExtension { /// @@ -10,6 +13,9 @@ internal static class LoggingTaskExtension /// be handling /// errors yourself. /// + /// The task to attach error logging to. + /// The logging method to call with error message and exception. + /// A continuation task that logs errors if the original task faults. public static Task LogErrors(this Task task, Action logMethod) => task.ContinueWith( t => LogErrorsInner(t, logMethod), @@ -28,6 +34,9 @@ public static Task LogErrors(this Task task, Action logMethod /// be handling /// errors yourself. /// + /// The task to attach error logging to. + /// The logging method to call with error message and exception. + /// A continuation task that logs errors, guaranteed to run regardless of task completion state. public static Task LogErrorsWaitable(this Task task, Action logMethod) => task.ContinueWith( t => LogErrorsInner(t, logMethod), @@ -35,6 +44,11 @@ public static Task LogErrorsWaitable(this Task task, Action l // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html TaskScheduler.Default); + /// + /// Logs any exceptions from the task using the provided log action. + /// + /// The task that may contain exceptions. + /// The action to invoke for logging errors. private static void LogErrorsInner(Task task, Action logAction) { if (task.Exception != null) diff --git a/src/Umbraco.Core/Logging/NoopProfiler.cs b/src/Umbraco.Core/Logging/NoopProfiler.cs index 7c7b0b323430..bcd9856f09d4 100644 --- a/src/Umbraco.Core/Logging/NoopProfiler.cs +++ b/src/Umbraco.Core/Logging/NoopProfiler.cs @@ -1,15 +1,25 @@ namespace Umbraco.Cms.Core.Logging; +/// +/// Implements as a no-operation profiler that performs no actual profiling. +/// +/// +/// This implementation is useful when profiling is disabled or not required, providing a +/// lightweight placeholder that satisfies the contract without overhead. +/// public class NoopProfiler : IProfiler { private readonly VoidDisposable _disposable = new(); + /// public IDisposable Step(string name) => _disposable; + /// public void Start() { } + /// public void Stop(bool discardResults = false) { } @@ -17,8 +27,12 @@ public void Stop(bool discardResults = false) /// public bool IsEnabled => false; + /// + /// A disposable that does nothing when disposed. + /// private sealed class VoidDisposable : DisposableObjectSlim { + /// protected override void DisposeResources() { } diff --git a/src/Umbraco.Core/Logging/ProfilerExtensions.cs b/src/Umbraco.Core/Logging/ProfilerExtensions.cs index e69506702af9..71ba53f7ac32 100644 --- a/src/Umbraco.Core/Logging/ProfilerExtensions.cs +++ b/src/Umbraco.Core/Logging/ProfilerExtensions.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Logging; +/// +/// Provides extension methods for . +/// internal static class ProfilerExtensions { /// diff --git a/src/Umbraco.Core/Logging/ProfilingLogger.cs b/src/Umbraco.Core/Logging/ProfilingLogger.cs index 53a9ee4f5852..fb0556cbd35c 100644 --- a/src/Umbraco.Core/Logging/ProfilingLogger.cs +++ b/src/Umbraco.Core/Logging/ProfilingLogger.cs @@ -35,9 +35,11 @@ public ProfilingLogger(ILogger logger, IProfiler profiler) /// public IProfiler Profiler { get; } + /// public DisposableTimer TraceDuration(string startMessage, object[]? startMessageArgs = null) => TraceDuration(startMessage, "Completed.", startMessageArgs: startMessageArgs); + /// public DisposableTimer TraceDuration( string startMessage, string completeMessage, @@ -47,6 +49,7 @@ public DisposableTimer TraceDuration( object[]? failMessageArgs = null) => new(Logger, LogLevel.Information, Profiler, typeof(T), startMessage, completeMessage, failMessage, startMessageArgs, endMessageArgs, failMessageArgs); + /// public DisposableTimer TraceDuration( Type loggerType, string startMessage, @@ -57,11 +60,13 @@ public DisposableTimer TraceDuration( object[]? failMessageArgs = null) => new(Logger, LogLevel.Information, Profiler, loggerType, startMessage, completeMessage, failMessage, startMessageArgs, endMessageArgs, failMessageArgs); + /// public DisposableTimer? DebugDuration(string startMessage, object[]? startMessageArgs = null) => Logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug) ? DebugDuration(startMessage, "Completed.", startMessageArgs: startMessageArgs) : null; + /// public DisposableTimer? DebugDuration( string startMessage, string completeMessage, @@ -85,6 +90,7 @@ public DisposableTimer TraceDuration( thresholdMilliseconds) : null; + /// public DisposableTimer? DebugDuration( Type loggerType, string startMessage, @@ -111,33 +117,86 @@ public DisposableTimer TraceDuration( #region ILogger + /// + /// Checks if the given log level is enabled. + /// + /// The log level to check. + /// true if the log level is enabled; otherwise, false. public bool IsEnabled(Microsoft.Extensions.Logging.LogLevel level) => Logger.IsEnabled(level); + /// + /// Logs a critical message with an exception. + /// + /// The exception to log. + /// The message template. + /// The property values to substitute into the template. public void LogCritical(Exception exception, string messageTemplate, params object[] propertyValues) => Logger.LogCritical(exception, messageTemplate, propertyValues); + /// + /// Logs a critical message. + /// + /// The message template. + /// The property values to substitute into the template. public void LogCritical(string messageTemplate, params object[] propertyValues) => Logger.LogCritical(messageTemplate, propertyValues); + /// + /// Logs an error message with an exception. + /// + /// The exception to log. + /// The message template. + /// The property values to substitute into the template. public void LogError(Exception exception, string messageTemplate, params object[] propertyValues) => Logger.LogError(exception, messageTemplate, propertyValues); + /// + /// Logs an error message. + /// + /// The message template. + /// The property values to substitute into the template. public void LogError(string messageTemplate, params object[] propertyValues) => Logger.LogError(messageTemplate, propertyValues); + /// + /// Logs a warning message. + /// + /// The message template. + /// The property values to substitute into the template. public void LogWarning(string messageTemplate, params object[] propertyValues) => Logger.LogWarning(messageTemplate, propertyValues); + /// + /// Logs a warning message with an exception. + /// + /// The exception to log. + /// The message template. + /// The property values to substitute into the template. public void LogWarning(Exception exception, string messageTemplate, params object[] propertyValues) => Logger.LogWarning(exception, messageTemplate, propertyValues); + /// + /// Logs an information message. + /// + /// The message template. + /// The property values to substitute into the template. public void LogInformation(string messageTemplate, params object[] propertyValues) => Logger.LogInformation(messageTemplate, propertyValues); + /// + /// Logs a debug message. + /// + /// The message template. + /// The property values to substitute into the template. public void LogDebug(string messageTemplate, params object[] propertyValues) => Logger.LogDebug(messageTemplate, propertyValues); + /// + /// Logs a trace message. + /// + /// The message template. + /// The property values to substitute into the template. public void LogTrace(string messageTemplate, params object[] propertyValues) => Logger.LogTrace(messageTemplate, propertyValues); diff --git a/src/Umbraco.Core/Logging/Viewer/ILogEntry.cs b/src/Umbraco.Core/Logging/Viewer/ILogEntry.cs index c690b70f287c..4fbf7ce86f8f 100644 --- a/src/Umbraco.Core/Logging/Viewer/ILogEntry.cs +++ b/src/Umbraco.Core/Logging/Viewer/ILogEntry.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Logging.Viewer; +/// +/// Defines the contract for a log entry with its associated metadata and content. +/// public interface ILogEntry { /// diff --git a/src/Umbraco.Core/Logging/Viewer/LogEntry.cs b/src/Umbraco.Core/Logging/Viewer/LogEntry.cs index b5c54eddbe1e..7ad899086934 100644 --- a/src/Umbraco.Core/Logging/Viewer/LogEntry.cs +++ b/src/Umbraco.Core/Logging/Viewer/LogEntry.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Logging.Viewer; +/// +/// Represents a single log entry with its associated metadata and content. +/// public class LogEntry : ILogEntry { /// diff --git a/src/Umbraco.Core/Logging/Viewer/LogLevelCounts.cs b/src/Umbraco.Core/Logging/Viewer/LogLevelCounts.cs index 6f03135c1f9d..fe4cb9be7f87 100644 --- a/src/Umbraco.Core/Logging/Viewer/LogLevelCounts.cs +++ b/src/Umbraco.Core/Logging/Viewer/LogLevelCounts.cs @@ -1,14 +1,32 @@ namespace Umbraco.Cms.Core.Logging.Viewer; +/// +/// Represents the count of log entries grouped by log level. +/// public class LogLevelCounts { + /// + /// Gets or sets the count of information level log entries. + /// public int Information { get; set; } + /// + /// Gets or sets the count of debug level log entries. + /// public int Debug { get; set; } + /// + /// Gets or sets the count of warning level log entries. + /// public int Warning { get; set; } + /// + /// Gets or sets the count of error level log entries. + /// public int Error { get; set; } + /// + /// Gets or sets the count of fatal level log entries. + /// public int Fatal { get; set; } } diff --git a/src/Umbraco.Core/Logging/Viewer/LogTemplate.cs b/src/Umbraco.Core/Logging/Viewer/LogTemplate.cs index 821115ff1150..c71f1a246fea 100644 --- a/src/Umbraco.Core/Logging/Viewer/LogTemplate.cs +++ b/src/Umbraco.Core/Logging/Viewer/LogTemplate.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.Logging.Viewer; +/// +/// Represents a log message template with its occurrence count. +/// public class LogTemplate { + /// + /// Gets or sets the message template string. + /// public string? MessageTemplate { get; set; } + /// + /// Gets or sets the number of times this template appears in the logs. + /// public int Count { get; set; } } diff --git a/src/Umbraco.Core/Logging/Viewer/LogTimePeriod.cs b/src/Umbraco.Core/Logging/Viewer/LogTimePeriod.cs index 67533ef4f1b6..d725b83d8127 100644 --- a/src/Umbraco.Core/Logging/Viewer/LogTimePeriod.cs +++ b/src/Umbraco.Core/Logging/Viewer/LogTimePeriod.cs @@ -1,14 +1,28 @@ namespace Umbraco.Cms.Core.Logging.Viewer; +/// +/// Represents a time period for filtering log entries. +/// public class LogTimePeriod { + /// + /// Initializes a new instance of the class. + /// + /// The start time of the period. + /// The end time of the period. public LogTimePeriod(DateTime startTime, DateTime endTime) { StartTime = startTime; EndTime = endTime; } + /// + /// Gets the start time of the period. + /// public DateTime StartTime { get; } + /// + /// Gets the end time of the period. + /// public DateTime EndTime { get; } } diff --git a/src/Umbraco.Core/Mail/ISmsSender.cs b/src/Umbraco.Core/Mail/ISmsSender.cs index 3c09bdc7e632..2a56b205dc13 100644 --- a/src/Umbraco.Core/Mail/ISmsSender.cs +++ b/src/Umbraco.Core/Mail/ISmsSender.cs @@ -1,10 +1,18 @@ namespace Umbraco.Cms.Core.Mail; /// -/// Service to send an SMS +/// Service to send an SMS. /// +/// +/// Borrowed from ASP.NET Core documentation samples. +/// public interface ISmsSender { - // borrowed from https://github.com/dotnet/AspNetCore.Docs/blob/master/aspnetcore/common/samples/WebApplication1/Services/ISmsSender.cs#L8 + /// + /// Sends an SMS message asynchronously. + /// + /// The phone number to send the SMS to. + /// The message content to send. + /// A task representing the asynchronous operation. Task SendSmsAsync(string number, string message); } diff --git a/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs b/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs index 21d49db76bf9..2fa8df06340e 100644 --- a/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs +++ b/src/Umbraco.Core/Mail/NotImplementedEmailSender.cs @@ -2,20 +2,31 @@ namespace Umbraco.Cms.Core.Mail; +/// +/// An implementation that throws for all operations. +/// +/// +/// This is the default implementation used when no custom email sender is configured. +/// To send emails, implement with a custom implementation. +/// internal sealed class NotImplementedEmailSender : IEmailSender { + /// public Task SendAsync(EmailMessage message, string emailType) => throw new NotImplementedException( "To send an Email ensure IEmailSender is implemented with a custom implementation"); + /// public Task SendAsync(EmailMessage message, string emailType, bool enableNotification) => throw new NotImplementedException( "To send an Email ensure IEmailSender is implemented with a custom implementation"); + /// public Task SendAsync(EmailMessage message, string emailType, bool enableNotification, TimeSpan? expires) => throw new NotImplementedException( "To send an Email ensure IEmailSender is implemented with a custom implementation"); + /// public bool CanSendRequiredEmail() => throw new NotImplementedException( "To send an Email ensure IEmailSender is implemented with a custom implementation"); diff --git a/src/Umbraco.Core/Mail/NotImplementedSmsSender.cs b/src/Umbraco.Core/Mail/NotImplementedSmsSender.cs index af3e0dff8b1b..49f1113e61b5 100644 --- a/src/Umbraco.Core/Mail/NotImplementedSmsSender.cs +++ b/src/Umbraco.Core/Mail/NotImplementedSmsSender.cs @@ -1,10 +1,15 @@ namespace Umbraco.Cms.Core.Mail; /// -/// An that throws +/// An that throws . /// +/// +/// This is the default implementation used when no custom SMS sender is configured. +/// To send SMS messages, implement with a custom implementation. +/// internal sealed class NotImplementedSmsSender : ISmsSender { + /// public Task SendSmsAsync(string number, string message) => throw new NotImplementedException( "To send an SMS ensure ISmsSender is implemented with a custom implementation"); diff --git a/src/Umbraco.Core/Manifest/BundleOptions.cs b/src/Umbraco.Core/Manifest/BundleOptions.cs index fe04c205d9ff..20b43c7f352c 100644 --- a/src/Umbraco.Core/Manifest/BundleOptions.cs +++ b/src/Umbraco.Core/Manifest/BundleOptions.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Manifest; +/// +/// Specifies the bundling options for assets in a package. +/// public enum BundleOptions { /// diff --git a/src/Umbraco.Core/Manifest/IPackageManifestService.cs b/src/Umbraco.Core/Manifest/IPackageManifestService.cs index e7ceededb7a2..1f4d5aaf7edf 100644 --- a/src/Umbraco.Core/Manifest/IPackageManifestService.cs +++ b/src/Umbraco.Core/Manifest/IPackageManifestService.cs @@ -1,12 +1,31 @@ -namespace Umbraco.Cms.Core.Manifest; +namespace Umbraco.Cms.Core.Manifest; +/// +/// Provides services for retrieving package manifests. +/// public interface IPackageManifestService { + /// + /// Gets all package manifests asynchronously. + /// + /// A task that represents the asynchronous operation containing all package manifests. Task> GetAllPackageManifestsAsync(); + /// + /// Gets all public package manifests asynchronously. + /// + /// A task that represents the asynchronous operation containing public package manifests that allow public access. Task> GetPublicPackageManifestsAsync(); + /// + /// Gets all private package manifests asynchronously. + /// + /// A task that represents the asynchronous operation containing private package manifests that do not allow public access. Task> GetPrivatePackageManifestsAsync(); + /// + /// Gets the combined importmap from all package manifests asynchronously. + /// + /// A task that represents the asynchronous operation containing the merged . Task GetPackageManifestImportmapAsync(); } diff --git a/src/Umbraco.Core/Manifest/PackageManifest.cs b/src/Umbraco.Core/Manifest/PackageManifest.cs index f07bbccdb51f..9746945eff80 100644 --- a/src/Umbraco.Core/Manifest/PackageManifest.cs +++ b/src/Umbraco.Core/Manifest/PackageManifest.cs @@ -1,21 +1,48 @@ namespace Umbraco.Cms.Core.Manifest; +/// +/// Represents a package manifest that defines metadata and extensions for an Umbraco package. +/// public class PackageManifest { + /// + /// Gets or sets the name of the package. + /// public required string Name { get; set; } + /// + /// Gets or sets the unique identifier of the package. + /// public string? Id { get; set; } + /// + /// Gets or sets the version of the package. + /// public string? Version { get; set; } + /// + /// Gets or sets a value indicating whether the package allows public access. + /// public bool AllowPublicAccess { get; set; } + /// + /// Gets or sets a value indicating whether the package allows telemetry collection. + /// public bool AllowTelemetry { get; set; } = true; + /// + /// Gets or sets a value indicating whether the package allows telemetry collection. + /// [Obsolete("Use AllowTelemetry instead. This property will be removed in future versions.")] public bool AllowPackageTelemetry { get; set; } = true; + /// + /// Gets or sets the array of extension objects defined by this package. + /// public required object[] Extensions { get; set; } + /// + /// Gets or sets the importmap configuration for the package. + /// public PackageManifestImportmap? Importmap { get; set; } } diff --git a/src/Umbraco.Core/Manifest/PackageManifestImportmap.cs b/src/Umbraco.Core/Manifest/PackageManifestImportmap.cs index aea9c6c12d16..b46e8a0b64c0 100644 --- a/src/Umbraco.Core/Manifest/PackageManifestImportmap.cs +++ b/src/Umbraco.Core/Manifest/PackageManifestImportmap.cs @@ -1,13 +1,22 @@ -using System.Runtime.Serialization; +using System.Runtime.Serialization; namespace Umbraco.Cms.Core.Manifest; +/// +/// Represents an import map configuration for a package manifest, used for JavaScript module resolution. +/// [DataContract(Name = "packageManifestImportmap", Namespace = "")] public class PackageManifestImportmap { + /// + /// Gets or sets the imports dictionary that maps module specifiers to URLs. + /// [DataMember(Name = "imports")] public required Dictionary Imports { get; set; } + /// + /// Gets or sets the scopes dictionary that provides scoped import mappings for specific URL prefixes. + /// [DataMember(Name = "scopes")] public Dictionary>? Scopes { get; set; } } diff --git a/src/Umbraco.Core/Mapping/IUmbracoMapper.cs b/src/Umbraco.Core/Mapping/IUmbracoMapper.cs index 4cfd976a12ac..3c40a193cade 100644 --- a/src/Umbraco.Core/Mapping/IUmbracoMapper.cs +++ b/src/Umbraco.Core/Mapping/IUmbracoMapper.cs @@ -1,5 +1,12 @@ namespace Umbraco.Cms.Core.Mapping; +/// +/// Provides object-to-object mapping functionality for Umbraco. +/// +/// +/// The mapper supports defining custom mappings between types, including constructors and mapping methods. +/// It can map single objects, map to existing objects, and map enumerables of objects. +/// public interface IUmbracoMapper { /// diff --git a/src/Umbraco.Core/Mapping/MapDefinitionCollection.cs b/src/Umbraco.Core/Mapping/MapDefinitionCollection.cs index db35a3ffac0c..7a97a24d30d2 100644 --- a/src/Umbraco.Core/Mapping/MapDefinitionCollection.cs +++ b/src/Umbraco.Core/Mapping/MapDefinitionCollection.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.Mapping; +/// +/// Represents a collection of instances used for object mapping. +/// public class MapDefinitionCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that provides the map definitions. public MapDefinitionCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/Mapping/MapDefinitionCollectionBuilder.cs b/src/Umbraco.Core/Mapping/MapDefinitionCollectionBuilder.cs index 1ac6de5b33e2..52484e5bc4ad 100644 --- a/src/Umbraco.Core/Mapping/MapDefinitionCollectionBuilder.cs +++ b/src/Umbraco.Core/Mapping/MapDefinitionCollectionBuilder.cs @@ -3,9 +3,17 @@ namespace Umbraco.Cms.Core.Mapping; +/// +/// Builds the by allowing registration of instances. +/// +/// +/// Use this builder to register custom map definitions that define how objects are mapped from one type to another. +/// public class MapDefinitionCollectionBuilder : SetCollectionBuilderBase { + /// protected override MapDefinitionCollectionBuilder This => this; + /// protected override ServiceLifetime CollectionLifetime => ServiceLifetime.Transient; } diff --git a/src/Umbraco.Core/Media/EmbedProviders/DailyMotion.cs b/src/Umbraco.Core/Media/EmbedProviders/DailyMotion.cs index 2ce637cd7b01..9ceb9029aa6a 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/DailyMotion.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/DailyMotion.cs @@ -8,21 +8,29 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class DailyMotion : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public DailyMotion(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "https://www.dailymotion.com/services/oembed"; + /// public override string[] UrlSchemeRegex => new[] { @"dailymotion.com/video/.*" }; + /// public override Dictionary RequestParams => new() { // ApiUrl/?format=xml { "format", "xml" }, }; + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) => await GetXmlBasedMarkupAsync(url, maxWidth, maxHeight, cancellationToken); } diff --git a/src/Umbraco.Core/Media/EmbedProviders/EmbedProviderBase.cs b/src/Umbraco.Core/Media/EmbedProviders/EmbedProviderBase.cs index e51005b84bd6..56f3e7df1e57 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/EmbedProviderBase.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/EmbedProviderBase.cs @@ -2,9 +2,16 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; +/// +/// Obsolete base class for embed providers. Use instead. +/// [Obsolete("Use OEmbedProviderBase instead")] public abstract class EmbedProviderBase : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. protected EmbedProviderBase(IJsonSerializer jsonSerializer) : base(jsonSerializer) { diff --git a/src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollection.cs b/src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollection.cs index 655d68b87881..795d03c121ee 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollection.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollection.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; +/// +/// Represents a collection of instances. +/// public class EmbedProvidersCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection of embed providers. public EmbedProvidersCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs b/src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs index 121785d7ebe3..99b5c8c329c8 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/EmbedProvidersCollectionBuilder.cs @@ -2,7 +2,11 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; +/// +/// Builds an by registering implementations. +/// public class EmbedProvidersCollectionBuilder : OrderedCollectionBuilderBase { + /// protected override EmbedProvidersCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/Media/EmbedProviders/Flickr.cs b/src/Umbraco.Core/Media/EmbedProviders/Flickr.cs index 4d10b9db9899..42d22d0e59ac 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/Flickr.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Flickr.cs @@ -9,17 +9,25 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class Flickr : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public Flickr(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "http://www.flickr.com/services/oembed/"; + /// public override string[] UrlSchemeRegex => new[] { @"flickr.com\/photos\/*", @"flic.kr\/p\/*" }; + /// public override Dictionary RequestParams => new(); + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) { var requestUrl = base.GetEmbedProviderUrl(url, maxWidth, maxHeight); diff --git a/src/Umbraco.Core/Media/EmbedProviders/GettyImages.cs b/src/Umbraco.Core/Media/EmbedProviders/GettyImages.cs index 5c48c31fc687..e5651ece7bcd 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/GettyImages.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/GettyImages.cs @@ -7,19 +7,28 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class GettyImages : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public GettyImages(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "http://embed.gettyimages.com/oembed"; // http://gty.im/74917285 // http://www.gettyimages.com/detail/74917285 + + /// public override string[] UrlSchemeRegex => new[] { @"gty\.im/*", @"gettyimages.com\/detail\/*" }; + /// public override Dictionary RequestParams => new(); + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) => await GetJsonBasedMarkupAsync(url, maxWidth, maxHeight, cancellationToken); } diff --git a/src/Umbraco.Core/Media/EmbedProviders/Giphy.cs b/src/Umbraco.Core/Media/EmbedProviders/Giphy.cs index 0ec933f5bec6..ab4d67439dee 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/Giphy.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Giphy.cs @@ -7,17 +7,25 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class Giphy : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public Giphy(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "https://giphy.com/services/oembed?url="; + /// public override string[] UrlSchemeRegex => new[] { @"giphy\.com/*", @"gph\.is/*" }; + /// public override Dictionary RequestParams => new(); + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) => await GetJsonBasedMarkupAsync(url, maxWidth, maxHeight, cancellationToken); } diff --git a/src/Umbraco.Core/Media/EmbedProviders/Hulu.cs b/src/Umbraco.Core/Media/EmbedProviders/Hulu.cs index fee7bb6d98f4..3eeab63f07e7 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/Hulu.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Hulu.cs @@ -7,17 +7,25 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class Hulu : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public Hulu(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "http://www.hulu.com/api/oembed.json"; + /// public override string[] UrlSchemeRegex => new[] { @"hulu.com/watch/.*" }; + /// public override Dictionary RequestParams => new(); + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) => await GetJsonBasedMarkupAsync(url, maxWidth, maxHeight, cancellationToken); } diff --git a/src/Umbraco.Core/Media/EmbedProviders/Issuu.cs b/src/Umbraco.Core/Media/EmbedProviders/Issuu.cs index c98887849c77..590433626626 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/Issuu.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Issuu.cs @@ -8,15 +8,22 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class Issuu : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public Issuu(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "https://issuu.com/oembed"; + /// public override string[] UrlSchemeRegex => new[] { @"issuu.com/.*/docs/.*" }; + /// public override Dictionary RequestParams => new() { // ApiUrl/?iframe=true @@ -26,6 +33,7 @@ public Issuu(IJsonSerializer jsonSerializer) { "format", "xml" }, }; + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) => await GetXmlBasedMarkupAsync(url, maxWidth, maxHeight, cancellationToken); } diff --git a/src/Umbraco.Core/Media/EmbedProviders/Kickstarter.cs b/src/Umbraco.Core/Media/EmbedProviders/Kickstarter.cs index ba4041c80706..510b916dc17f 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/Kickstarter.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Kickstarter.cs @@ -7,17 +7,25 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class Kickstarter : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public Kickstarter(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "http://www.kickstarter.com/services/oembed"; + /// public override string[] UrlSchemeRegex => new[] { @"kickstarter\.com/projects/*" }; + /// public override Dictionary RequestParams => new(); + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) => await GetJsonBasedMarkupAsync(url, maxWidth, maxHeight, cancellationToken); } diff --git a/src/Umbraco.Core/Media/EmbedProviders/LottieFiles.cs b/src/Umbraco.Core/Media/EmbedProviders/LottieFiles.cs index 7da886d495f4..93075e7da46f 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/LottieFiles.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/LottieFiles.cs @@ -8,17 +8,25 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class LottieFiles : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public LottieFiles(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "https://embed.lottiefiles.com/oembed"; + /// public override string[] UrlSchemeRegex => new[] { @"lottiefiles\.com/*" }; + /// public override Dictionary RequestParams => new(); + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) { var requestUrl = GetEmbedProviderUrl(url, maxWidth, maxHeight); diff --git a/src/Umbraco.Core/Media/EmbedProviders/OEmbedProviderBase.cs b/src/Umbraco.Core/Media/EmbedProviders/OEmbedProviderBase.cs index 00468a099c00..cca99c8226a0 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/OEmbedProviderBase.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/OEmbedProviderBase.cs @@ -5,23 +5,48 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; +/// +/// Abstract base class for OEmbed providers that implements the interface. +/// public abstract class OEmbedProviderBase : IEmbedProvider { private static HttpClient? _httpClient; private readonly IJsonSerializer _jsonSerializer; + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. protected OEmbedProviderBase(IJsonSerializer jsonSerializer) => _jsonSerializer = jsonSerializer; + /// public abstract string ApiEndpoint { get; } + /// public abstract string[] UrlSchemeRegex { get; } + /// public abstract Dictionary RequestParams { get; } + /// public abstract Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken); + /// + /// Gets the full OEmbed provider URL including the URL to embed and dimension constraints. + /// + /// The URL of the media to embed. + /// The maximum width, or null for no constraint. + /// The maximum height, or null for no constraint. + /// The full OEmbed provider URL with query parameters. public virtual string GetEmbedProviderUrl(string url, int? maxWidth, int? maxHeight) => GetEmbedProviderUrl(url, maxWidth ?? 0, maxHeight ?? 0); + /// + /// Gets the full OEmbed provider URL including the URL to embed and dimension constraints. + /// + /// The URL of the media to embed. + /// The maximum width, or 0 for no constraint. + /// The maximum height, or 0 for no constraint. + /// The full OEmbed provider URL with query parameters. public virtual string GetEmbedProviderUrl(string url, int maxWidth, int maxHeight) { if (Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute) == false) @@ -52,6 +77,12 @@ public virtual string GetEmbedProviderUrl(string url, int maxWidth, int maxHeigh return fullUrl.ToString(); } + /// + /// Downloads the response content from the specified URL. + /// + /// The URL to download from. + /// A cancellation token to observe while waiting for the task to complete. + /// A task that represents the asynchronous operation, containing the response content as a string. public virtual async Task DownloadResponseAsync(string url, CancellationToken cancellationToken) { if (_httpClient == null) @@ -67,6 +98,13 @@ public virtual async Task DownloadResponseAsync(string url, Cancellation } } + /// + /// Gets the JSON response from the specified URL and deserializes it to the specified type. + /// + /// The type to deserialize the response to. + /// The URL to download from. + /// A cancellation token to observe while waiting for the task to complete. + /// A task that represents the asynchronous operation, containing the deserialized response or null. public virtual async Task GetJsonResponseAsync(string url, CancellationToken cancellationToken) where T : class { @@ -74,6 +112,12 @@ public virtual async Task DownloadResponseAsync(string url, Cancellation return _jsonSerializer.Deserialize(response); } + /// + /// Gets the XML response from the specified URL. + /// + /// The URL to download from. + /// A cancellation token to observe while waiting for the task to complete. + /// A task that represents the asynchronous operation, containing the response as an . public virtual async Task GetXmlResponseAsync(string url, CancellationToken cancellationToken) { var response = await DownloadResponseAsync(url, cancellationToken); @@ -83,12 +127,26 @@ public virtual async Task GetXmlResponseAsync(string url, Cancellat return doc; } + /// + /// Gets a property value from an XML document using an XPath expression. + /// + /// The XML document. + /// The XPath expression to select the property. + /// The inner text of the selected node, or an empty string if not found. public virtual string GetXmlProperty(XmlDocument doc, string property) { XmlNode? selectSingleNode = doc.SelectSingleNode(property); return selectSingleNode != null ? selectSingleNode.InnerText : string.Empty; } + /// + /// Gets the HTML markup for embedding media using a JSON-based OEmbed response. + /// + /// The URL of the media to embed. + /// The maximum width, or null for no constraint. + /// The maximum height, or null for no constraint. + /// A cancellation token to observe while waiting for the task to complete. + /// A task that represents the asynchronous operation, containing the HTML markup or null. public virtual async Task GetJsonBasedMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) { var requestUrl = GetEmbedProviderUrl(url, maxWidth, maxHeight); @@ -97,6 +155,15 @@ public virtual string GetXmlProperty(XmlDocument doc, string property) return oembed?.GetHtml(); } + /// + /// Gets the HTML markup for embedding media using an XML-based OEmbed response. + /// + /// The URL of the media to embed. + /// The maximum width, or null for no constraint. + /// The maximum height, or null for no constraint. + /// A cancellation token to observe while waiting for the task to complete. + /// The XPath expression to select the HTML property. Defaults to "/oembed/html". + /// A task that represents the asynchronous operation, containing the HTML markup or null. public virtual async Task GetXmlBasedMarkupAsync( string url, int? maxWidth, diff --git a/src/Umbraco.Core/Media/EmbedProviders/OEmbedResponse.cs b/src/Umbraco.Core/Media/EmbedProviders/OEmbedResponse.cs index 9f0a224e7650..f3f9dd04f314 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/OEmbedResponse.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/OEmbedResponse.cs @@ -8,14 +8,26 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; [DataContract] public class OEmbedResponse : OEmbedResponseBase { - // these is only here to avoid breaking changes. In theory it should still be source code compatible to remove them. + + /// + /// Gets the thumbnail height. + /// public new double? ThumbnailHeight => base.ThumbnailHeight; + /// + /// Gets the thumbnail width. + /// public new double? ThumbnailWidth => base.ThumbnailWidth; + /// + /// Gets the height of the embedded content. + /// public new double? Height => base.Height; + /// + /// Gets the width of the embedded content. + /// public new double? Width => base.Width; } diff --git a/src/Umbraco.Core/Media/EmbedProviders/OEmbedResponseBase.cs b/src/Umbraco.Core/Media/EmbedProviders/OEmbedResponseBase.cs index c71ecb8391b5..d727711d78a3 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/OEmbedResponseBase.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/OEmbedResponseBase.cs @@ -9,45 +9,87 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; [DataContract] public abstract class OEmbedResponseBase { + /// + /// Gets or sets the resource type (e.g., "photo", "video", "link", "rich"). + /// [DataMember(Name = "type")] public string? Type { get; set; } + /// + /// Gets or sets the OEmbed version number. + /// [DataMember(Name = "version")] public string? Version { get; set; } + /// + /// Gets or sets the title of the resource. + /// [DataMember(Name = "title")] public string? Title { get; set; } + /// + /// Gets or sets the name of the author/owner of the resource. + /// [DataMember(Name = "author_name")] public string? AuthorName { get; set; } + /// + /// Gets or sets the URL of the author/owner of the resource. + /// [DataMember(Name = "author_url")] public string? AuthorUrl { get; set; } + /// + /// Gets or sets the name of the resource provider. + /// [DataMember(Name = "provider_name")] public string? ProviderName { get; set; } + /// + /// Gets or sets the URL of the resource provider. + /// [DataMember(Name = "provider_url")] public string? ProviderUrl { get; set; } + /// + /// Gets or sets the URL to a thumbnail image representing the resource. + /// [DataMember(Name = "thumbnail_url")] public string? ThumbnailUrl { get; set; } + /// + /// Gets or sets the height of the thumbnail image. + /// [DataMember(Name = "thumbnail_height")] public virtual T? ThumbnailHeight { get; set; } + /// + /// Gets or sets the width of the thumbnail image. + /// [DataMember(Name = "thumbnail_width")] public T? ThumbnailWidth { get; set; } + /// + /// Gets or sets the HTML snippet for embedding the resource. + /// [DataMember(Name = "html")] public string? Html { get; set; } + /// + /// Gets or sets the source URL of the resource (used for photo type). + /// [DataMember(Name = "url")] public string? Url { get; set; } + /// + /// Gets or sets the height of the embedded resource. + /// [DataMember(Name = "height")] public T? Height { get; set; } + /// + /// Gets or sets the width of the embedded resource. + /// [DataMember(Name = "width")] public T? Width { get; set; } diff --git a/src/Umbraco.Core/Media/EmbedProviders/Slideshare.cs b/src/Umbraco.Core/Media/EmbedProviders/Slideshare.cs index 48de83aeb3b1..57627350d1c1 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/Slideshare.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Slideshare.cs @@ -8,17 +8,25 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class Slideshare : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public Slideshare(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "http://www.slideshare.net/api/oembed/2"; + /// public override string[] UrlSchemeRegex => new[] { @"slideshare\.net/" }; + /// public override Dictionary RequestParams => new(); + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) => await GetXmlBasedMarkupAsync(url, maxWidth, maxHeight, cancellationToken); } diff --git a/src/Umbraco.Core/Media/EmbedProviders/SoundCloud.cs b/src/Umbraco.Core/Media/EmbedProviders/SoundCloud.cs index 94a82f6957a2..893bb64d7ca5 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/SoundCloud.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/SoundCloud.cs @@ -8,17 +8,25 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class Soundcloud : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public Soundcloud(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "https://soundcloud.com/oembed"; + /// public override string[] UrlSchemeRegex => new[] { @"soundcloud.com\/*" }; + /// public override Dictionary RequestParams => new(); + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) => await GetXmlBasedMarkupAsync(url, maxWidth, maxHeight, cancellationToken); } diff --git a/src/Umbraco.Core/Media/EmbedProviders/Ted.cs b/src/Umbraco.Core/Media/EmbedProviders/Ted.cs index eb3fd3d1101a..a520f5c9bb47 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/Ted.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Ted.cs @@ -8,17 +8,25 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class Ted : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public Ted(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "http://www.ted.com/talks/oembed.xml"; + /// public override string[] UrlSchemeRegex => new[] { @"ted.com\/talks\/*" }; + /// public override Dictionary RequestParams => new(); + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) => await GetXmlBasedMarkupAsync(url, maxWidth, maxHeight, cancellationToken); } diff --git a/src/Umbraco.Core/Media/EmbedProviders/Vimeo.cs b/src/Umbraco.Core/Media/EmbedProviders/Vimeo.cs index d5f85f71ddba..682f05054d20 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/Vimeo.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Vimeo.cs @@ -8,17 +8,25 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class Vimeo : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public Vimeo(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "https://vimeo.com/api/oembed.xml"; + /// public override string[] UrlSchemeRegex => new[] { @"vimeo\.com/" }; + /// public override Dictionary RequestParams => new(); + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) => await GetXmlBasedMarkupAsync(url, maxWidth, maxHeight, cancellationToken); } diff --git a/src/Umbraco.Core/Media/EmbedProviders/X.cs b/src/Umbraco.Core/Media/EmbedProviders/X.cs index 0375e53fcd18..6ed11b3e23c6 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/X.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/X.cs @@ -7,17 +7,25 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class X : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public X(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "https://publish.x.com/oembed"; + /// public override string[] UrlSchemeRegex => new[] { @"(https?:\/\/(www\.)?)(twitter|x)\.com\/.*\/status\/.*" }; + /// public override Dictionary RequestParams => new(); + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) => await GetJsonBasedMarkupAsync(url, maxWidth, maxHeight, cancellationToken); } diff --git a/src/Umbraco.Core/Media/EmbedProviders/Youtube.cs b/src/Umbraco.Core/Media/EmbedProviders/Youtube.cs index 50dd1de659f4..2b6d7b1bfa5f 100644 --- a/src/Umbraco.Core/Media/EmbedProviders/Youtube.cs +++ b/src/Umbraco.Core/Media/EmbedProviders/Youtube.cs @@ -7,21 +7,29 @@ namespace Umbraco.Cms.Core.Media.EmbedProviders; /// public class YouTube : OEmbedProviderBase { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public YouTube(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// public override string ApiEndpoint => "https://www.youtube.com/oembed"; + /// public override string[] UrlSchemeRegex => new[] { @"youtu.be/.*", @"youtube.com/watch.*", @"youtube.com/shorts/.*", @"youtube.com/live/.*" }; + /// public override Dictionary RequestParams => new() { // ApiUrl/?format=json { "format", "json" }, }; + /// public override async Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken) => await GetJsonBasedMarkupAsync(url, maxWidth, maxHeight, cancellationToken); } diff --git a/src/Umbraco.Core/Media/IEmbedProvider.cs b/src/Umbraco.Core/Media/IEmbedProvider.cs index aed82213bd67..5c88b244f275 100644 --- a/src/Umbraco.Core/Media/IEmbedProvider.cs +++ b/src/Umbraco.Core/Media/IEmbedProvider.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Media; +/// +/// Defines a provider for embedding media content from external sources using OEmbed protocol. +/// public interface IEmbedProvider { /// @@ -18,5 +21,13 @@ public interface IEmbedProvider /// ?key=value&key2=value2 Dictionary RequestParams { get; } + /// + /// Gets the HTML markup for embedding the media content from the specified URL. + /// + /// The URL of the media to embed. + /// The maximum width of the embedded content, or null for no constraint. + /// The maximum height of the embedded content, or null for no constraint. + /// A cancellation token to observe while waiting for the task to complete. + /// A task that represents the asynchronous operation, containing the HTML markup or null if unavailable. Task GetMarkupAsync(string url, int? maxWidth, int? maxHeight, CancellationToken cancellationToken); } diff --git a/src/Umbraco.Core/Media/ImageDimensionExtractorExtensions.cs b/src/Umbraco.Core/Media/ImageDimensionExtractorExtensions.cs index 64efb7e0ece9..d757793e49fe 100644 --- a/src/Umbraco.Core/Media/ImageDimensionExtractorExtensions.cs +++ b/src/Umbraco.Core/Media/ImageDimensionExtractorExtensions.cs @@ -3,6 +3,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class ImageDimensionExtractorExtensions { /// diff --git a/src/Umbraco.Core/Media/ImageUrlGeneratorExtensions.cs b/src/Umbraco.Core/Media/ImageUrlGeneratorExtensions.cs index bc75f1176a55..fccfd33cdd17 100644 --- a/src/Umbraco.Core/Media/ImageUrlGeneratorExtensions.cs +++ b/src/Umbraco.Core/Media/ImageUrlGeneratorExtensions.cs @@ -3,6 +3,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class ImageUrlGeneratorExtensions { /// diff --git a/src/Umbraco.Core/Media/NoopImageDimensionExtractor.cs b/src/Umbraco.Core/Media/NoopImageDimensionExtractor.cs index da5dc1f9ef35..b691931d586b 100644 --- a/src/Umbraco.Core/Media/NoopImageDimensionExtractor.cs +++ b/src/Umbraco.Core/Media/NoopImageDimensionExtractor.cs @@ -2,9 +2,14 @@ namespace Umbraco.Cms.Core.Media; +/// +/// A no-operation implementation of that does not extract any image dimensions. +/// public sealed class NoopImageDimensionExtractor : IImageDimensionExtractor { + /// public IEnumerable SupportedImageFileTypes { get; } = Enumerable.Empty(); + /// public Size? GetDimensions(Stream stream) => null; } diff --git a/src/Umbraco.Core/Media/NoopImageUrlGenerator.cs b/src/Umbraco.Core/Media/NoopImageUrlGenerator.cs index de2338a63226..68420665c2bc 100644 --- a/src/Umbraco.Core/Media/NoopImageUrlGenerator.cs +++ b/src/Umbraco.Core/Media/NoopImageUrlGenerator.cs @@ -2,9 +2,14 @@ namespace Umbraco.Cms.Core.Media; +/// +/// A no-operation implementation of that returns the original image URL without modifications. +/// public sealed class NoopImageUrlGenerator : IImageUrlGenerator { + /// public IEnumerable SupportedImageFileTypes { get; } = Enumerable.Empty(); + /// public string? GetImageUrl(ImageUrlGenerationOptions options) => options?.ImageUrl; } diff --git a/src/Umbraco.Core/Media/TypeDetector/JpegDetector.cs b/src/Umbraco.Core/Media/TypeDetector/JpegDetector.cs index e89d8e159d3a..ef0e7fedf677 100644 --- a/src/Umbraco.Core/Media/TypeDetector/JpegDetector.cs +++ b/src/Umbraco.Core/Media/TypeDetector/JpegDetector.cs @@ -1,7 +1,15 @@ namespace Umbraco.Cms.Core.Media.TypeDetector; +/// +/// Detects whether a file stream contains a JPEG image by examining its header bytes. +/// public class JpegDetector : RasterizedTypeDetector { + /// + /// Determines whether the specified file stream contains a JPEG image. + /// + /// The file stream to examine. + /// true if the stream contains a JPEG image; otherwise, false. public static bool IsOfType(Stream fileStream) { var header = GetFileHeader(fileStream); diff --git a/src/Umbraco.Core/Media/TypeDetector/RasterizedTypeDetector.cs b/src/Umbraco.Core/Media/TypeDetector/RasterizedTypeDetector.cs index c6793b790444..53f6fe0e8d4f 100644 --- a/src/Umbraco.Core/Media/TypeDetector/RasterizedTypeDetector.cs +++ b/src/Umbraco.Core/Media/TypeDetector/RasterizedTypeDetector.cs @@ -1,7 +1,15 @@ namespace Umbraco.Cms.Core.Media.TypeDetector; +/// +/// Base class for detecting rasterized image types by reading file headers. +/// public abstract class RasterizedTypeDetector { + /// + /// Gets the file header bytes from the specified stream. + /// + /// The file stream to read the header from. + /// The first 8 bytes of the file header, or null if the header could not be read. public static byte[]? GetFileHeader(Stream fileStream) { var header = new byte[8]; diff --git a/src/Umbraco.Core/Media/TypeDetector/SvgDetector.cs b/src/Umbraco.Core/Media/TypeDetector/SvgDetector.cs index c790806b9b3d..9a1024673e2b 100644 --- a/src/Umbraco.Core/Media/TypeDetector/SvgDetector.cs +++ b/src/Umbraco.Core/Media/TypeDetector/SvgDetector.cs @@ -2,8 +2,16 @@ namespace Umbraco.Cms.Core.Media.TypeDetector; +/// +/// Detects whether a file stream contains an SVG (Scalable Vector Graphics) image. +/// public class SvgDetector { + /// + /// Determines whether the specified file stream contains an SVG image. + /// + /// The file stream to examine. + /// true if the stream contains an SVG image; otherwise, false. public static bool IsOfType(Stream fileStream) { var document = new XDocument(); diff --git a/src/Umbraco.Core/Media/TypeDetector/TIFFDetector.cs b/src/Umbraco.Core/Media/TypeDetector/TIFFDetector.cs index 5581c81a6256..a22ef89c5d0a 100644 --- a/src/Umbraco.Core/Media/TypeDetector/TIFFDetector.cs +++ b/src/Umbraco.Core/Media/TypeDetector/TIFFDetector.cs @@ -2,14 +2,27 @@ namespace Umbraco.Cms.Core.Media.TypeDetector; +/// +/// Detects whether a file stream contains a TIFF (Tagged Image File Format) image by examining its header bytes. +/// public class TIFFDetector { + /// + /// Determines whether the specified file stream contains a TIFF image. + /// + /// The file stream to examine. + /// true if the stream contains a TIFF image; otherwise, false. public static bool IsOfType(Stream fileStream) { var tiffHeader = GetFileHeader(fileStream); return (tiffHeader != null && tiffHeader == "MM\x00\x2a") || tiffHeader == "II\x2a\x00"; } + /// + /// Gets the TIFF file header string from the specified stream. + /// + /// The file stream to read the header from. + /// The first 4 bytes of the file header as a string, or null if the header could not be read. public static string? GetFileHeader(Stream fileStream) { var header = RasterizedTypeDetector.GetFileHeader(fileStream); diff --git a/src/Umbraco.Core/Media/UploadAutoFillProperties.cs b/src/Umbraco.Core/Media/UploadAutoFillProperties.cs index 654d23135ea7..5c657bcb3917 100644 --- a/src/Umbraco.Core/Media/UploadAutoFillProperties.cs +++ b/src/Umbraco.Core/Media/UploadAutoFillProperties.cs @@ -16,6 +16,12 @@ public class UploadAutoFillProperties private readonly ILogger _logger; private readonly MediaFileManager _mediaFileManager; + /// + /// Initializes a new instance of the class. + /// + /// The media file manager. + /// The logger. + /// The image dimension extractor. public UploadAutoFillProperties( MediaFileManager mediaFileManager, ILogger logger, diff --git a/src/Umbraco.Core/Models/AuditItem.cs b/src/Umbraco.Core/Models/AuditItem.cs index cfbe676dac03..f265529c05fd 100644 --- a/src/Umbraco.Core/Models/AuditItem.cs +++ b/src/Umbraco.Core/Models/AuditItem.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents an audit log entry. +/// public sealed class AuditItem : EntityBase, IAuditItem { /// diff --git a/src/Umbraco.Core/Models/Blocks/BlockEditorData.cs b/src/Umbraco.Core/Models/Blocks/BlockEditorData.cs index 9b610f4ed21e..ca4512880adc 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockEditorData.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockEditorData.cs @@ -4,12 +4,20 @@ namespace Umbraco.Cms.Core.Models.Blocks; /// -/// Convertable block data from json +/// Represents convertible block data from JSON. /// +/// The type of the block value. +/// The type of the layout item. public class BlockEditorData where TValue : BlockValue, new() where TLayout : IBlockLayoutItem { + /// + /// Initializes a new instance of the class. + /// + /// The content and settings references. + /// The block value. + /// Thrown when references or blockValue is null. public BlockEditorData(IEnumerable references, TValue blockValue) { BlockValue = blockValue ?? throw new ArgumentNullException(nameof(blockValue)); @@ -18,20 +26,41 @@ public BlockEditorData(IEnumerable references, TVal : throw new ArgumentNullException(nameof(references)); } + /// + /// Initializes a new instance of the class. + /// private BlockEditorData() => BlockValue = new TValue(); + /// + /// Gets the empty instance of . + /// + /// + /// The empty instance. + /// public static BlockEditorData Empty { get; } = new(); /// - /// Returns the layout for this specific property editor + /// Gets the layout for this specific property editor. /// + /// + /// The layout. + /// public IEnumerable? Layout => BlockValue.GetLayouts(); /// - /// Returns the reference to the original BlockValue + /// Gets the reference to the original block value. /// + /// + /// The block value. + /// public TValue BlockValue { get; } + /// + /// Gets the content and settings references. + /// + /// + /// The references. + /// public List References { get; } = new(); } diff --git a/src/Umbraco.Core/Models/Blocks/BlockEditorDataConverter.cs b/src/Umbraco.Core/Models/Blocks/BlockEditorDataConverter.cs index c408d401004c..a2f83f1d0eae 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockEditorDataConverter.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockEditorDataConverter.cs @@ -7,17 +7,31 @@ namespace Umbraco.Cms.Core.Models.Blocks; /// -/// Converts the block json data into objects +/// Converts the block JSON data into objects. /// +/// The type of the block value. +/// The type of the layout item. public abstract class BlockEditorDataConverter where TValue : BlockValue, new() where TLayout : IBlockLayoutItem { private readonly IJsonSerializer _jsonSerializer; + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. protected BlockEditorDataConverter(IJsonSerializer jsonSerializer) => _jsonSerializer = jsonSerializer; + /// + /// Tries to deserialize the specified JSON into block editor data. + /// + /// The JSON string to deserialize. + /// When this method returns, contains the block editor data if deserialization succeeded, or null if it failed. + /// + /// true if deserialization succeeded; otherwise, false. + /// public bool TryDeserialize(string json, [MaybeNullWhen(false)] out BlockEditorData blockEditorData) { try @@ -33,6 +47,11 @@ public bool TryDeserialize(string json, [MaybeNullWhen(false)] out BlockEditorDa } } + /// + /// Deserializes the specified JSON into block editor data. + /// + /// The JSON string to deserialize. + /// The deserialized block editor data. public BlockEditorData Deserialize(string json) { TValue? value = _jsonSerializer.Deserialize(json); @@ -46,6 +65,11 @@ public BlockEditorData Deserialize(string json) /// protected abstract IEnumerable GetBlockReferences(IEnumerable layout); + /// + /// Converts the specified block value into block editor data. + /// + /// The block value to convert. + /// The converted block editor data. public BlockEditorData Convert(TValue? value) { if (value is not null) diff --git a/src/Umbraco.Core/Models/Blocks/BlockGridArea.cs b/src/Umbraco.Core/Models/Blocks/BlockGridArea.cs index 8cc2e5231b67..22b9a3d64a19 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockGridArea.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockGridArea.cs @@ -5,16 +5,19 @@ namespace Umbraco.Cms.Core.Models.Blocks; +/// +/// Represents an area within a block grid that can contain block items. +/// [DataContract(Name = "area", Namespace = "")] public class BlockGridArea : BlockModelCollection { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The list to wrap. - /// The area alias - /// The number of rows this area should span - /// The number of columns this area should span + /// The area alias. + /// The number of rows this area should span. + /// The number of columns this area should span. public BlockGridArea(IList list, string alias, int rowSpan, int columnSpan) : base(list) { Alias = alias; @@ -23,20 +26,29 @@ public BlockGridArea(IList list, string alias, int rowSpan, int c } /// - /// The area alias + /// Gets the area alias. /// + /// + /// The area alias. + /// [DataMember(Name = "alias")] public string Alias { get; } /// - /// The number of rows this area should span. + /// Gets the number of rows this area should span. /// + /// + /// The row span. + /// [DataMember(Name = "rowSpan")] public int RowSpan { get; } /// - /// The number of columns this area should span. + /// Gets the number of columns this area should span. /// + /// + /// The column span. + /// [DataMember(Name = "columnSpan")] public int ColumnSpan { get; } } diff --git a/src/Umbraco.Core/Models/Blocks/BlockGridEditorDataConverter.cs b/src/Umbraco.Core/Models/Blocks/BlockGridEditorDataConverter.cs index b2e3a1337dee..516e85462b61 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockGridEditorDataConverter.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockGridEditorDataConverter.cs @@ -6,15 +6,20 @@ namespace Umbraco.Cms.Core.Models.Blocks; /// -/// Data converter for the block grid property editor +/// Data converter for the block grid property editor. /// public class BlockGridEditorDataConverter : BlockEditorDataConverter { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public BlockGridEditorDataConverter(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// protected override IEnumerable GetBlockReferences(IEnumerable layout) { IList ExtractContentAndSettingsReferences(BlockGridLayoutItem item) diff --git a/src/Umbraco.Core/Models/Blocks/BlockGridItem.cs b/src/Umbraco.Core/Models/Blocks/BlockGridItem.cs index 8c463187e32a..6d41957a06f0 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockGridItem.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockGridItem.cs @@ -33,6 +33,14 @@ public BlockGridItem(Udi contentUdi, IPublishedElement content, Udi settingsUdi, { } + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The content. + /// The settings key. + /// The settings. + /// Thrown when content is null. public BlockGridItem(Guid contentKey, IPublishedElement content, Guid? settingsKey, IPublishedElement? settings) { ContentKey = contentKey; @@ -136,6 +144,13 @@ public BlockGridItem(Udi contentUdi, T content, Udi settingsUdi, IPublishedEleme Content = content; } + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The content. + /// The settings key. + /// The settings. public BlockGridItem(Guid contentKey, T content, Guid? settingsKey, IPublishedElement? settings) : base(contentKey, content, settingsKey, settings) { @@ -174,6 +189,13 @@ public BlockGridItem(Udi contentUdi, TContent content, Udi settingsUdi, TSetting Settings = settings; } + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The content. + /// The settings key. + /// The settings. public BlockGridItem(Guid contentKey, TContent content, Guid? settingsKey, TSettings? settings) : base(contentKey, content, settingsKey, settings) { diff --git a/src/Umbraco.Core/Models/Blocks/BlockGridLayoutAreaItem.cs b/src/Umbraco.Core/Models/Blocks/BlockGridLayoutAreaItem.cs index 5ee2c3c7aa74..d69d2f6db4dd 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockGridLayoutAreaItem.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockGridLayoutAreaItem.cs @@ -1,20 +1,56 @@ namespace Umbraco.Cms.Core.Models.Blocks; +/// +/// Represents an area item within a block grid layout. +/// public class BlockGridLayoutAreaItem { + /// + /// Gets or sets the key. + /// + /// + /// The key. + /// public Guid Key { get; set; } = Guid.Empty; + /// + /// Gets or sets the items within this area. + /// + /// + /// The items. + /// public BlockGridLayoutItem[] Items { get; set; } = Array.Empty(); + /// + /// Initializes a new instance of the class. + /// public BlockGridLayoutAreaItem() { } + /// + /// Initializes a new instance of the class. + /// + /// The key. public BlockGridLayoutAreaItem(Guid key) => Key = key; + /// + /// Determines whether this area contains content with the specified key. + /// + /// The content key to check. + /// + /// true if this area contains content with the specified key; otherwise, false. + /// public bool ContainsContent(Guid key) => Items.Any(item => item.ReferencesContent(key)); + /// + /// Determines whether this area contains settings with the specified key. + /// + /// The settings key to check. + /// + /// true if this area contains settings with the specified key; otherwise, false. + /// public bool ContainsSetting(Guid key) => Items.Any(item => item.ReferencesSetting(key)); } diff --git a/src/Umbraco.Core/Models/Blocks/BlockGridLayoutItem.cs b/src/Umbraco.Core/Models/Blocks/BlockGridLayoutItem.cs index 79ff8e40bcc7..996952e8a9f4 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockGridLayoutItem.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockGridLayoutItem.cs @@ -4,44 +4,85 @@ namespace Umbraco.Cms.Core.Models.Blocks; /// -/// Used for deserializing the block grid layout +/// Used for deserializing the block grid layout. /// public class BlockGridLayoutItem : BlockLayoutItemBase { + /// + /// Gets or sets the number of columns this item should span. + /// + /// + /// The column span. + /// public int? ColumnSpan { get; set; } + /// + /// Gets or sets the number of rows this item should span. + /// + /// + /// The row span. + /// public int? RowSpan { get; set; } + /// + /// Gets or sets the areas within this layout item. + /// + /// + /// The areas. + /// public BlockGridLayoutAreaItem[] Areas { get; set; } = Array.Empty(); + /// + /// Initializes a new instance of the class. + /// public BlockGridLayoutItem() { } + /// + /// Initializes a new instance of the class. + /// + /// The content UDI. [Obsolete("Use constructor that accepts GUIDs instead. Will be removed in V18.")] public BlockGridLayoutItem(Udi contentUdi) : base(contentUdi) { } + /// + /// Initializes a new instance of the class. + /// + /// The content UDI. + /// The settings UDI. [Obsolete("Use constructor that accepts GUIDs instead. Will be removed in V18.")] public BlockGridLayoutItem(Udi contentUdi, Udi settingsUdi) : base(contentUdi, settingsUdi) { } + /// + /// Initializes a new instance of the class. + /// + /// The content key. public BlockGridLayoutItem(Guid contentKey) : base(contentKey) { } + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The settings key. public BlockGridLayoutItem(Guid contentKey, Guid settingsKey) : base(contentKey, settingsKey) { } + /// public override bool ReferencesContent(Guid key) => ContentKey == key || Areas.Any(area => area.ContainsContent(key)); + /// public override bool ReferencesSetting(Guid key) => SettingsKey == key || Areas.Any(area => area.ContainsSetting(key)); } diff --git a/src/Umbraco.Core/Models/Blocks/BlockItemData.cs b/src/Umbraco.Core/Models/Blocks/BlockItemData.cs index e99e8010e7e2..aae5167b3c40 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockItemData.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockItemData.cs @@ -6,14 +6,23 @@ namespace Umbraco.Cms.Core.Models.Blocks; /// -/// Represents a single block's data in raw form +/// Represents a single block's data in raw form. /// public class BlockItemData { + /// + /// Initializes a new instance of the class. + /// public BlockItemData() { } + /// + /// Initializes a new instance of the class. + /// + /// The UDI. + /// The content type key. + /// The content type alias. [Obsolete("Use constructor that accepts GUID key instead. Will be removed in V18.")] public BlockItemData(Udi udi, Guid contentTypeKey, string contentTypeAlias) : this( @@ -23,6 +32,12 @@ public BlockItemData(Udi udi, Guid contentTypeKey, string contentTypeAlias) { } + /// + /// Initializes a new instance of the class. + /// + /// The key. + /// The content type key. + /// The content type alias. public BlockItemData(Guid key, Guid contentTypeKey, string contentTypeAlias) { ContentTypeAlias = contentTypeAlias; @@ -31,21 +46,54 @@ public BlockItemData(Guid key, Guid contentTypeKey, string contentTypeAlias) ContentTypeKey = contentTypeKey; } + /// + /// Gets or sets the content type key. + /// + /// + /// The content type key. + /// public Guid ContentTypeKey { get; set; } /// - /// not serialized, manually set and used during internally + /// Gets or sets the content type alias. /// + /// + /// Not serialized, manually set and used internally. + /// [JsonIgnore] public string ContentTypeAlias { get; set; } = string.Empty; + /// + /// Gets or sets the UDI. + /// + /// + /// The UDI. + /// [Obsolete("Use Key instead. Will be removed in V18.")] public Udi? Udi { get; set; } + /// + /// Gets or sets the key. + /// + /// + /// The key. + /// public Guid Key { get; set; } + /// + /// Gets or sets the property values. + /// + /// + /// The property values. + /// public IList Values { get; set; } = new List(); + /// + /// Gets or sets the raw property values. + /// + /// + /// The raw property values. + /// [Obsolete("Use Properties instead. Will be removed in V18.")] [JsonExtensionData] public Dictionary RawPropertyValues { get; set; } = new(); diff --git a/src/Umbraco.Core/Models/Blocks/BlockItemVariation.cs b/src/Umbraco.Core/Models/Blocks/BlockItemVariation.cs index bb8dfcff2298..afde6e7cc50d 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockItemVariation.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockItemVariation.cs @@ -1,11 +1,23 @@ -namespace Umbraco.Cms.Core.Models.Blocks; +namespace Umbraco.Cms.Core.Models.Blocks; +/// +/// Represents a block item variation for culture and segment. +/// public class BlockItemVariation { + /// + /// Initializes a new instance of the class. + /// public BlockItemVariation() { } + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The culture. + /// The segment. public BlockItemVariation(Guid contentKey, string? culture, string? segment) { ContentKey = contentKey; @@ -13,9 +25,27 @@ public BlockItemVariation(Guid contentKey, string? culture, string? segment) Segment = segment; } + /// + /// Gets or sets the content key. + /// + /// + /// The content key. + /// public Guid ContentKey { get; set; } + /// + /// Gets or sets the culture. + /// + /// + /// The culture. + /// public string? Culture { get; set; } + /// + /// Gets or sets the segment. + /// + /// + /// The segment. + /// public string? Segment { get; set; } } diff --git a/src/Umbraco.Core/Models/Blocks/BlockLayoutItemBase.cs b/src/Umbraco.Core/Models/Blocks/BlockLayoutItemBase.cs index 154de1618c83..dd9c26adef02 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockLayoutItemBase.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockLayoutItemBase.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.Blocks; +namespace Umbraco.Cms.Core.Models.Blocks; +/// +/// Base class for block layout items. +/// public abstract class BlockLayoutItemBase : IBlockLayoutItem { private Guid? _contentKey; @@ -8,6 +11,7 @@ public abstract class BlockLayoutItemBase : IBlockLayoutItem private Udi? _contentUdi; private Udi? _settingsUdi; + /// [Obsolete("Use ContentKey instead. Will be removed in V18.")] public Udi? ContentUdi { @@ -24,6 +28,7 @@ public Udi? ContentUdi } } + /// [Obsolete("Use SettingsKey instead. Will be removed in V18.")] public Udi? SettingsUdi { @@ -40,27 +45,41 @@ public Udi? SettingsUdi } } + /// public Guid ContentKey { get => _contentKey ?? throw new InvalidOperationException("ContentKey has not yet been initialized"); set => _contentKey = value; } + /// public Guid? SettingsKey { get => _settingsKey; set => _settingsKey = value; } + /// + /// Initializes a new instance of the class. + /// protected BlockLayoutItemBase() { } + /// + /// Initializes a new instance of the class. + /// + /// The content UDI. [Obsolete("Use constructor that accepts GUIDs instead. Will be removed in V18.")] protected BlockLayoutItemBase(Udi contentUdi) : this((contentUdi as GuidUdi)?.Guid ?? throw new ArgumentException(nameof(contentUdi))) { } + /// + /// Initializes a new instance of the class. + /// + /// The content UDI. + /// The settings UDI. [Obsolete("Use constructor that accepts GUIDs instead. Will be removed in V18.")] protected BlockLayoutItemBase(Udi contentUdi, Udi settingsUdi) : this( @@ -69,12 +88,21 @@ protected BlockLayoutItemBase(Udi contentUdi, Udi settingsUdi) { } + /// + /// Initializes a new instance of the class. + /// + /// The content key. protected BlockLayoutItemBase(Guid contentKey) { ContentKey = contentKey; ContentUdi = new GuidUdi(Constants.UdiEntityType.Element, contentKey); } + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The settings key. protected BlockLayoutItemBase(Guid contentKey, Guid settingsKey) : this(contentKey) { @@ -82,9 +110,11 @@ protected BlockLayoutItemBase(Guid contentKey, Guid settingsKey) SettingsUdi = new GuidUdi(Constants.UdiEntityType.Element, settingsKey); } + /// public virtual bool ReferencesContent(Guid key) => ContentKey == key; + /// public virtual bool ReferencesSetting(Guid key) => SettingsKey == key; } diff --git a/src/Umbraco.Core/Models/Blocks/BlockListEditorDataConverter.cs b/src/Umbraco.Core/Models/Blocks/BlockListEditorDataConverter.cs index e213be5f127e..02d6380faff2 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockListEditorDataConverter.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockListEditorDataConverter.cs @@ -6,15 +6,20 @@ namespace Umbraco.Cms.Core.Models.Blocks; /// -/// Data converter for the block list property editor +/// Data converter for the block list property editor. /// public class BlockListEditorDataConverter : BlockEditorDataConverter { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public BlockListEditorDataConverter(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// protected override IEnumerable GetBlockReferences(IEnumerable layout) => layout.Select(x => new ContentAndSettingsReference(x.ContentKey, x.SettingsKey)).ToList(); } diff --git a/src/Umbraco.Core/Models/Blocks/BlockListItem.cs b/src/Umbraco.Core/Models/Blocks/BlockListItem.cs index 7e14a1b1e8c5..ebd482ac1025 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockListItem.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockListItem.cs @@ -35,6 +35,14 @@ public BlockListItem(Udi contentUdi, IPublishedElement content, Udi settingsUdi, { } + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The content. + /// The settings key. + /// The settings. + /// Thrown when content is null. public BlockListItem(Guid contentKey, IPublishedElement content, Guid? settingsKey, IPublishedElement? settings) { ContentKey = contentKey; @@ -112,6 +120,13 @@ public BlockListItem(Udi contentUdi, T content, Udi settingsUdi, IPublishedEleme : base(contentUdi, content, settingsUdi, settings) => Content = content; + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The content. + /// The settings key. + /// The settings. public BlockListItem(Guid contentKey, T content, Guid? settingsKey, IPublishedElement? settings) : base(contentKey, content, settingsKey, settings) => Content = content; @@ -147,6 +162,13 @@ public BlockListItem(Udi contentUdi, TContent content, Udi settingsUdi, TSetting : base(contentUdi, content, settingsUdi, settings) => Settings = settings; + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The content. + /// The settings key. + /// The settings. public BlockListItem(Guid contentKey, TContent content, Guid? settingsKey, TSettings? settings) : base(contentKey, content, settingsKey, settings) => Settings = settings; diff --git a/src/Umbraco.Core/Models/Blocks/BlockListLayoutItem.cs b/src/Umbraco.Core/Models/Blocks/BlockListLayoutItem.cs index cffa234156aa..55c7f0f1eee3 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockListLayoutItem.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockListLayoutItem.cs @@ -4,30 +4,51 @@ namespace Umbraco.Cms.Core.Models.Blocks; /// -/// Used for deserializing the block list layout +/// Used for deserializing the block list layout. /// public class BlockListLayoutItem : BlockLayoutItemBase { + /// + /// Initializes a new instance of the class. + /// public BlockListLayoutItem() { } + /// + /// Initializes a new instance of the class. + /// + /// The content UDI. [Obsolete("Use constructor that accepts GUIDs instead. Will be removed in V18.")] public BlockListLayoutItem(Udi contentUdi) : base(contentUdi) { } + /// + /// Initializes a new instance of the class. + /// + /// The content UDI. + /// The settings UDI. [Obsolete("Use constructor that accepts GUIDs instead. Will be removed in V18.")] public BlockListLayoutItem(Udi contentUdi, Udi settingsUdi) : base(contentUdi, settingsUdi) { } + /// + /// Initializes a new instance of the class. + /// + /// The content key. public BlockListLayoutItem(Guid contentKey) : base(contentKey) { } + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The settings key. public BlockListLayoutItem(Guid contentKey, Guid settingsKey) : base(contentKey, settingsKey) { diff --git a/src/Umbraco.Core/Models/Blocks/BlockModelCollection.cs b/src/Umbraco.Core/Models/Blocks/BlockModelCollection.cs index 22442847408a..1f139cb56637 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockModelCollection.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockModelCollection.cs @@ -6,35 +6,42 @@ namespace Umbraco.Cms.Core.Models.Blocks; +/// +/// Represents a read-only collection of block items. +/// +/// The type of block item. public abstract class BlockModelCollection : ReadOnlyCollection where T : class, IBlockReference { + /// + /// Initializes a new instance of the class. + /// + /// The list to wrap. protected BlockModelCollection(IList list) : base(list) { } - /// - /// Gets the with the specified content key. + /// Gets the block item with the specified content key. /// /// - /// The . + /// The block item. /// /// The content key. /// - /// The with the specified content key. + /// The block item with the specified content key. /// public T? this[Guid contentKey] => this.FirstOrDefault(x => x.Content.Key == contentKey); /// - /// Gets the with the specified content UDI. + /// Gets the block item with the specified content UDI. /// /// - /// The . + /// The block item. /// /// The content UDI. /// - /// The with the specified content UDI. + /// The block item with the specified content UDI. /// public T? this[Udi contentUdi] => contentUdi is GuidUdi guidUdi ? this.FirstOrDefault(x => x.Content.Key == guidUdi.Guid) diff --git a/src/Umbraco.Core/Models/Blocks/BlockPropertyValue.cs b/src/Umbraco.Core/Models/Blocks/BlockPropertyValue.cs index 0b27f1668181..cbebd908b504 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockPropertyValue.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockPropertyValue.cs @@ -3,11 +3,25 @@ namespace Umbraco.Cms.Core.Models.Blocks; +/// +/// Represents a property value within a block item. +/// public sealed class BlockPropertyValue : ValueModelBase { - // Used during deserialization to populate the property value/property type of a block item content property + /// + /// Gets or sets the property type. + /// + /// + /// Used during deserialization to populate the property value/property type of a block item content property. + /// [JsonIgnore] public IPropertyType? PropertyType { get; set; } + /// + /// Gets the property editor alias. + /// + /// + /// The property editor alias. + /// public string? EditorAlias => PropertyType?.PropertyEditorAlias; } diff --git a/src/Umbraco.Core/Models/Blocks/BlockValue.cs b/src/Umbraco.Core/Models/Blocks/BlockValue.cs index 1c25c8d434e1..0dab50caf681 100644 --- a/src/Umbraco.Core/Models/Blocks/BlockValue.cs +++ b/src/Umbraco.Core/Models/Blocks/BlockValue.cs @@ -48,11 +48,21 @@ public abstract class BlockValue /// public abstract string PropertyEditorAlias { get; } + /// + /// Determines whether the specified block layout alias is supported. + /// + /// The block layout alias. + /// + /// true if the specified block layout alias is supported; otherwise, false. + /// [Obsolete("Will be removed in V18.")] public virtual bool SupportsBlockLayoutAlias(string alias) => alias.Equals(PropertyEditorAlias); } -/// +/// +/// Represents a block value with a specific layout type. +/// +/// The type of the layout item. public abstract class BlockValue : BlockValue where TLayout : IBlockLayoutItem { diff --git a/src/Umbraco.Core/Models/Blocks/ContentAndSettingsReference.cs b/src/Umbraco.Core/Models/Blocks/ContentAndSettingsReference.cs index f26db3b46d56..51d883f8c8ea 100644 --- a/src/Umbraco.Core/Models/Blocks/ContentAndSettingsReference.cs +++ b/src/Umbraco.Core/Models/Blocks/ContentAndSettingsReference.cs @@ -3,8 +3,16 @@ namespace Umbraco.Cms.Core.Models.Blocks; +/// +/// Represents a reference to block content and settings data. +/// public struct ContentAndSettingsReference : IEquatable { + /// + /// Initializes a new instance of the struct. + /// + /// The content UDI. + /// The settings UDI. [Obsolete("Use constructor that accepts GUIDs instead. Will be removed in V18.")] public ContentAndSettingsReference(Udi? contentUdi, Udi? settingsUdi) : this( @@ -13,6 +21,11 @@ public ContentAndSettingsReference(Udi? contentUdi, Udi? settingsUdi) { } + /// + /// Initializes a new instance of the struct. + /// + /// The content key. + /// The settings key. public ContentAndSettingsReference(Guid contentKey, Guid? settingsKey) { ContentKey = contentKey; @@ -23,21 +36,55 @@ public ContentAndSettingsReference(Guid contentKey, Guid? settingsKey) : null; } + /// + /// Gets the content UDI. + /// + /// + /// The content UDI. + /// [Obsolete("Use ContentKey instead. Will be removed in V18.")] public Udi ContentUdi { get; } + /// + /// Gets the settings UDI. + /// + /// + /// The settings UDI. + /// [Obsolete("Use SettingsKey instead. Will be removed in V18.")] public Udi? SettingsUdi { get; } + /// + /// Gets or sets the content key. + /// + /// + /// The content key. + /// public Guid ContentKey { get; set; } + /// + /// Gets or sets the settings key. + /// + /// + /// The settings key. + /// public Guid? SettingsKey { get; set; } + /// + /// Determines whether two instances are equal. + /// + /// The left instance. + /// The right instance. + /// + /// true if the instances are equal; otherwise, false. + /// public static bool operator ==(ContentAndSettingsReference left, ContentAndSettingsReference right) => left.Equals(right); + /// public override bool Equals(object? obj) => obj is ContentAndSettingsReference reference && Equals(reference); + /// public bool Equals(ContentAndSettingsReference other) => other != null && EqualityComparer.Default.Equals( ContentUdi, @@ -46,8 +93,17 @@ public bool Equals(ContentAndSettingsReference other) => other != null SettingsUdi, other.SettingsUdi); + /// public override int GetHashCode() => (ContentUdi, SettingsUdi).GetHashCode(); + /// + /// Determines whether two instances are not equal. + /// + /// The left instance. + /// The right instance. + /// + /// true if the instances are not equal; otherwise, false. + /// public static bool operator !=(ContentAndSettingsReference left, ContentAndSettingsReference right) => !(left == right); } diff --git a/src/Umbraco.Core/Models/Blocks/IBlockLayoutItem.cs b/src/Umbraco.Core/Models/Blocks/IBlockLayoutItem.cs index a67b0983d6d2..bcd4589214dc 100644 --- a/src/Umbraco.Core/Models/Blocks/IBlockLayoutItem.cs +++ b/src/Umbraco.Core/Models/Blocks/IBlockLayoutItem.cs @@ -3,19 +3,60 @@ namespace Umbraco.Cms.Core.Models.Blocks; +/// +/// Represents a layout item for a block editor. +/// public interface IBlockLayoutItem { + /// + /// Gets or sets the content UDI. + /// + /// + /// The content UDI. + /// [Obsolete("Use ContentKey instead. Will be removed in V18.")] public Udi? ContentUdi { get; set; } + /// + /// Gets or sets the settings UDI. + /// + /// + /// The settings UDI. + /// [Obsolete("Use SettingsKey instead. Will be removed in V18.")] public Udi? SettingsUdi { get; set; } + /// + /// Gets or sets the content key. + /// + /// + /// The content key. + /// public Guid ContentKey { get; set; } + /// + /// Gets or sets the settings key. + /// + /// + /// The settings key. + /// public Guid? SettingsKey { get; set; } + /// + /// Determines whether this layout item references the specified content key. + /// + /// The content key to check. + /// + /// true if this layout item references the specified content key; otherwise, false. + /// public bool ReferencesContent(Guid key) => ContentKey == key; + /// + /// Determines whether this layout item references the specified settings key. + /// + /// The settings key to check. + /// + /// true if this layout item references the specified settings key; otherwise, false. + /// public bool ReferencesSetting(Guid key) => SettingsKey == key; } diff --git a/src/Umbraco.Core/Models/Blocks/RichTextBlockItem.cs b/src/Umbraco.Core/Models/Blocks/RichTextBlockItem.cs index 17abbe1d90c8..971488f5fb0a 100644 --- a/src/Umbraco.Core/Models/Blocks/RichTextBlockItem.cs +++ b/src/Umbraco.Core/Models/Blocks/RichTextBlockItem.cs @@ -1,4 +1,4 @@ -// Copyright (c) Umbraco. +// Copyright (c) Umbraco. // See LICENSE for more details. using System.Runtime.Serialization; @@ -35,6 +35,14 @@ public RichTextBlockItem(Udi contentUdi, IPublishedElement content, Udi settings { } + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The content. + /// The settings key. + /// The settings. + /// Thrown when content is null. public RichTextBlockItem(Guid contentKey, IPublishedElement content, Guid? settingsKey, IPublishedElement? settings) { ContentKey = contentKey; @@ -47,8 +55,20 @@ public RichTextBlockItem(Guid contentKey, IPublishedElement content, Guid? setti Settings = settings; } + /// + /// Gets or sets the content key. + /// + /// + /// The content key. + /// public Guid ContentKey { get; set; } + /// + /// Gets or sets the settings key. + /// + /// + /// The settings key. + /// public Guid? SettingsKey { get; set; } /// @@ -106,6 +126,13 @@ public RichTextBlockItem(Udi contentUdi, T content, Udi settingsUdi, IPublishedE : base(contentUdi, content, settingsUdi, settings) => Content = content; + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The content. + /// The settings key. + /// The settings. public RichTextBlockItem(Guid contentKey, T content, Guid? settingsKey, IPublishedElement? settings) : base(contentKey, content, settingsKey, settings) => Content = content; @@ -141,6 +168,13 @@ public RichTextBlockItem(Udi contentUdi, TContent content, Udi settingsUdi, TSet : base(contentUdi, content, settingsUdi, settings) => Settings = settings; + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The content. + /// The settings key. + /// The settings. public RichTextBlockItem(Guid contentKey, TContent content, Guid? settingsKey, TSettings? settings) : base(contentKey, content, settingsKey, settings) => Settings = settings; diff --git a/src/Umbraco.Core/Models/Blocks/RichTextBlockLayoutItem.cs b/src/Umbraco.Core/Models/Blocks/RichTextBlockLayoutItem.cs index 57d69003a184..2413a4ed88aa 100644 --- a/src/Umbraco.Core/Models/Blocks/RichTextBlockLayoutItem.cs +++ b/src/Umbraco.Core/Models/Blocks/RichTextBlockLayoutItem.cs @@ -4,30 +4,51 @@ namespace Umbraco.Cms.Core.Models.Blocks; /// -/// Used for deserializing the rich text block layouts +/// Used for deserializing the rich text block layouts. /// public class RichTextBlockLayoutItem : BlockLayoutItemBase { + /// + /// Initializes a new instance of the class. + /// public RichTextBlockLayoutItem() { } + /// + /// Initializes a new instance of the class. + /// + /// The content UDI. [Obsolete("Use constructor that accepts GUIDs instead. Will be removed in V18.")] public RichTextBlockLayoutItem(Udi contentUdi) : base(contentUdi) { } + /// + /// Initializes a new instance of the class. + /// + /// The content UDI. + /// The settings UDI. [Obsolete("Use constructor that accepts GUIDs instead. Will be removed in V18.")] public RichTextBlockLayoutItem(Udi contentUdi, Udi settingsUdi) : base(contentUdi, settingsUdi) { } + /// + /// Initializes a new instance of the class. + /// + /// The content key. public RichTextBlockLayoutItem(Guid contentKey) : base(contentKey) { } + /// + /// Initializes a new instance of the class. + /// + /// The content key. + /// The settings key. public RichTextBlockLayoutItem(Guid contentKey, Guid settingsKey) : base(contentKey, settingsKey) { diff --git a/src/Umbraco.Core/Models/Blocks/RichTextEditorBlockDataConverter.cs b/src/Umbraco.Core/Models/Blocks/RichTextEditorBlockDataConverter.cs index 508b55202c03..cde00934b60b 100644 --- a/src/Umbraco.Core/Models/Blocks/RichTextEditorBlockDataConverter.cs +++ b/src/Umbraco.Core/Models/Blocks/RichTextEditorBlockDataConverter.cs @@ -1,17 +1,22 @@ -using Umbraco.Cms.Core.Serialization; +using Umbraco.Cms.Core.Serialization; namespace Umbraco.Cms.Core.Models.Blocks; /// -/// Data converter for blocks in the richtext property editor +/// Data converter for blocks in the richtext property editor. /// public sealed class RichTextEditorBlockDataConverter : BlockEditorDataConverter { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public RichTextEditorBlockDataConverter(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// protected override IEnumerable GetBlockReferences(IEnumerable layout) => layout.Select(x => new ContentAndSettingsReference(x.ContentKey, x.SettingsKey)).ToList(); } diff --git a/src/Umbraco.Core/Models/Blocks/SingleBlockEditorDataConverter.cs b/src/Umbraco.Core/Models/Blocks/SingleBlockEditorDataConverter.cs index 6d1911f337c3..ea5ab7fb4ab1 100644 --- a/src/Umbraco.Core/Models/Blocks/SingleBlockEditorDataConverter.cs +++ b/src/Umbraco.Core/Models/Blocks/SingleBlockEditorDataConverter.cs @@ -3,15 +3,20 @@ namespace Umbraco.Cms.Core.Models.Blocks; /// -/// Data converter for the single block property editor +/// Data converter for the single block property editor. /// public class SingleBlockEditorDataConverter : BlockEditorDataConverter { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public SingleBlockEditorDataConverter(IJsonSerializer jsonSerializer) : base(jsonSerializer) { } + /// protected override IEnumerable GetBlockReferences(IEnumerable layout) => layout.Select(x => new ContentAndSettingsReference(x.ContentKey, x.SettingsKey)).ToList(); } diff --git a/src/Umbraco.Core/Models/Blocks/SingleBlockLayoutItem.cs b/src/Umbraco.Core/Models/Blocks/SingleBlockLayoutItem.cs index aa405cb1f369..65f4337c89e6 100644 --- a/src/Umbraco.Core/Models/Blocks/SingleBlockLayoutItem.cs +++ b/src/Umbraco.Core/Models/Blocks/SingleBlockLayoutItem.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Models.Blocks; +/// +/// Represents a layout item for a single block property editor. +/// public class SingleBlockLayoutItem : BlockLayoutItemBase { } diff --git a/src/Umbraco.Core/Models/CacheEntrySettings.cs b/src/Umbraco.Core/Models/CacheEntrySettings.cs index e0015505ab68..3fdea3c37c70 100644 --- a/src/Umbraco.Core/Models/CacheEntrySettings.cs +++ b/src/Umbraco.Core/Models/CacheEntrySettings.cs @@ -1,19 +1,59 @@ -using System.ComponentModel; +using System.ComponentModel; namespace Umbraco.Cms.Core.Models; +/// +/// Represents configuration settings for cache entry durations. +/// +/// +/// This class defines the time-to-live (TTL) settings for different cache layers +/// including local (in-memory), remote (distributed), and seed caches. +/// public class CacheEntrySettings { + /// + /// The default duration for local cache entries (1 day). + /// internal const string StaticLocalCacheDuration = "1.00:00:00"; + + /// + /// The default duration for remote cache entries (365 days). + /// internal const string StaticRemoteCacheDuration = "365.00:00:00"; + + /// + /// The default duration for seed cache entries (365 days). + /// internal const string StaticSeedCacheDuration = "365.00:00:00"; + /// + /// Gets or sets the duration that items remain in the local (in-memory) cache. + /// + /// + /// The local cache duration. Defaults to 1 day. + /// [DefaultValue(StaticLocalCacheDuration)] public TimeSpan LocalCacheDuration { get; set; } = TimeSpan.Parse(StaticLocalCacheDuration); + /// + /// Gets or sets the duration that items remain in the remote (distributed) cache. + /// + /// + /// The remote cache duration. Defaults to 365 days. + /// [DefaultValue(StaticRemoteCacheDuration)] public TimeSpan RemoteCacheDuration { get; set; } = TimeSpan.Parse(StaticRemoteCacheDuration); + /// + /// Gets or sets the duration that items remain in the seed cache. + /// + /// + /// The seed cache duration. Defaults to 365 days. + /// + /// + /// The seed cache is used during application startup to pre-populate the cache + /// with frequently accessed content. + /// [DefaultValue(StaticSeedCacheDuration)] public TimeSpan SeedCacheDuration { get; set; } = TimeSpan.Parse(StaticSeedCacheDuration); diff --git a/src/Umbraco.Core/Models/CacheSettings.cs b/src/Umbraco.Core/Models/CacheSettings.cs index 94cf80b4d65c..d6f9dc4e1bb7 100644 --- a/src/Umbraco.Core/Models/CacheSettings.cs +++ b/src/Umbraco.Core/Models/CacheSettings.cs @@ -3,12 +3,35 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents configuration settings for the Umbraco content and media cache. +/// +/// +/// This class configures cache seeding behavior and cache entry durations for +/// documents and media items. Cache seeding pre-populates the cache during +/// application startup for improved performance. +/// [UmbracoOptions(Constants.Configuration.ConfigCache)] public class CacheSettings { + /// + /// The default number of documents to seed using breadth-first traversal. + /// internal const int StaticDocumentBreadthFirstSeedCount = 100; + + /// + /// The default number of media items to seed using breadth-first traversal. + /// internal const int StaticMediaBreadthFirstSeedCount = 100; + + /// + /// The default batch size for seeding documents. + /// internal const int StaticDocumentSeedBatchSize = 100; + + /// + /// The default batch size for seeding media items. + /// internal const int StaticMediaSeedBatchSize = 100; /// @@ -41,12 +64,24 @@ public class CacheSettings [DefaultValue(StaticMediaSeedBatchSize)] public int MediaSeedBatchSize { get; set; } = StaticMediaSeedBatchSize; + /// + /// Gets or sets the cache entry settings for documents and media. + /// public CacheEntry Entry { get; set; } = new CacheEntry(); + /// + /// Represents cache entry settings for documents and media items. + /// public class CacheEntry { + /// + /// Gets or sets the cache entry settings for documents. + /// public CacheEntrySettings Document { get; set; } = new CacheEntrySettings(); + /// + /// Gets or sets the cache entry settings for media items. + /// public CacheEntrySettings Media { get; set; } = new CacheEntrySettings(); } } diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index 880c7b6bd00e..894775838440 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -168,6 +168,7 @@ public PublishedState PublishedState } } + /// [IgnoreDataMember] public bool Edited { get; set; } @@ -285,12 +286,15 @@ public ContentCultureInfosCollection? PublishCultureInfos return _publishInfos.TryGetValue(culture, out ContentCultureInfos infos) ? infos.Date : null; } + /// [IgnoreDataMember] public int PublishedVersionId { get; set; } + /// [DataMember] public bool Blueprint { get; set; } + /// public override void ResetWereDirtyProperties() { base.ResetWereDirtyProperties(); @@ -299,6 +303,7 @@ public override void ResetWereDirtyProperties() _previousPublishCultureChanges.addedCultures = null; } + /// public override void ResetDirtyProperties(bool rememberDirty) { base.ResetDirtyProperties(rememberDirty); @@ -523,6 +528,7 @@ internal void ChangeContentType(IContentType contentType, bool clearProperties) Properties.CollectionChanged += PropertiesChanged; } + /// protected override void PerformDeepClone(object clone) { base.PerformDeepClone(clone); diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs index 2bb9c1543fce..5a5ca0f429bd 100644 --- a/src/Umbraco.Core/Models/ContentBase.cs +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -64,11 +64,14 @@ private ContentBase(string? name, IContentTypeComposition? contentType, IPropert _properties.EnsurePropertyTypes(contentType.CompositionPropertyTypes); } + /// + /// Gets the simple content type information for this content. + /// [IgnoreDataMember] public ISimpleContentType ContentType { get; private set; } /// - /// Id of the user who wrote/updated this entity + /// Gets or sets the identifier of the user who wrote/updated this entity. /// [DataMember] public int WriterId @@ -77,6 +80,9 @@ public int WriterId set => SetPropertyValueAndDetectChanges(value, ref _writerId, nameof(WriterId)); } + /// + /// Gets or sets the version identifier. + /// [IgnoreDataMember] public int VersionId { get; set; } @@ -123,12 +129,21 @@ public IPropertyCollection Properties } } + /// + /// Changes the content type of this content. + /// + /// The new content type. public void ChangeContentType(ISimpleContentType contentType) { ContentType = contentType; ContentTypeId = contentType.Id; } + /// + /// Handles changes to the properties collection. + /// + /// The source of the event. + /// The event arguments. protected void PropertiesChanged(object? sender, NotifyCollectionChangedEventArgs e) => OnPropertyChanged(nameof(Properties)); @@ -183,13 +198,39 @@ protected override void PerformDeepClone(object clone) private (HashSet? addedCultures, HashSet? removedCultures, HashSet? updatedCultures) _previousCultureChanges; + /// + /// Contains prefix constants used for culture change tracking. + /// public static class ChangeTrackingPrefix { + /// + /// Prefix for tracking updated cultures. + /// public const string UpdatedCulture = "_updatedCulture_"; + + /// + /// Prefix for tracking changed cultures. + /// public const string ChangedCulture = "_changedCulture_"; + + /// + /// Prefix for tracking published cultures. + /// public const string PublishedCulture = "_publishedCulture_"; + + /// + /// Prefix for tracking unpublished cultures. + /// public const string UnpublishedCulture = "_unpublishedCulture_"; + + /// + /// Prefix for tracking added cultures. + /// public const string AddedCulture = "_addedCulture_"; + + /// + /// Prefix for tracking removed cultures. + /// public const string RemovedCulture = "_removedCulture_"; } @@ -486,6 +527,7 @@ public void RemoveValue(string propertyTypeAlias) #region Dirty + /// public override void ResetWereDirtyProperties() { base.ResetWereDirtyProperties(); diff --git a/src/Umbraco.Core/Models/ContentDataIntegrityReport.cs b/src/Umbraco.Core/Models/ContentDataIntegrityReport.cs index f4ad0b0dfcef..0c4cd22aabcc 100644 --- a/src/Umbraco.Core/Models/ContentDataIntegrityReport.cs +++ b/src/Umbraco.Core/Models/ContentDataIntegrityReport.cs @@ -1,10 +1,20 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a report of data integrity issues detected in content data. +/// public class ContentDataIntegrityReport { + /// + /// Initializes a new instance of the class. + /// + /// A dictionary of detected issues keyed by content ID. public ContentDataIntegrityReport(IReadOnlyDictionary detectedIssues) => DetectedIssues = detectedIssues; + /// + /// Defines the types of data integrity issues that can be detected. + /// public enum IssueType { /// @@ -33,10 +43,19 @@ public enum IssueType InvalidPathByParentId, } + /// + /// Gets a value indicating whether all detected issues have been resolved or no issues were found. + /// public bool Ok => DetectedIssues.Count == 0 || DetectedIssues.Count == DetectedIssues.Values.Count(x => x.Fixed); + /// + /// Gets a dictionary of all detected data integrity issues keyed by content ID. + /// public IReadOnlyDictionary DetectedIssues { get; } + /// + /// Gets a dictionary of issues that have been successfully fixed, keyed by content ID. + /// public IReadOnlyDictionary FixedIssues => DetectedIssues.Where(x => x.Value.Fixed).ToDictionary(x => x.Key, x => x.Value); } diff --git a/src/Umbraco.Core/Models/ContentDataIntegrityReportEntry.cs b/src/Umbraco.Core/Models/ContentDataIntegrityReportEntry.cs index fe0ebce5492d..2d5e24d9a478 100644 --- a/src/Umbraco.Core/Models/ContentDataIntegrityReportEntry.cs +++ b/src/Umbraco.Core/Models/ContentDataIntegrityReportEntry.cs @@ -1,10 +1,23 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a single entry in a content data integrity report. +/// public class ContentDataIntegrityReportEntry { + /// + /// Initializes a new instance of the class. + /// + /// The type of data integrity issue detected. public ContentDataIntegrityReportEntry(ContentDataIntegrityReport.IssueType issueType) => IssueType = issueType; + /// + /// Gets the type of data integrity issue that was detected. + /// public ContentDataIntegrityReport.IssueType IssueType { get; } + /// + /// Gets or sets a value indicating whether the issue has been fixed. + /// public bool Fixed { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentDataIntegrityReportOptions.cs b/src/Umbraco.Core/Models/ContentDataIntegrityReportOptions.cs index 40657069ffcb..0943c811e070 100644 --- a/src/Umbraco.Core/Models/ContentDataIntegrityReportOptions.cs +++ b/src/Umbraco.Core/Models/ContentDataIntegrityReportOptions.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents options for configuring content data integrity checks. +/// public class ContentDataIntegrityReportOptions { /// diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentBlueprintCreateModel.cs b/src/Umbraco.Core/Models/ContentEditing/ContentBlueprintCreateModel.cs index 3d0ed9fdda86..f9ae72f1bc2d 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentBlueprintCreateModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentBlueprintCreateModel.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a model for creating a content blueprint. +/// public class ContentBlueprintCreateModel : ContentCreationModelBase { } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentBlueprintUpdateModel.cs b/src/Umbraco.Core/Models/ContentEditing/ContentBlueprintUpdateModel.cs index bc609e1a0b8b..06beaea643bb 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentBlueprintUpdateModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentBlueprintUpdateModel.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a model for updating a content blueprint. +/// public class ContentBlueprintUpdateModel : ContentEditingModelBase { } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentCreateModel.cs b/src/Umbraco.Core/Models/ContentEditing/ContentCreateModel.cs index 5fe06ba759d8..7884c16c10f6 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentCreateModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentCreateModel.cs @@ -1,6 +1,12 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a model for creating content. +/// public class ContentCreateModel : ContentCreationModelBase { + /// + /// Gets or sets the optional template key to associate with the content. + /// public Guid? TemplateKey { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentCreateResult.cs b/src/Umbraco.Core/Models/ContentEditing/ContentCreateResult.cs index d90f9611a669..53029297ecf8 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentCreateResult.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentCreateResult.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the result of a content creation operation. +/// public class ContentCreateResult : ContentCreateResultBase { } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentCreateResultBase.cs b/src/Umbraco.Core/Models/ContentEditing/ContentCreateResultBase.cs index a76c142753e5..52bc7a0300ce 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentCreateResultBase.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentCreateResultBase.cs @@ -1,9 +1,19 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the base result of a content creation operation. +/// +/// The type of content being created, which must implement . public abstract class ContentCreateResultBase where TContent : class, IContentBase { + /// + /// Gets the created content, or null if creation failed. + /// public TContent? Content { get; init; } + /// + /// Gets the validation result containing any validation errors that occurred during creation. + /// public ContentValidationResult ValidationResult { get; init; } = new(); } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentCreationModelBase.cs b/src/Umbraco.Core/Models/ContentEditing/ContentCreationModelBase.cs index b6303ca2aa0c..51fbfb65dc78 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentCreationModelBase.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentCreationModelBase.cs @@ -1,10 +1,22 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the base model for content creation operations. +/// public abstract class ContentCreationModelBase : ContentEditingModelBase { + /// + /// Gets or sets the optional unique key for the content being created. + /// public Guid? Key { get; set; } + /// + /// Gets or sets the key of the content type for the content being created. + /// public Guid ContentTypeKey { get; set; } = Guid.Empty; + /// + /// Gets or sets the optional key of the parent content item. + /// public Guid? ParentKey { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentEditingModelBase.cs b/src/Umbraco.Core/Models/ContentEditing/ContentEditingModelBase.cs index 305d50688afb..d31026882e64 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentEditingModelBase.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentEditingModelBase.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the base model for content editing operations. +/// public abstract class ContentEditingModelBase { + /// + /// Gets or sets the collection of property values for the content. + /// public IEnumerable Properties { get; set; } = Array.Empty(); + /// + /// Gets or sets the collection of variant models for culture and segment variations. + /// public IEnumerable Variants { get; set; } = Array.Empty(); } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentModelBase.cs b/src/Umbraco.Core/Models/ContentEditing/ContentModelBase.cs index bf7ef96ba079..20ec22e69967 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentModelBase.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentModelBase.cs @@ -1,10 +1,21 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the base model for content with values and variants. +/// +/// The type of value model, which must inherit from . +/// The type of variant model, which must inherit from . public abstract class ContentModelBase where TValueModel : ValueModelBase where TVariantModel : VariantModelBase { + /// + /// Gets or sets the collection of property values for the content. + /// public IEnumerable Values { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of variant models for culture and segment variations. + /// public IEnumerable Variants { get; set; } = Enumerable.Empty(); } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentUpdateModel.cs b/src/Umbraco.Core/Models/ContentEditing/ContentUpdateModel.cs index 327bdafdcfa9..2dfa9eebc4ab 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentUpdateModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentUpdateModel.cs @@ -1,6 +1,12 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a model for updating content. +/// public class ContentUpdateModel : ContentEditingModelBase { + /// + /// Gets or sets the optional template key to associate with the content. + /// public Guid? TemplateKey { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentUpdateResult.cs b/src/Umbraco.Core/Models/ContentEditing/ContentUpdateResult.cs index a7a3d9ca56aa..f30d8c596701 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentUpdateResult.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentUpdateResult.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the result of a content update operation. +/// public class ContentUpdateResult : ContentUpdateResultBase { } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentUpdateResultBase.cs b/src/Umbraco.Core/Models/ContentEditing/ContentUpdateResultBase.cs index a3a5833deccc..66b6732eeba0 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentUpdateResultBase.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentUpdateResultBase.cs @@ -1,9 +1,19 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the base result of a content update operation. +/// +/// The type of content being updated, which must implement . public abstract class ContentUpdateResultBase where TContent : class, IContentBase { + /// + /// Gets the updated content, or null if the update failed. + /// public TContent? Content { get; init; } + /// + /// Gets the validation result containing any validation errors that occurred during the update. + /// public ContentValidationResult ValidationResult { get; init; } = new(); } diff --git a/src/Umbraco.Core/Models/ContentEditing/ContentValidationResult.cs b/src/Umbraco.Core/Models/ContentEditing/ContentValidationResult.cs index 4c693ecc622b..371b315848a6 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ContentValidationResult.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ContentValidationResult.cs @@ -1,8 +1,14 @@ -using Umbraco.Cms.Core.Models.ContentEditing.Validation; +using Umbraco.Cms.Core.Models.ContentEditing.Validation; namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the result of content validation containing any validation errors. +/// public class ContentValidationResult { + /// + /// Gets the collection of property validation errors that occurred during validation. + /// public IEnumerable ValidationErrors { get; init; } = Enumerable.Empty(); } diff --git a/src/Umbraco.Core/Models/ContentEditing/DomainModel.cs b/src/Umbraco.Core/Models/ContentEditing/DomainModel.cs index f989b90421d1..1ff53f5af410 100644 --- a/src/Umbraco.Core/Models/ContentEditing/DomainModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/DomainModel.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a domain model for content editing operations. +/// public class DomainModel { + /// + /// Gets or sets the domain name. + /// public required string DomainName { get; set; } + /// + /// Gets or sets the ISO culture code associated with the domain. + /// public required string IsoCode { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/DomainUpdateResult.cs b/src/Umbraco.Core/Models/ContentEditing/DomainUpdateResult.cs index e00cabbe63fd..082ae96bc081 100644 --- a/src/Umbraco.Core/Models/ContentEditing/DomainUpdateResult.cs +++ b/src/Umbraco.Core/Models/ContentEditing/DomainUpdateResult.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the result of a domain update operation. +/// public sealed class DomainUpdateResult { + /// + /// Gets the collection of domains that were successfully updated. + /// public IEnumerable Domains { get; init; } = Enumerable.Empty(); + /// + /// Gets the collection of domains that conflicted with existing domains, or null if there were no conflicts. + /// public IEnumerable? ConflictingDomains { get; init; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/DomainsUpdateModel.cs b/src/Umbraco.Core/Models/ContentEditing/DomainsUpdateModel.cs index e5f7012a60a2..e7a70a87f15d 100644 --- a/src/Umbraco.Core/Models/ContentEditing/DomainsUpdateModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/DomainsUpdateModel.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a model for updating domains associated with content. +/// public class DomainsUpdateModel { + /// + /// Gets or sets the optional default ISO culture code for the domains. + /// public string? DefaultIsoCode { get; set; } + /// + /// Gets or sets the collection of domain models to update. + /// public required IEnumerable Domains { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/GetAvailableCompositionsFilter.cs b/src/Umbraco.Core/Models/ContentEditing/GetAvailableCompositionsFilter.cs index c3f49d5b7d1c..ac0f75774907 100644 --- a/src/Umbraco.Core/Models/ContentEditing/GetAvailableCompositionsFilter.cs +++ b/src/Umbraco.Core/Models/ContentEditing/GetAvailableCompositionsFilter.cs @@ -1,7 +1,13 @@ namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a filter for retrieving available content type compositions. +/// public class GetAvailableCompositionsFilter { + /// + /// Gets or sets the content type ID to get compositions for. + /// public int ContentTypeId { get; set; } /// diff --git a/src/Umbraco.Core/Models/ContentEditing/HistoryCleanup.cs b/src/Umbraco.Core/Models/ContentEditing/HistoryCleanup.cs index 386ca5f12f9d..beec20492893 100644 --- a/src/Umbraco.Core/Models/ContentEditing/HistoryCleanup.cs +++ b/src/Umbraco.Core/Models/ContentEditing/HistoryCleanup.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the history cleanup settings for content versions. +/// [DataContract(Name = "historyCleanup", Namespace = "")] public class HistoryCleanup : BeingDirtyBase { @@ -10,6 +13,9 @@ public class HistoryCleanup : BeingDirtyBase private int? _keepLatestVersionPerDayForDays; private bool _preventCleanup; + /// + /// Gets or sets a value indicating whether to prevent automatic history cleanup for this content. + /// [DataMember(Name = "preventCleanup")] public bool PreventCleanup { @@ -17,6 +23,9 @@ public bool PreventCleanup set => SetPropertyValueAndDetectChanges(value, ref _preventCleanup, nameof(PreventCleanup)); } + /// + /// Gets or sets the number of days to keep all versions of this content. + /// [DataMember(Name = "keepAllVersionsNewerThanDays")] public int? KeepAllVersionsNewerThanDays { @@ -24,6 +33,9 @@ public int? KeepAllVersionsNewerThanDays set => SetPropertyValueAndDetectChanges(value, ref _keepAllVersionsNewerThanDays, nameof(KeepAllVersionsNewerThanDays)); } + /// + /// Gets or sets the number of days to keep the latest version per day for this content. + /// [DataMember(Name = "keepLatestVersionPerDayForDays")] public int? KeepLatestVersionPerDayForDays { diff --git a/src/Umbraco.Core/Models/ContentEditing/IHasCultureAndSegment.cs b/src/Umbraco.Core/Models/ContentEditing/IHasCultureAndSegment.cs index f026c6426ad6..45f1309cc50c 100644 --- a/src/Umbraco.Core/Models/ContentEditing/IHasCultureAndSegment.cs +++ b/src/Umbraco.Core/Models/ContentEditing/IHasCultureAndSegment.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents an entity that has culture and segment properties for content variation. +/// public interface IHasCultureAndSegment { + /// + /// Gets the culture code for this variant, or null for invariant content. + /// public string? Culture { get; } + /// + /// Gets the segment identifier for this variant, or null for non-segmented content. + /// public string? Segment { get; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/LinkDisplay.cs b/src/Umbraco.Core/Models/ContentEditing/LinkDisplay.cs index 860fad480233..c4d5d8fa02be 100644 --- a/src/Umbraco.Core/Models/ContentEditing/LinkDisplay.cs +++ b/src/Umbraco.Core/Models/ContentEditing/LinkDisplay.cs @@ -2,40 +2,84 @@ namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a link display model for content editing. +/// [DataContract(Name = "link", Namespace = "")] public class LinkDisplay { + /// + /// Gets or sets the icon for the link. + /// [DataMember(Name = "icon")] public string? Icon { get; set; } + /// + /// Gets or sets the display name of the link. + /// [DataMember(Name = "name")] public string? Name { get; set; } + /// + /// Gets or sets a value indicating whether the linked content is published. + /// [DataMember(Name = "published")] public bool Published { get; set; } + /// + /// Gets or sets the query string portion of the link URL. + /// [DataMember(Name = "queryString")] public string? QueryString { get; set; } + /// + /// Gets or sets the target attribute for the link (e.g., "_blank"). + /// [DataMember(Name = "target")] public string? Target { get; set; } + /// + /// Gets or sets a value indicating whether the linked content is in the recycle bin. + /// [DataMember(Name = "trashed")] public bool Trashed { get; set; } + /// + /// Gets or sets the type of link (document, media, or external). + /// [DataMember(Name = "type")] public string? Type { get; set; } + /// + /// Gets or sets the unique identifier of the linked content. + /// [DataMember(Name = "unique")] public Guid? Unique { get; set; } + /// + /// Gets or sets the URL of the link. + /// [DataMember(Name = "url")] public string? Url { get; set; } + /// + /// Contains constants for link types. + /// public static class Types { + /// + /// Represents a link to a document. + /// public const string Document = "document"; + + /// + /// Represents a link to a media item. + /// public const string Media = "media"; + + /// + /// Represents an external link. + /// public const string External = "external"; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/MediaCreateModel.cs b/src/Umbraco.Core/Models/ContentEditing/MediaCreateModel.cs index d6495f1afa0c..e63a09aea5cb 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MediaCreateModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MediaCreateModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a model for creating media. +/// public class MediaCreateModel : ContentCreationModelBase { } diff --git a/src/Umbraco.Core/Models/ContentEditing/MediaCreateResult.cs b/src/Umbraco.Core/Models/ContentEditing/MediaCreateResult.cs index 13a96ff267dc..baafdfeeab8d 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MediaCreateResult.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MediaCreateResult.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the result of a media creation operation. +/// public class MediaCreateResult : ContentCreateResultBase { } diff --git a/src/Umbraco.Core/Models/ContentEditing/MediaUpdateModel.cs b/src/Umbraco.Core/Models/ContentEditing/MediaUpdateModel.cs index 29d85e33b509..426ceeb61b73 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MediaUpdateModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MediaUpdateModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a model for updating media. +/// public class MediaUpdateModel : ContentEditingModelBase { } diff --git a/src/Umbraco.Core/Models/ContentEditing/MediaUpdateResult.cs b/src/Umbraco.Core/Models/ContentEditing/MediaUpdateResult.cs index 4c71e2d99c81..2d7d83a0865b 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MediaUpdateResult.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MediaUpdateResult.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the result of a media update operation. +/// public class MediaUpdateResult : ContentUpdateResultBase { } diff --git a/src/Umbraco.Core/Models/ContentEditing/MemberCreateModel.cs b/src/Umbraco.Core/Models/ContentEditing/MemberCreateModel.cs index 0369d15af55b..87ab2b8f8c35 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MemberCreateModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MemberCreateModel.cs @@ -1,11 +1,22 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a model for creating a member. +/// public class MemberCreateModel : MemberEditingModelBase { + /// + /// Gets or sets the password for the new member. + /// public string Password { get; set; } = string.Empty; + /// + /// Gets or sets the optional unique key for the member being created. + /// public Guid? Key { get; set; } + /// + /// Gets or sets the key of the member type for the member being created. + /// public Guid ContentTypeKey { get; set; } = Guid.Empty; } - diff --git a/src/Umbraco.Core/Models/ContentEditing/MemberCreateResult.cs b/src/Umbraco.Core/Models/ContentEditing/MemberCreateResult.cs index 394f5b842c69..72411ca315cb 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MemberCreateResult.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MemberCreateResult.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the result of a member creation operation. +/// public class MemberCreateResult : ContentCreateResultBase { } diff --git a/src/Umbraco.Core/Models/ContentEditing/MemberEditingModelBase.cs b/src/Umbraco.Core/Models/ContentEditing/MemberEditingModelBase.cs index 057baecd7023..019533239ad1 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MemberEditingModelBase.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MemberEditingModelBase.cs @@ -1,12 +1,27 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the base model for member editing operations. +/// public abstract class MemberEditingModelBase : ContentEditingModelBase { + /// + /// Gets or sets a value indicating whether the member is approved. + /// public bool IsApproved { get; set; } + /// + /// Gets or sets the collection of role keys assigned to the member. + /// public IEnumerable? Roles { get; set; } + /// + /// Gets or sets the email address of the member. + /// public string Email { get; set; } = string.Empty; + /// + /// Gets or sets the username of the member. + /// public string Username { get; set; } = string.Empty; } diff --git a/src/Umbraco.Core/Models/ContentEditing/MemberUpdateModel.cs b/src/Umbraco.Core/Models/ContentEditing/MemberUpdateModel.cs index 555fbed928a5..2409284e4769 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MemberUpdateModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MemberUpdateModel.cs @@ -1,12 +1,27 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a model for updating a member. +/// public class MemberUpdateModel : MemberEditingModelBase { + /// + /// Gets or sets a value indicating whether the member is locked out. + /// public bool IsLockedOut { get; set; } + /// + /// Gets or sets a value indicating whether two-factor authentication is enabled for the member. + /// public bool IsTwoFactorEnabled { get; set; } + /// + /// Gets or sets the old password for password change verification. + /// public string? OldPassword { get; set; } + /// + /// Gets or sets the new password to set for the member. + /// public string? NewPassword { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/MemberUpdateResult.cs b/src/Umbraco.Core/Models/ContentEditing/MemberUpdateResult.cs index 8624275ad5f9..b70ca4226393 100644 --- a/src/Umbraco.Core/Models/ContentEditing/MemberUpdateResult.cs +++ b/src/Umbraco.Core/Models/ContentEditing/MemberUpdateResult.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the result of a member update operation. +/// public class MemberUpdateResult : ContentUpdateResultBase { } diff --git a/src/Umbraco.Core/Models/ContentEditing/PropertyValueModel.cs b/src/Umbraco.Core/Models/ContentEditing/PropertyValueModel.cs index 2afa1604183f..ffe6559b70e7 100644 --- a/src/Umbraco.Core/Models/ContentEditing/PropertyValueModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/PropertyValueModel.cs @@ -1,12 +1,27 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a property value model for content editing operations. +/// public class PropertyValueModel { + /// + /// Gets or sets the property type alias. + /// public required string Alias { get; set; } + /// + /// Gets or sets the property value. + /// public required object? Value { get; set; } + /// + /// Gets or sets the culture code for this property value, or null for invariant properties. + /// public string? Culture { get; set; } + /// + /// Gets or sets the segment identifier for this property value, or null for non-segmented properties. + /// public string? Segment { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/RichTextEditorCommandMode.cs b/src/Umbraco.Core/Models/ContentEditing/RichTextEditorCommandMode.cs index fecbe62641a7..08880eae58b5 100644 --- a/src/Umbraco.Core/Models/ContentEditing/RichTextEditorCommandMode.cs +++ b/src/Umbraco.Core/Models/ContentEditing/RichTextEditorCommandMode.cs @@ -1,8 +1,22 @@ namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the mode in which a rich text editor command operates. +/// public enum RichTextEditorCommandMode { + /// + /// The command inserts content at the cursor position. + /// Insert, + + /// + /// The command operates on the current selection. + /// Selection, + + /// + /// The command operates on all content. + /// All, } diff --git a/src/Umbraco.Core/Models/ContentEditing/SortingModel.cs b/src/Umbraco.Core/Models/ContentEditing/SortingModel.cs index c2d5fc797647..a527dab1c10b 100644 --- a/src/Umbraco.Core/Models/ContentEditing/SortingModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/SortingModel.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a model for sorting content items. +/// public class SortingModel { + /// + /// Gets the unique key of the content item to sort. + /// public required Guid Key { get; init; } + /// + /// Gets the sort order position for the content item. + /// public required int SortOrder { get; init; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/ValidateContentUpdateModel.cs b/src/Umbraco.Core/Models/ContentEditing/ValidateContentUpdateModel.cs index 159398c3b1ef..847877b98356 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ValidateContentUpdateModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ValidateContentUpdateModel.cs @@ -1,6 +1,12 @@ namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a model for validating content updates. +/// public class ValidateContentUpdateModel : ContentUpdateModel { + /// + /// Gets or sets the set of cultures to validate, or null to validate all cultures. + /// public ISet? Cultures { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/Validation/PropertyValidationError.cs b/src/Umbraco.Core/Models/ContentEditing/Validation/PropertyValidationError.cs index 74eb3090f51a..543eed44a281 100644 --- a/src/Umbraco.Core/Models/ContentEditing/Validation/PropertyValidationError.cs +++ b/src/Umbraco.Core/Models/ContentEditing/Validation/PropertyValidationError.cs @@ -1,14 +1,32 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing.Validation; +namespace Umbraco.Cms.Core.Models.ContentEditing.Validation; +/// +/// Represents a validation error for a content property. +/// public class PropertyValidationError { + /// + /// Gets the JSON path to the property value that failed validation. + /// public required string JsonPath { get; init; } + /// + /// Gets the collection of error messages describing the validation failures. + /// public required string[] ErrorMessages { get; init; } + /// + /// Gets or sets the property type alias of the property that failed validation. + /// public required string Alias { get; set; } + /// + /// Gets or sets the culture code for the property value that failed validation, or null for invariant properties. + /// public required string? Culture { get; set; } + /// + /// Gets or sets the segment identifier for the property value that failed validation, or null for non-segmented properties. + /// public required string? Segment { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/ValueModelBase.cs b/src/Umbraco.Core/Models/ContentEditing/ValueModelBase.cs index 7c284df2c63d..fd526d745237 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ValueModelBase.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ValueModelBase.cs @@ -1,15 +1,30 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the base model for property values with culture and segment support. +/// public abstract class ValueModelBase : IHasCultureAndSegment { + /// + /// Gets or sets the culture code for this value, or null for invariant properties. + /// public string? Culture { get; set; } + /// + /// Gets or sets the segment identifier for this value, or null for non-segmented properties. + /// public string? Segment { get; set; } + /// + /// Gets or sets the property type alias. + /// [Required] public string Alias { get; set; } = string.Empty; + /// + /// Gets or sets the property value. + /// public object? Value { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/ValueResponseModelBase.cs b/src/Umbraco.Core/Models/ContentEditing/ValueResponseModelBase.cs index 65e61cfaba36..0a0054a31186 100644 --- a/src/Umbraco.Core/Models/ContentEditing/ValueResponseModelBase.cs +++ b/src/Umbraco.Core/Models/ContentEditing/ValueResponseModelBase.cs @@ -1,9 +1,15 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the base model for property value responses including editor information. +/// public abstract class ValueResponseModelBase : ValueModelBase { + /// + /// Gets or sets the alias of the property editor used for this value. + /// [Required] public string EditorAlias { get; set; } = string.Empty; } diff --git a/src/Umbraco.Core/Models/ContentEditing/VariantModel.cs b/src/Umbraco.Core/Models/ContentEditing/VariantModel.cs index 1249b5630d7c..d9a262f487ab 100644 --- a/src/Umbraco.Core/Models/ContentEditing/VariantModel.cs +++ b/src/Umbraco.Core/Models/ContentEditing/VariantModel.cs @@ -1,10 +1,22 @@ -namespace Umbraco.Cms.Core.Models.ContentEditing; +namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents a variant model for content editing operations. +/// public class VariantModel { + /// + /// Gets or sets the culture code for this variant, or null for invariant content. + /// public string? Culture { get; set; } + /// + /// Gets or sets the segment identifier for this variant, or null for non-segmented content. + /// public string? Segment { get; set; } + /// + /// Gets or sets the name of the content for this variant. + /// public required string Name { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentEditing/VariantModelBase.cs b/src/Umbraco.Core/Models/ContentEditing/VariantModelBase.cs index 423a05dff91d..7a3cbf28952c 100644 --- a/src/Umbraco.Core/Models/ContentEditing/VariantModelBase.cs +++ b/src/Umbraco.Core/Models/ContentEditing/VariantModelBase.cs @@ -1,13 +1,25 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; namespace Umbraco.Cms.Core.Models.ContentEditing; +/// +/// Represents the base model for content variants with culture and segment support. +/// public abstract class VariantModelBase : IHasCultureAndSegment { + /// + /// Gets or sets the culture code for this variant, or null for invariant content. + /// public string? Culture { get; set; } + /// + /// Gets or sets the segment identifier for this variant, or null for non-segmented content. + /// public string? Segment { get; set; } + /// + /// Gets or sets the name of the content for this variant. + /// [Required] public string Name { get; set; } = string.Empty; } diff --git a/src/Umbraco.Core/Models/ContentModel{TContent}.cs b/src/Umbraco.Core/Models/ContentModel{TContent}.cs index 32889331e002..f63a4d0f986a 100644 --- a/src/Umbraco.Core/Models/ContentModel{TContent}.cs +++ b/src/Umbraco.Core/Models/ContentModel{TContent}.cs @@ -2,6 +2,14 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a strongly-typed model for the current Umbraco view. +/// +/// The type of the published content, which must implement . +/// +/// This generic class extends to provide type-safe access to the content +/// in Umbraco views and controllers. +/// public class ContentModel : ContentModel where TContent : IPublishedContent { diff --git a/src/Umbraco.Core/Models/ContentPropertySettings.cs b/src/Umbraco.Core/Models/ContentPropertySettings.cs index 7953a5a1d5b4..a391e8feb20a 100644 --- a/src/Umbraco.Core/Models/ContentPropertySettings.cs +++ b/src/Umbraco.Core/Models/ContentPropertySettings.cs @@ -1,5 +1,12 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents settings for content properties, including reserved field names. +/// +/// +/// Reserved field names are standard names that cannot be used for custom properties +/// to prevent conflicts with built-in Umbraco functionality. +/// public class ContentPropertySettings { private readonly HashSet _reservedFieldNames = new(); @@ -9,7 +16,16 @@ public class ContentPropertySettings /// public ISet ReservedFieldNames => _reservedFieldNames; + /// + /// Adds a reserved field name to the set. + /// + /// The field name to reserve. + /// true if the name was added; false if it already exists. public bool AddReservedFieldName(string name) => _reservedFieldNames.Add(name); + /// + /// Adds multiple reserved field names to the set. + /// + /// The set of field names to reserve. public void AddReservedFieldNames(ISet names) => _reservedFieldNames.UnionWith(names); } diff --git a/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingBranchInternalResult.cs b/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingBranchInternalResult.cs index fbc598180bbd..c47de98d3b40 100644 --- a/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingBranchInternalResult.cs +++ b/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingBranchInternalResult.cs @@ -1,14 +1,32 @@ namespace Umbraco.Cms.Core.Models.ContentPublishing; +/// +/// Represents the internal result of a content branch publishing operation. +/// internal sealed class ContentPublishingBranchInternalResult { + /// + /// Gets or initializes the unique key of the content item. + /// public Guid? ContentKey { get; init; } + /// + /// Gets or initializes the content item that was processed. + /// public IContent? Content { get; init; } + /// + /// Gets or sets the collection of successfully published items in the branch. + /// public IEnumerable SucceededItems { get; set; } = []; + /// + /// Gets or sets the collection of items that failed to publish in the branch. + /// public IEnumerable FailedItems { get; set; } = []; + /// + /// Gets or initializes the unique identifier of the accepted background task, if any. + /// public Guid? AcceptedTaskId { get; init; } } diff --git a/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingBranchItemResult.cs b/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingBranchItemResult.cs index 03d301452d92..4570b3061534 100644 --- a/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingBranchItemResult.cs +++ b/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingBranchItemResult.cs @@ -1,10 +1,19 @@ -using Umbraco.Cms.Core.Services.OperationStatus; +using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Models.ContentPublishing; +/// +/// Represents the result of publishing an individual item within a content branch operation. +/// public sealed class ContentPublishingBranchItemResult { + /// + /// Gets the unique key of the content item. + /// public required Guid Key { get; init; } + /// + /// Gets the operation status indicating the result of the publishing operation for this item. + /// public required ContentPublishingOperationStatus OperationStatus { get; init; } } diff --git a/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingBranchResult.cs b/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingBranchResult.cs index 476f20b821be..69ff64fb9c5c 100644 --- a/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingBranchResult.cs +++ b/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingBranchResult.cs @@ -1,12 +1,27 @@ namespace Umbraco.Cms.Core.Models.ContentPublishing; +/// +/// Represents the result of a content branch publishing operation. +/// public sealed class ContentPublishingBranchResult { + /// + /// Gets or initializes the root content item of the branch that was processed. + /// public IContent? Content { get; init; } + /// + /// Gets or sets the collection of successfully published items in the branch. + /// public IEnumerable SucceededItems { get; set; } = []; + /// + /// Gets or sets the collection of items that failed to publish in the branch. + /// public IEnumerable FailedItems { get; set; } = []; + /// + /// Gets or initializes the unique identifier of the accepted background task, if any. + /// public Guid? AcceptedTaskId { get; init; } } diff --git a/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingResult.cs b/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingResult.cs index a9307f197208..625315379585 100644 --- a/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingResult.cs +++ b/src/Umbraco.Core/Models/ContentPublishing/ContentPublishingResult.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.ContentPublishing; +namespace Umbraco.Cms.Core.Models.ContentPublishing; +/// +/// Represents the result of a content publishing operation. +/// public sealed class ContentPublishingResult { + /// + /// Gets or initializes the content item that was published. + /// public IContent? Content { get; init; } + /// + /// Gets or sets the collection of property aliases that failed validation. + /// public IEnumerable InvalidPropertyAliases { get; set; } = []; } diff --git a/src/Umbraco.Core/Models/ContentPublishing/CultureAndScheduleModel.cs b/src/Umbraco.Core/Models/ContentPublishing/CultureAndScheduleModel.cs index 42a586508be9..d1dee0e5f81f 100644 --- a/src/Umbraco.Core/Models/ContentPublishing/CultureAndScheduleModel.cs +++ b/src/Umbraco.Core/Models/ContentPublishing/CultureAndScheduleModel.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Models.ContentPublishing; +/// +/// Represents a model containing cultures to publish immediately and scheduled publishing information. +/// public class CultureAndScheduleModel { + /// + /// Gets or sets the set of cultures that should be published immediately. + /// public required ISet CulturesToPublishImmediately { get; set; } + + /// + /// Gets or sets the collection of content schedules for scheduled publishing and unpublishing. + /// public required ContentScheduleCollection Schedules { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentPublishing/CulturePublishScheduleModel.cs b/src/Umbraco.Core/Models/ContentPublishing/CulturePublishScheduleModel.cs index 5b00bfc798f2..56d88052d331 100644 --- a/src/Umbraco.Core/Models/ContentPublishing/CulturePublishScheduleModel.cs +++ b/src/Umbraco.Core/Models/ContentPublishing/CulturePublishScheduleModel.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models.ContentPublishing; +/// +/// Represents a model for scheduling content publishing for a specific culture. +/// public class CulturePublishScheduleModel { /// @@ -13,9 +16,18 @@ public class CulturePublishScheduleModel public ContentScheduleModel? Schedule { get; set; } } +/// +/// Represents the scheduling model for content publishing and unpublishing dates. +/// public class ContentScheduleModel { + /// + /// Gets or sets the date and time when the content should be published. + /// public DateTimeOffset? PublishDate { get; set; } + /// + /// Gets or sets the date and time when the content should be unpublished. + /// public DateTimeOffset? UnpublishDate { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentQuery/ContentScheduleQueryResult.cs b/src/Umbraco.Core/Models/ContentQuery/ContentScheduleQueryResult.cs index 04fcb154f3ff..35fa2c8f05e0 100644 --- a/src/Umbraco.Core/Models/ContentQuery/ContentScheduleQueryResult.cs +++ b/src/Umbraco.Core/Models/ContentQuery/ContentScheduleQueryResult.cs @@ -1,14 +1,28 @@ namespace Umbraco.Cms.Core.Models.ContentQuery; +/// +/// Represents the result of a content schedule query, containing the content item and its associated schedules. +/// public class ContentScheduleQueryResult { + /// + /// Initializes a new instance of the class. + /// + /// The content item. + /// The collection of schedules associated with the content. public ContentScheduleQueryResult(IContent content, ContentScheduleCollection schedules) { Content = content; Schedules = schedules; } + /// + /// Gets the content item. + /// public IContent Content { get; init; } + /// + /// Gets the collection of schedules associated with the content. + /// public ContentScheduleCollection Schedules { get; init; } } diff --git a/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs b/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs index c8663e18b154..f9917db4bee6 100644 --- a/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs +++ b/src/Umbraco.Core/Models/ContentRepositoryExtensions.cs @@ -8,6 +8,15 @@ namespace Umbraco.Extensions; /// public static class ContentRepositoryExtensions { + /// + /// Sets the culture information for a specific culture on the content item. + /// + /// The content item to update. + /// The culture code (e.g., "en-US"). + /// The name of the content in the specified culture. + /// The date to associate with this culture information. + /// Thrown when or is null. + /// Thrown when or is empty or whitespace. public static void SetCultureInfo(this IContentBase content, string? culture, string? name, DateTime date) { if (name == null) @@ -243,6 +252,15 @@ public static void CopyFrom(this IContent content, IContent other, string? cultu } } + /// + /// Sets the publish information for a specific culture on the content item. + /// + /// The content item to update. + /// The culture code (e.g., "en-US"). + /// The published name of the content in the specified culture. + /// The publish date to associate with this culture. + /// Thrown when or is null. + /// Thrown when or is empty or whitespace. public static void SetPublishInfo(this IContent content, string? culture, string? name, DateTime date) { if (name == null) @@ -272,7 +290,11 @@ public static void SetPublishInfo(this IContent content, string? culture, string content.PublishCultureInfos?.AddOrUpdate(culture, name, date); } - // sets the edited cultures on the content + /// + /// Sets the cultures that have been edited on the content item. + /// + /// The content item to update. + /// The collection of culture codes that have been edited, or null to clear. public static void SetCultureEdited(this IContent content, IEnumerable? cultures) { if (cultures == null) @@ -428,6 +450,10 @@ public static bool UnpublishCulture(this IContent content, string? culture = "*" return keepProcessing; } + /// + /// Clears all publish culture information from the content item. + /// + /// The content item to clear publish information from. public static void ClearPublishInfos(this IContent content) => content.PublishCultureInfos = null; /// diff --git a/src/Umbraco.Core/Models/ContentSchedule.cs b/src/Umbraco.Core/Models/ContentSchedule.cs index 18d254a9aabe..c14a0c5ec897 100644 --- a/src/Umbraco.Core/Models/ContentSchedule.cs +++ b/src/Umbraco.Core/Models/ContentSchedule.cs @@ -59,16 +59,28 @@ public ContentSchedule(Guid id, string culture, DateTime date, ContentScheduleAc [DataMember] public ContentScheduleAction Action { get; } + /// public object DeepClone() => new ContentSchedule(Id, Culture, Date, Action); + /// public override bool Equals(object? obj) => obj is ContentSchedule other && Equals(other); + /// + /// Determines whether this schedule is equal to another schedule. + /// + /// The other schedule to compare. + /// true if the schedules are equal; otherwise, false. + /// + /// Two ContentSchedule instances are equal if they are for the same action, + /// for the same culture, on the same date. The Id is not compared. + /// public bool Equals(ContentSchedule other) => // don't compare Ids, two ContentSchedule are equal if they are for the same change // for the same culture, on the same date - and the collection deals w/duplicates Culture.InvariantEquals(other.Culture) && Date == other.Date && Action == other.Action; + /// public override int GetHashCode() => throw new NotImplementedException(); } diff --git a/src/Umbraco.Core/Models/ContentScheduleCollection.cs b/src/Umbraco.Core/Models/ContentScheduleCollection.cs index 8dbdd76e795e..95e34eeaae5f 100644 --- a/src/Umbraco.Core/Models/ContentScheduleCollection.cs +++ b/src/Umbraco.Core/Models/ContentScheduleCollection.cs @@ -2,12 +2,20 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a collection of content schedules for publishing and unpublishing content. +/// +/// +/// The underlying storage is backed by a sorted list so that the schedule is always in order of date +/// and duplicate dates per culture are not allowed. +/// public class ContentScheduleCollection : INotifyCollectionChanged, IDeepCloneable, IEquatable { // underlying storage for the collection backed by a sorted list so that the schedule is always in order of date and that duplicate dates per culture are not allowed private readonly Dictionary> _schedule = new(StringComparer.InvariantCultureIgnoreCase); + /// public event NotifyCollectionChangedEventHandler? CollectionChanged; /// @@ -16,6 +24,7 @@ private readonly Dictionary> _sche /// public IReadOnlyList FullSchedule => _schedule.SelectMany(x => x.Value.Values).ToList(); + /// public object DeepClone() { var clone = new ContentScheduleCollection(); @@ -33,6 +42,7 @@ public object DeepClone() return clone; } + /// public bool Equals(ContentScheduleCollection? other) { if (other == null) @@ -61,6 +71,12 @@ public bool Equals(ContentScheduleCollection? other) return true; } + /// + /// Creates a new with a schedule entry for invariant content. + /// + /// The release date, or null if no release is scheduled. + /// The expiration date, or null if no expiration is scheduled. + /// A new content schedule collection with the specified entry. public static ContentScheduleCollection CreateWithEntry(DateTime? release, DateTime? expire) { var schedule = new ContentScheduleCollection(); @@ -170,6 +186,11 @@ public void Remove(ContentSchedule change) } } + /// + /// Removes a schedule entry for the specified culture and action if it exists. + /// + /// The culture of the schedule to remove. + /// The action type (release or expire) to remove. public void RemoveIfExists(string culture, ContentScheduleAction action) { ContentSchedule? changeToRemove = FullSchedule.FirstOrDefault(change => @@ -181,6 +202,12 @@ public void RemoveIfExists(string culture, ContentScheduleAction action) } } + /// + /// Adds or updates a schedule entry for the specified culture and action. + /// + /// The culture for the schedule. + /// The date and time for the scheduled action. + /// The action type (release or expire). public void AddOrUpdate(string culture, DateTime dateTime, ContentScheduleAction action) { // we need to remove the old one as ContentSchedule.Date is immutable @@ -270,9 +297,17 @@ public IEnumerable GetSchedule(string? culture, ContentSchedule return Enumerable.Empty(); } + /// public override bool Equals(object? obj) => obj is ContentScheduleCollection other && Equals(other); + /// + /// Creates a new with a schedule entry for a specific culture. + /// + /// The culture for the schedule. + /// The release date, or null if no release is scheduled. + /// The expiration date, or null if no expiration is scheduled. + /// A new content schedule collection with the specified entry. public static ContentScheduleCollection CreateWithEntry(string culture, DateTime? release, DateTime? expire) { var schedule = new ContentScheduleCollection(); @@ -280,6 +315,7 @@ public static ContentScheduleCollection CreateWithEntry(string culture, DateTime return schedule; } + /// public override int GetHashCode() { throw new NotImplementedException(); diff --git a/src/Umbraco.Core/Models/ContentType.cs b/src/Umbraco.Core/Models/ContentType.cs index c31f5f72ff66..c33124f08844 100644 --- a/src/Umbraco.Core/Models/ContentType.cs +++ b/src/Umbraco.Core/Models/ContentType.cs @@ -12,6 +12,9 @@ namespace Umbraco.Cms.Core.Models; [DataContract(IsReference = true)] public class ContentType : ContentTypeCompositionBase, IContentType { + /// + /// Constant indicating that content types support publishing. + /// public const bool SupportsPublishingConst = true; // Custom comparer for enumerable @@ -68,6 +71,9 @@ public ContentType(IShortStringHelper shortStringHelper, IContentType parent, st /// public override ISimpleContentType ToSimple() => new SimpleContentType(this); + /// + /// Gets or sets the identifier of the default template for this content type. + /// [DataMember] public int DefaultTemplateId { @@ -96,6 +102,9 @@ public IEnumerable? AllowedTemplates } } + /// + /// Gets or sets the history cleanup configuration for this content type. + /// public HistoryCleanup? HistoryCleanup { get => _historyCleanup; diff --git a/src/Umbraco.Core/Models/ContentTypeAvailableCompositionsResult.cs b/src/Umbraco.Core/Models/ContentTypeAvailableCompositionsResult.cs index c4ab790dfe6c..b8e13e205c46 100644 --- a/src/Umbraco.Core/Models/ContentTypeAvailableCompositionsResult.cs +++ b/src/Umbraco.Core/Models/ContentTypeAvailableCompositionsResult.cs @@ -5,13 +5,24 @@ namespace Umbraco.Cms.Core.Models; /// public class ContentTypeAvailableCompositionsResult { + /// + /// Initializes a new instance of the class. + /// + /// The composition content type. + /// Whether the composition is allowed. public ContentTypeAvailableCompositionsResult(IContentTypeComposition composition, bool allowed) { Composition = composition; Allowed = allowed; } + /// + /// Gets the composition content type. + /// public IContentTypeComposition Composition { get; } + /// + /// Gets a value indicating whether the composition is allowed. + /// public bool Allowed { get; } } diff --git a/src/Umbraco.Core/Models/ContentTypeAvailableCompositionsResults.cs b/src/Umbraco.Core/Models/ContentTypeAvailableCompositionsResults.cs index 4dc268faf368..668636c29d10 100644 --- a/src/Umbraco.Core/Models/ContentTypeAvailableCompositionsResults.cs +++ b/src/Umbraco.Core/Models/ContentTypeAvailableCompositionsResults.cs @@ -5,12 +5,20 @@ namespace Umbraco.Cms.Core.Models; /// public class ContentTypeAvailableCompositionsResults { + /// + /// Initializes a new instance of the class with default empty values. + /// public ContentTypeAvailableCompositionsResults() { Ancestors = Enumerable.Empty(); Results = Enumerable.Empty(); } + /// + /// Initializes a new instance of the class. + /// + /// The ancestor content types. + /// The composition availability results. public ContentTypeAvailableCompositionsResults( IEnumerable ancestors, IEnumerable results) @@ -19,7 +27,13 @@ public ContentTypeAvailableCompositionsResults( Results = results; } + /// + /// Gets the ancestor content types. + /// public IEnumerable Ancestors { get; } + /// + /// Gets the composition availability results. + /// public IEnumerable Results { get; } } diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index 2190437f351b..e922d28c481b 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -35,6 +35,12 @@ public abstract class ContentTypeBase : TreeEntityBase, IContentTypeBase private string? _thumbnail = "folder.png"; private ContentVariation _variations; + /// + /// Initializes a new instance of the class with a parent identifier. + /// + /// The short string helper for alias generation. + /// The identifier of the parent content type. + /// Thrown when is zero. protected ContentTypeBase(IShortStringHelper shortStringHelper, int parentId) { _alias = string.Empty; @@ -57,11 +63,23 @@ protected ContentTypeBase(IShortStringHelper shortStringHelper, int parentId) _variations = ContentVariation.Nothing; } + /// + /// Initializes a new instance of the class with a parent content type. + /// + /// The short string helper for alias generation. + /// The parent content type. protected ContentTypeBase(IShortStringHelper shortStringHelper, IContentTypeBase parent) : this(shortStringHelper, parent, string.Empty) { } + /// + /// Initializes a new instance of the class with a parent content type and alias. + /// + /// The short string helper for alias generation. + /// The parent content type. + /// The alias for this content type. + /// Thrown when is null. protected ContentTypeBase(IShortStringHelper shortStringHelper, IContentTypeBase parent, string alias) { if (parent == null) @@ -140,6 +158,10 @@ private set // TODO: should we mark this as EditorBrowsable hidden since it really isn't ever used? internal PropertyTypeCollection PropertyTypeCollection { get; private set; } + /// + /// Converts this content type to a simple content type representation. + /// + /// A simple content type representation. public abstract ISimpleContentType ToSimple(); /// @@ -467,6 +489,11 @@ public override void ResetDirtyProperties() } } + /// + /// Creates a deep clone of this content type with reset identities. + /// + /// The alias for the cloned content type. + /// A deep clone with reset identities. public IContentTypeBase DeepCloneWithResetIdentities(string alias) { var clone = (IContentTypeBase)DeepClone(); @@ -489,9 +516,19 @@ public IContentTypeBase DeepCloneWithResetIdentities(string alias) return clone; } + /// + /// Handles changes to the property groups collection. + /// + /// The source of the event. + /// The event arguments. protected void PropertyGroupsChanged(object? sender, NotifyCollectionChangedEventArgs e) => OnPropertyChanged(nameof(PropertyGroups)); + /// + /// Handles changes to the property types collection. + /// + /// The source of the event. + /// The event arguments. protected void PropertyTypesChanged(object? sender, NotifyCollectionChangedEventArgs e) => // enable this to detect duplicate property aliases. We do want this, however making this change in a @@ -509,6 +546,7 @@ protected void PropertyTypesChanged(object? sender, NotifyCollectionChangedEvent // } OnPropertyChanged(nameof(PropertyTypes)); + /// protected override void PerformDeepClone(object clone) { base.PerformDeepClone(clone); diff --git a/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs b/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs index 12e0e5a13823..f8ec45c94391 100644 --- a/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs +++ b/src/Umbraco.Core/Models/ContentTypeBaseExtensions.cs @@ -8,6 +8,11 @@ namespace Umbraco.Extensions; /// public static class ContentTypeBaseExtensions { + /// + /// Gets the published item type for the content type. + /// + /// The content type. + /// The for the content type. public static PublishedItemType GetItemType(this IContentTypeBase contentType) { Type type = contentType.GetType(); diff --git a/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs b/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs index dcf17b7c2026..2f075032090f 100644 --- a/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeCompositionBase.cs @@ -14,20 +14,39 @@ public abstract class ContentTypeCompositionBase : ContentTypeBase, IContentType private List _contentTypeComposition = new(); private List _removedContentTypeKeyTracker = new(); + /// + /// Initializes a new instance of the class with the specified parent ID. + /// + /// The short string helper. + /// The identifier of the parent content type. protected ContentTypeCompositionBase(IShortStringHelper shortStringHelper, int parentId) : base(shortStringHelper, parentId) { } + /// + /// Initializes a new instance of the class with a parent content type. + /// + /// The short string helper. + /// The parent content type composition. protected ContentTypeCompositionBase(IShortStringHelper shortStringHelper, IContentTypeComposition parent) : this(shortStringHelper, parent, string.Empty) { } + /// + /// Initializes a new instance of the class with a parent content type and alias. + /// + /// The short string helper. + /// The parent content type composition. + /// The alias for the content type. protected ContentTypeCompositionBase(IShortStringHelper shortStringHelper, IContentTypeComposition parent, string alias) : base(shortStringHelper, parent, alias) => AddContentType(parent); + /// + /// Gets the collection of removed content type identifiers. + /// public IEnumerable RemovedContentTypes => _removedContentTypeKeyTracker; /// @@ -295,6 +314,7 @@ public IEnumerable CompositionKeys() .Union(ContentTypeComposition.SelectMany(x => x.CompositionKeys())); + /// protected override void PerformDeepClone(object clone) { base.PerformDeepClone(clone); diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/Composition.cs b/src/Umbraco.Core/Models/ContentTypeEditing/Composition.cs index 5d688e47fade..54a76fe4f27e 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/Composition.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/Composition.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents a composition relationship for a content type. +/// public class Composition { + /// + /// Gets the unique key of the composed content type. + /// public required Guid Key { get; init; } + /// + /// Gets the type of composition relationship. + /// public required CompositionType CompositionType { get; init; } } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/CompositionType.cs b/src/Umbraco.Core/Models/ContentTypeEditing/CompositionType.cs index 2f49a65a7634..391f22ff2ad4 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/CompositionType.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/CompositionType.cs @@ -1,7 +1,17 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Specifies the type of composition relationship between content types. +/// public enum CompositionType { + /// + /// Indicates a composition relationship where properties are included from another content type. + /// Composition, + + /// + /// Indicates an inheritance relationship where the content type inherits from a parent content type. + /// Inheritance } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeCleanup.cs b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeCleanup.cs index 818a76928834..bed35adfec16 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeCleanup.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeCleanup.cs @@ -1,10 +1,22 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents the cleanup settings for content version history of a content type. +/// public class ContentTypeCleanup { + /// + /// Gets or sets a value indicating whether automatic cleanup of content versions is prevented. + /// public bool PreventCleanup { get; init; } + /// + /// Gets or sets the number of days for which all content versions should be retained. + /// public int? KeepAllVersionsNewerThanDays { get; init; } + /// + /// Gets or sets the number of days for which to keep only the latest version per day. + /// public int? KeepLatestVersionPerDayForDays { get; init; } } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeCreateModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeCreateModel.cs index aa77a804c48a..a75c91def55d 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeCreateModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeCreateModel.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents the model for creating a new document content type. +/// public class ContentTypeCreateModel : ContentTypeModelBase { + /// + /// Gets or sets the unique key for the content type being created. + /// public Guid? Key { get; set; } + /// + /// Gets or sets the key of the container (folder) to place the content type in. + /// public Guid? ContainerKey { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeEditingModelBase.cs b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeEditingModelBase.cs index 3bdc97dbec7f..d0a2ffcbf9fa 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeEditingModelBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeEditingModelBase.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; /// /// @@ -14,29 +14,68 @@ public abstract class ContentTypeEditingModelBase + /// Gets or sets the alias of the content type. + /// public string Alias { get; set; } = string.Empty; + /// + /// Gets or sets the display name of the content type. + /// public string Name { get; set; } = string.Empty; + /// + /// Gets or sets the description of the content type. + /// public string? Description { get; set; } + /// + /// Gets or sets the icon identifier for the content type. + /// public string Icon { get; set; } = string.Empty; + /// + /// Gets or sets a value indicating whether content of this type can be created at the root level. + /// public bool AllowedAsRoot { get; set; } + /// + /// Gets or sets a value indicating whether content of this type varies by culture. + /// public bool VariesByCulture { get; set; } + /// + /// Gets or sets a value indicating whether content of this type varies by segment. + /// public bool VariesBySegment { get; set; } + /// + /// Gets or sets a value indicating whether this content type is an element type. + /// public bool IsElement { get; set; } + /// + /// Gets or sets the key of the list view data type associated with this content type. + /// public Guid? ListView { get; set; } + /// + /// Gets or sets the property types defined on this content type. + /// public IEnumerable Properties { get; set; } = Array.Empty(); + /// + /// Gets or sets the property type containers (tabs and groups) defined on this content type. + /// public IEnumerable Containers { get; set; } = Array.Empty(); + /// + /// Gets or sets the content types that are allowed to be created as children of content of this type. + /// public IEnumerable AllowedContentTypes { get; set; } = Array.Empty(); + /// + /// Gets or sets the compositions that this content type uses. + /// public IEnumerable Compositions { get; set; } = Array.Empty(); } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeModelBase.cs b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeModelBase.cs index 1e228e0c2186..6c94456cc69c 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeModelBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeModelBase.cs @@ -1,10 +1,22 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Base model for document content types, providing common properties for create and update operations. +/// public abstract class ContentTypeModelBase : ContentTypeEditingModelBase { + /// + /// Gets or sets the cleanup settings for content version history. + /// public ContentTypeCleanup Cleanup { get; set; } = new(); + /// + /// Gets or sets the keys of the templates that are allowed for content of this type. + /// public IEnumerable AllowedTemplateKeys { get; set; } = Array.Empty(); + /// + /// Gets or sets the key of the default template for content of this type. + /// public Guid? DefaultTemplateKey { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypePropertyContainerModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypePropertyContainerModel.cs index cba40c473d3d..59717fcbdd17 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypePropertyContainerModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypePropertyContainerModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents a property type container model for document content types. +/// public class ContentTypePropertyContainerModel : PropertyTypeContainerModelBase { } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypePropertyTypeModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypePropertyTypeModel.cs index f0220b9a265b..a02d492b574f 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypePropertyTypeModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypePropertyTypeModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents a property type model for document content types. +/// public class ContentTypePropertyTypeModel : PropertyTypeModelBase { } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeUpdateModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeUpdateModel.cs index be9d25f2be07..e3fd5993cbf8 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeUpdateModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/ContentTypeUpdateModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents the model for updating an existing document content type. +/// public class ContentTypeUpdateModel : ContentTypeModelBase { } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeCreateModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeCreateModel.cs index fb69d520df71..71277b63bf79 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeCreateModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeCreateModel.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents the model for creating a new media type. +/// public class MediaTypeCreateModel : MediaTypeModelBase { + /// + /// Gets or sets the unique key for the media type being created. + /// public Guid? Key { get; set; } + /// + /// Gets or sets the key of the container (folder) to place the media type in. + /// public Guid? ContainerKey { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeModelBase.cs b/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeModelBase.cs index 89b837012d61..25e2843aeb36 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeModelBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeModelBase.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Base model for media types, providing common properties for create and update operations. +/// public class MediaTypeModelBase : ContentTypeEditingModelBase { } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypePropertyContainerModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypePropertyContainerModel.cs index e69cb074aa41..4ebf4793162a 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypePropertyContainerModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypePropertyContainerModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents a property type container model for media types. +/// public class MediaTypePropertyContainerModel : PropertyTypeContainerModelBase { } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypePropertyTypeModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypePropertyTypeModel.cs index 5019c09b5746..aa1759ab5782 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypePropertyTypeModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypePropertyTypeModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents a property type model for media types. +/// public class MediaTypePropertyTypeModel : PropertyTypeModelBase { } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeUpdateModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeUpdateModel.cs index 00ece8a2a02d..9e72ba1566e3 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeUpdateModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/MediaTypeUpdateModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents the model for updating an existing media type. +/// public class MediaTypeUpdateModel : MediaTypeModelBase { } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypeCreateModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypeCreateModel.cs index a327cc5fe0ef..6915d1884819 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypeCreateModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypeCreateModel.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents the model for creating a new member type. +/// public class MemberTypeCreateModel : MemberTypeModelBase { + /// + /// Gets or sets the unique key for the member type being created. + /// public Guid? Key { get; set; } + /// + /// Gets or sets the key of the container (folder) to place the member type in. + /// public Guid? ContainerKey { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypeModelBase.cs b/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypeModelBase.cs index 2a416bb9c1af..aa69616c286d 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypeModelBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypeModelBase.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Base model for member types, providing common properties for create and update operations. +/// public class MemberTypeModelBase : ContentTypeEditingModelBase { } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypePropertyContainerModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypePropertyContainerModel.cs index 67dc372ad714..c5d0b8a16d3b 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypePropertyContainerModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypePropertyContainerModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents a property type container model for member types. +/// public class MemberTypePropertyContainerModel : PropertyTypeContainerModelBase { } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypePropertyTypeModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypePropertyTypeModel.cs index 9ab2a356c0ab..8a41a4b19c56 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypePropertyTypeModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypePropertyTypeModel.cs @@ -1,10 +1,22 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents a property type model for member types with additional member-specific settings. +/// public class MemberTypePropertyTypeModel : PropertyTypeModelBase { + /// + /// Gets or sets a value indicating whether the property contains sensitive data. + /// public bool IsSensitive { get; set; } + /// + /// Gets or sets a value indicating whether members can view this property on their own profile. + /// public bool MemberCanView { get; set; } + /// + /// Gets or sets a value indicating whether members can edit this property on their own profile. + /// public bool MemberCanEdit { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypeUpdateModel.cs b/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypeUpdateModel.cs index 3d36a78ca7e6..757fbc445ea2 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypeUpdateModel.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/MemberTypeUpdateModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents the model for updating an existing member type. +/// public class MemberTypeUpdateModel : MemberTypeModelBase { } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeAppearance.cs b/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeAppearance.cs index b7134f309465..99b484bc35b9 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeAppearance.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeAppearance.cs @@ -1,6 +1,12 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents the appearance settings for a property type in the backoffice. +/// public class PropertyTypeAppearance { + /// + /// Gets or sets a value indicating whether the label should be displayed above the property editor. + /// public bool LabelOnTop { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeContainerModelBase.cs b/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeContainerModelBase.cs index 04ed7c350a7e..8b0ab116b61b 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeContainerModelBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeContainerModelBase.cs @@ -1,15 +1,35 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Base model for property type containers such as tabs and groups. +/// public abstract class PropertyTypeContainerModelBase { + /// + /// Gets or sets the unique key of the container. + /// public Guid Key { get; set; } + /// + /// Gets or sets the key of the parent container, if any. + /// public Guid? ParentKey { get; set; } + /// + /// Gets or sets the name of the container. + /// public string? Name { get; set; } - // NOTE: This needs to be a string because it can be anything in the future (= not necessarily limited to "tab" or "group") + /// + /// Gets or sets the type of container (e.g., "Tab" or "Group"). + /// + /// + /// This needs to be a string because it can be anything in the future (not necessarily limited to "tab" or "group"). + /// public string Type { get; set; } = string.Empty; + /// + /// Gets or sets the sort order of the container. + /// public int SortOrder { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeModelBase.cs b/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeModelBase.cs index 93966f606810..d0f544b76ddd 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeModelBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeModelBase.cs @@ -1,26 +1,62 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Base model for property types used in content type editing. +/// public abstract class PropertyTypeModelBase { + /// + /// Gets or sets the unique key of the property type. + /// public Guid Key { get; set; } + /// + /// Gets or sets the key of the container (tab or group) that this property belongs to. + /// public Guid? ContainerKey { get; set; } + /// + /// Gets or sets the sort order of the property type within its container. + /// public int SortOrder { get; set; } + /// + /// Gets or sets the alias of the property type. + /// public string Alias { get; set; } = string.Empty; + /// + /// Gets or sets the display name of the property type. + /// public string Name { get; set; } = string.Empty; + /// + /// Gets or sets the description of the property type. + /// public string? Description { get; set; } + /// + /// Gets or sets the key of the data type used by this property type. + /// public Guid DataTypeKey { get; set; } + /// + /// Gets or sets a value indicating whether the property value varies by culture. + /// public bool VariesByCulture { get; set; } + /// + /// Gets or sets a value indicating whether the property value varies by segment. + /// public bool VariesBySegment { get; set; } + /// + /// Gets or sets the validation settings for the property type. + /// public PropertyTypeValidation Validation { get; set; } = new(); + /// + /// Gets or sets the appearance settings for the property type. + /// public PropertyTypeAppearance Appearance { get; set; } = new(); } diff --git a/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeValidation.cs b/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeValidation.cs index 0b0b78228233..0b7814fdd982 100644 --- a/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeValidation.cs +++ b/src/Umbraco.Core/Models/ContentTypeEditing/PropertyTypeValidation.cs @@ -1,12 +1,27 @@ -namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +namespace Umbraco.Cms.Core.Models.ContentTypeEditing; +/// +/// Represents the validation settings for a property type. +/// public class PropertyTypeValidation { + /// + /// Gets or sets a value indicating whether the property value is mandatory. + /// public bool Mandatory { get; set; } + /// + /// Gets or sets the custom validation message to display when a mandatory property is not filled in. + /// public string? MandatoryMessage { get; set; } + /// + /// Gets or sets the regular expression pattern used to validate the property value. + /// public string? RegularExpression { get; set; } + /// + /// Gets or sets the custom validation message to display when the regular expression validation fails. + /// public string? RegularExpressionMessage { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentTypeSort.cs b/src/Umbraco.Core/Models/ContentTypeSort.cs index e3ad70cb360c..fc99d2867967 100644 --- a/src/Umbraco.Core/Models/ContentTypeSort.cs +++ b/src/Umbraco.Core/Models/ContentTypeSort.cs @@ -7,14 +7,22 @@ namespace Umbraco.Cms.Core.Models; /// public class ContentTypeSort : IValueObject, IDeepCloneable { - // this parameterless ctor should never be used BUT is required by AutoMapper in EntityMapperProfile + /// + /// Initializes a new instance of the class. + /// + /// + /// This parameterless constructor should not be used directly but is required by AutoMapper in EntityMapperProfile. + /// public ContentTypeSort() { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with the specified values. /// + /// The unique key of the content type. + /// The sort order position. + /// The alias of the content type. public ContentTypeSort(Guid key, int sortOrder, string alias) { SortOrder = sortOrder; @@ -37,12 +45,14 @@ public ContentTypeSort(Guid key, int sortOrder, string alias) /// public Guid Key { get; set; } + /// public object DeepClone() { var clone = (ContentTypeSort)MemberwiseClone(); return clone; } + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -63,9 +73,15 @@ public override bool Equals(object? obj) return Equals((ContentTypeSort)obj); } + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// true if the specified object is equal to this instance; otherwise, false. protected bool Equals(ContentTypeSort other) => Key.Equals(other.Key) && string.Equals(Alias, other.Alias); + /// public override int GetHashCode() { unchecked diff --git a/src/Umbraco.Core/Models/ContentVersionCleanupPolicySettings.cs b/src/Umbraco.Core/Models/ContentVersionCleanupPolicySettings.cs index 7d7cc6c57832..5dd7eb4c10a8 100644 --- a/src/Umbraco.Core/Models/ContentVersionCleanupPolicySettings.cs +++ b/src/Umbraco.Core/Models/ContentVersionCleanupPolicySettings.cs @@ -1,14 +1,51 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents the content version cleanup policy settings for a specific content type. +/// +/// +/// These settings control how historical content versions are cleaned up to manage database size. +/// Each content type can have its own cleanup policy. +/// public class ContentVersionCleanupPolicySettings { + /// + /// Gets or sets the identifier of the content type these settings apply to. + /// public int ContentTypeId { get; set; } + /// + /// Gets or sets a value indicating whether version cleanup should be prevented for this content type. + /// + /// + /// true to prevent automatic cleanup of versions; false to allow cleanup. + /// public bool PreventCleanup { get; set; } + /// + /// Gets or sets the number of days to keep all versions. + /// + /// + /// The number of days during which all versions are retained, or null to use the global default. + /// + /// + /// All versions created within this time period will be kept regardless of other settings. + /// public int? KeepAllVersionsNewerThanDays { get; set; } + /// + /// Gets or sets the number of days to keep the latest version per day. + /// + /// + /// The number of days during which only the latest version per day is retained, or null to use the global default. + /// + /// + /// After the period, only one version per day is kept for this duration. + /// public int? KeepLatestVersionPerDayForDays { get; set; } + /// + /// Gets or sets the date and time when these settings were last updated. + /// public DateTime Updated { get; set; } } diff --git a/src/Umbraco.Core/Models/ContentVersionMeta.cs b/src/Umbraco.Core/Models/ContentVersionMeta.cs index 768f16c71d49..4f89c43a3732 100644 --- a/src/Umbraco.Core/Models/ContentVersionMeta.cs +++ b/src/Umbraco.Core/Models/ContentVersionMeta.cs @@ -2,12 +2,34 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents metadata about a content version. +/// +/// +/// This class contains information about a specific version of content, including +/// the user who created it, the date, and whether it's the current published or draft version. +/// public class ContentVersionMeta { + /// + /// Initializes a new instance of the class. + /// public ContentVersionMeta() { } + /// + /// Initializes a new instance of the class with the specified values. + /// + /// The version identifier. + /// The content identifier. + /// The content type identifier. + /// The identifier of the user who created this version. + /// The date and time when this version was created. + /// A value indicating whether this is the current published version. + /// A value indicating whether this is the current draft version. + /// A value indicating whether this version should be prevented from cleanup. + /// The username of the user who created this version. public ContentVersionMeta( int versionId, int contentId, @@ -31,25 +53,56 @@ public ContentVersionMeta( Username = username; } + /// + /// Gets the content identifier. + /// public int ContentId { get; } + /// + /// Gets the content type identifier. + /// public int ContentTypeId { get; } + /// + /// Gets the version identifier. + /// public int VersionId { get; } + /// + /// Gets the identifier of the user who created this version. + /// public int UserId { get; } + /// + /// Gets the date and time when this version was created. + /// public DateTime VersionDate { get; private set; } + /// + /// Gets a value indicating whether this is the current published version. + /// public bool CurrentPublishedVersion { get; } + /// + /// Gets a value indicating whether this is the current draft version. + /// public bool CurrentDraftVersion { get; } + /// + /// Gets a value indicating whether this version should be prevented from automatic cleanup. + /// public bool PreventCleanup { get; } + /// + /// Gets the username of the user who created this version. + /// public string? Username { get; } + /// public override string ToString() => $"ContentVersionMeta(versionId: {VersionId}, versionDate: {VersionDate:s}"; + /// + /// Ensures the is in UTC format. + /// public void EnsureUtc() => VersionDate = VersionDate.EnsureUtc(); } diff --git a/src/Umbraco.Core/Models/CultureImpact.cs b/src/Umbraco.Core/Models/CultureImpact.cs index a505206fbe64..c8534a36bb16 100644 --- a/src/Umbraco.Core/Models/CultureImpact.cs +++ b/src/Umbraco.Core/Models/CultureImpact.cs @@ -38,12 +38,30 @@ internal CultureImpact(string? culture, bool isDefault = false, bool allowEditIn AllowEditInvariantFromNonDefault = allowEditInvariantFromNonDefault; } + /// + /// Defines behavior flags for culture impact. + /// [Flags] public enum Behavior : byte { + /// + /// Impacts all cultures. + /// AllCultures = 1, + + /// + /// Impacts only the invariant culture. + /// InvariantCulture = 2, + + /// + /// Impacts an explicit culture. + /// ExplicitCulture = 4, + + /// + /// Impacts invariant properties. + /// InvariantProperties = 8, } @@ -107,6 +125,9 @@ public enum Behavior : byte !ImpactsAllCultures && (ImpactsOnlyDefaultCulture || AllowEditInvariantFromNonDefault); + /// + /// Gets the behavior flags for this culture impact. + /// public Behavior CultureBehavior { get @@ -205,5 +226,8 @@ public static CultureImpact Explicit(string? culture, bool isDefault) return new CultureImpact(culture, isDefault); } + /// + /// Gets a value indicating whether editing invariant properties from a non-default language is allowed. + /// public bool AllowEditInvariantFromNonDefault { get; } } diff --git a/src/Umbraco.Core/Models/DeepCloneHelper.cs b/src/Umbraco.Core/Models/DeepCloneHelper.cs index 7b9110f4324d..2e10550c32f6 100644 --- a/src/Umbraco.Core/Models/DeepCloneHelper.cs +++ b/src/Umbraco.Core/Models/DeepCloneHelper.cs @@ -5,6 +5,9 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Provides helper methods for deep cloning objects. +/// public static class DeepCloneHelper { /// @@ -213,6 +216,13 @@ public ClonePropertyInfo(PropertyInfo propertyInfo) public bool IsList => GenericListType != null; } + /// + /// Clones list items from a source collection to a target collection. + /// + /// The type of collection. + /// The type of entity in the collection. + /// The source collection to clone from. + /// The target collection to clone to. public static void CloneListItems(TList source, TList target) where TList : ICollection { diff --git a/src/Umbraco.Core/Models/DefaultPayloadModel.cs b/src/Umbraco.Core/Models/DefaultPayloadModel.cs index deccb4c42768..ef12ef05feae 100644 --- a/src/Umbraco.Core/Models/DefaultPayloadModel.cs +++ b/src/Umbraco.Core/Models/DefaultPayloadModel.cs @@ -1,6 +1,12 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents a default payload model containing an identifier. +/// internal sealed class DefaultPayloadModel { + /// + /// Gets or sets the unique identifier. + /// public Guid Id { get; set; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiBlockGridArea.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiBlockGridArea.cs index c3ac9155f0bf..73fd414b13fb 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiBlockGridArea.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiBlockGridArea.cs @@ -1,7 +1,17 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents an area within a block grid item in the Delivery API. +/// public sealed class ApiBlockGridArea { + /// + /// Initializes a new instance of the class. + /// + /// The alias of the area. + /// The number of rows the area spans. + /// The number of columns the area spans. + /// The block grid items within the area. public ApiBlockGridArea(string alias, int rowSpan, int columnSpan, IEnumerable items) { Alias = alias; @@ -10,11 +20,23 @@ public ApiBlockGridArea(string alias, int rowSpan, int columnSpan, IEnumerable + /// Gets the alias of the area. + /// public string Alias { get; } + /// + /// Gets the number of rows the area spans. + /// public int RowSpan { get; } + /// + /// Gets the number of columns the area spans. + /// public int ColumnSpan { get; } + /// + /// Gets the block grid items within the area. + /// public IEnumerable Items { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiBlockGridItem.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiBlockGridItem.cs index 8bb026e5dff6..cd748cc6469b 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiBlockGridItem.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiBlockGridItem.cs @@ -1,7 +1,19 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a block grid item in the Delivery API. +/// public sealed class ApiBlockGridItem : ApiBlockItem { + /// + /// Initializes a new instance of the class. + /// + /// The content element of the block. + /// The optional settings element of the block. + /// The number of rows the block spans. + /// The number of columns the block spans. + /// The number of columns in the block's area grid. + /// The areas within the block. public ApiBlockGridItem(IApiElement content, IApiElement? settings, int rowSpan, int columnSpan, int areaGridColumns, IEnumerable areas) : base(content, settings) { @@ -11,11 +23,23 @@ public ApiBlockGridItem(IApiElement content, IApiElement? settings, int rowSpan, Areas = areas; } + /// + /// Gets the number of rows the block spans. + /// public int RowSpan { get; } + /// + /// Gets the number of columns the block spans. + /// public int ColumnSpan { get; } + /// + /// Gets the number of columns in the block's area grid. + /// public int AreaGridColumns { get; } + /// + /// Gets the areas within the block. + /// public IEnumerable Areas { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiBlockGridModel.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiBlockGridModel.cs index 9fcd280082de..dfd40951ec57 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiBlockGridModel.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiBlockGridModel.cs @@ -1,14 +1,28 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a block grid model in the Delivery API. +/// public sealed class ApiBlockGridModel { + /// + /// Initializes a new instance of the class. + /// + /// The number of columns in the grid. + /// The block grid items in the model. public ApiBlockGridModel(int gridColumns, IEnumerable items) { GridColumns = gridColumns; Items = items; } + /// + /// Gets the number of columns in the grid. + /// public int GridColumns { get; } + /// + /// Gets the block grid items in the model. + /// public IEnumerable Items { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiBlockItem.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiBlockItem.cs index f6809ce2cf05..117d0d18496a 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiBlockItem.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiBlockItem.cs @@ -1,14 +1,28 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a block item in the Delivery API. +/// public class ApiBlockItem { + /// + /// Initializes a new instance of the class. + /// + /// The content element of the block. + /// The optional settings element of the block. public ApiBlockItem(IApiElement content, IApiElement? settings) { Content = content; Settings = settings; } + /// + /// Gets the content element of the block. + /// public IApiElement Content { get; } + /// + /// Gets the optional settings element of the block. + /// public IApiElement? Settings { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiBlockListModel.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiBlockListModel.cs index 8cf64909a555..ccbeb1cc6a34 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiBlockListModel.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiBlockListModel.cs @@ -1,8 +1,18 @@ namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a block list model in the Delivery API. +/// public sealed class ApiBlockListModel { + /// + /// Initializes a new instance of the class. + /// + /// The block items in the list. public ApiBlockListModel(IEnumerable items) => Items = items; + /// + /// Gets the block items in the list. + /// public IEnumerable Items { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiContent.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiContent.cs index 0b6830db6165..c2566905b034 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiContent.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiContent.cs @@ -1,7 +1,20 @@ namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents content in the Delivery API. +/// public class ApiContent : ApiElement, IApiContent { + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier of the content. + /// The name of the content. + /// The content type alias. + /// The date and time when the content was created. + /// The date and time when the content was last updated. + /// The route information for the content. + /// The property values of the content. public ApiContent(Guid id, string name, string contentType, DateTime createDate, DateTime updateDate, IApiContentRoute route, IDictionary properties) : base(id, contentType, properties) { @@ -11,11 +24,15 @@ public ApiContent(Guid id, string name, string contentType, DateTime createDate, Route = route; } + /// public string Name { get; } + /// public DateTime CreateDate { get; } + /// public DateTime UpdateDate { get; } + /// public IApiContentRoute Route { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiContentResponse.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiContentResponse.cs index ce57cf7417d8..6ec1ca3c6046 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiContentResponse.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiContentResponse.cs @@ -1,13 +1,33 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a content response in the Delivery API that includes culture-specific routes. +/// public class ApiContentResponse : ApiContent, IApiContentResponse { + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier of the content. + /// The name of the content. + /// The content type alias. + /// The date and time when the content was created. + /// The date and time when the content was last updated. + /// The route information for the content. + /// The property values of the content. + /// The culture-specific routes for the content. public ApiContentResponse(Guid id, string name, string contentType, DateTime createDate, DateTime updateDate, IApiContentRoute route, IDictionary properties, IDictionary cultures) : base(id, name, contentType, createDate, updateDate, route, properties) => Cultures = cultures; + /// + /// Gets the culture-specific routes for the content, keyed by culture code. + /// + /// + /// This property is serialized last for better readability of API responses. + /// // a little DX; by default this dictionary will be serialized as the first part of the response due to the inner workings of the serializer. // that's rather confusing to see as the very first thing when you get a response from the API, so let's move it downwards. // hopefully some day System.Text.Json will be able to order the properties differently in a centralized way. for now we have to live diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiContentRoute.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiContentRoute.cs index f5d56fbf2e2a..2f15f6c3a99e 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiContentRoute.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiContentRoute.cs @@ -1,16 +1,27 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a route to content in the Delivery API. +/// public sealed class ApiContentRoute : IApiContentRoute { + /// + /// Initializes a new instance of the class. + /// + /// The URL path of the content. + /// The start item for this route. public ApiContentRoute(string path, ApiContentStartItem startItem) { Path = path; StartItem = startItem; } + /// public string Path { get; } + /// public string? QueryString { get; set; } + /// public IApiContentStartItem StartItem { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiContentStartItem.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiContentStartItem.cs index 96a9b4964240..e203e0cfe285 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiContentStartItem.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiContentStartItem.cs @@ -1,14 +1,24 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a start item for content routing in the Delivery API. +/// public sealed class ApiContentStartItem : IApiContentStartItem { + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier of the start item. + /// The path of the start item. public ApiContentStartItem(Guid id, string path) { Id = id; Path = path; } + /// public Guid Id { get; } + /// public string Path { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiElement.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiElement.cs index d5941a1ed135..d461878ac698 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiElement.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiElement.cs @@ -2,8 +2,17 @@ namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a generic element in the Delivery API. +/// public class ApiElement : IApiElement { + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier of the element. + /// The content type alias of the element. + /// The property values of the element. public ApiElement(Guid id, string contentType, IDictionary properties) { Id = id; @@ -11,12 +20,20 @@ public ApiElement(Guid id, string contentType, IDictionary prop Properties = properties; } + /// public Guid Id { get; } + /// + /// Gets the content type alias of the element. + /// + /// + /// This property is serialized first to enable use as a discriminator field by System.Text.Json. + /// // Ensure the ContentType property is serialized first // This is needed so it can be used as a discriminator field by System.Text.Json [JsonPropertyOrder(-100)] public string ContentType { get; } + /// public IDictionary Properties { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiLink.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiLink.cs index cc146c8e2f68..b5fbaac4a7af 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiLink.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiLink.cs @@ -1,13 +1,44 @@ namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a link in the Delivery API. +/// public sealed class ApiLink { + /// + /// Creates a link to content. + /// + /// The title of the link. + /// The query string of the link. + /// The target attribute of the link (e.g., "_blank"). + /// The unique identifier of the destination content. + /// The content type alias of the destination. + /// The route information for the destination content. + /// A new instance representing a content link. public static ApiLink Content(string title, string? queryString, string? target, Guid destinationId, string destinationType, IApiContentRoute route) => new(LinkType.Content, url: null, queryString, title, target, destinationId, destinationType, route); + /// + /// Creates a link to media. + /// + /// The title of the link. + /// The URL of the media. + /// The query string of the link. + /// The target attribute of the link (e.g., "_blank"). + /// The unique identifier of the destination media. + /// The media type alias of the destination. + /// A new instance representing a media link. public static ApiLink Media(string title, string url, string? queryString, string? target, Guid destinationId, string destinationType) => new(LinkType.Media, url, queryString, title, target, destinationId, destinationType, route: null); + /// + /// Creates an external link. + /// + /// The title of the link. + /// The external URL. + /// The query string of the link. + /// The target attribute of the link (e.g., "_blank"). + /// A new instance representing an external link. public static ApiLink External(string? title, string url, string? queryString, string? target) => new(LinkType.External, url, queryString, title, target, null, null, null); @@ -23,19 +54,43 @@ private ApiLink(LinkType linkType, string? url, string? queryString, string? tit Route = route; } + /// + /// Gets the URL of the link. + /// public string? Url { get; } + /// + /// Gets the query string of the link. + /// public string? QueryString { get; } + /// + /// Gets the title of the link. + /// public string? Title { get; } + /// + /// Gets the target attribute of the link (e.g., "_blank"). + /// public string? Target { get; } + /// + /// Gets the unique identifier of the destination content or media. + /// public Guid? DestinationId { get; } + /// + /// Gets the content or media type alias of the destination. + /// public string? DestinationType { get; } + /// + /// Gets the route information for the destination content. + /// public IApiContentRoute? Route { get; } + /// + /// Gets the type of the link. + /// public LinkType LinkType { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ApiMedia.cs b/src/Umbraco.Core/Models/DeliveryApi/ApiMedia.cs index a161b69e2ad7..68ae23dcf597 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ApiMedia.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ApiMedia.cs @@ -1,7 +1,22 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents media in the Delivery API. +/// public sealed class ApiMedia : IApiMedia { + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier of the media. + /// The name of the media. + /// The media type alias. + /// The URL of the media. + /// The file extension of the media. + /// The width of the media in pixels. + /// The height of the media in pixels. + /// The size of the media in bytes. + /// The property values of the media. public ApiMedia(Guid id, string name, string mediaType, string url, string? extension, int? width, int? height, int? bytes, IDictionary properties) { Id = id; @@ -15,21 +30,30 @@ public ApiMedia(Guid id, string name, string mediaType, string url, string? exte Properties = properties; } + /// public Guid Id { get; } + /// public string Name { get; } + /// public string MediaType { get; } + /// public string Url { get; } + /// public string? Extension { get; } + /// public int? Width { get; } + /// public int? Height { get; } + /// public int? Bytes { get; } + /// public IDictionary Properties { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/IApiContent.cs b/src/Umbraco.Core/Models/DeliveryApi/IApiContent.cs index 9192cbe7d598..7c3139972afa 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/IApiContent.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/IApiContent.cs @@ -1,12 +1,27 @@ namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents content in the Delivery API. +/// public interface IApiContent : IApiElement { + /// + /// Gets the name of the content. + /// string? Name { get; } + /// + /// Gets the date and time when the content was created. + /// public DateTime CreateDate { get; } + /// + /// Gets the date and time when the content was last updated. + /// public DateTime UpdateDate { get; } + /// + /// Gets the route information for the content. + /// IApiContentRoute Route { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/IApiContentResponse.cs b/src/Umbraco.Core/Models/DeliveryApi/IApiContentResponse.cs index fe7d80ce0bbd..8ad731ed69f9 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/IApiContentResponse.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/IApiContentResponse.cs @@ -1,6 +1,12 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a content response in the Delivery API that includes culture-specific routes. +/// public interface IApiContentResponse : IApiContent { + /// + /// Gets the culture-specific routes for the content, keyed by culture code. + /// IDictionary Cultures { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/IApiContentRoute.cs b/src/Umbraco.Core/Models/DeliveryApi/IApiContentRoute.cs index cfc0b2984a29..49e459dc1922 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/IApiContentRoute.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/IApiContentRoute.cs @@ -1,13 +1,25 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a route to content in the Delivery API. +/// public interface IApiContentRoute { + /// + /// Gets the URL path of the content. + /// string Path { get; } + /// + /// Gets or sets the query string associated with the route. + /// public string? QueryString { get => null; set { } } + /// + /// Gets the start item for this route. + /// IApiContentStartItem StartItem { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/IApiContentStartItem.cs b/src/Umbraco.Core/Models/DeliveryApi/IApiContentStartItem.cs index 7cf117c647b9..92da6d7f3eb1 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/IApiContentStartItem.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/IApiContentStartItem.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a start item for content routing in the Delivery API. +/// public interface IApiContentStartItem { + /// + /// Gets the unique identifier of the start item. + /// Guid Id { get; } + /// + /// Gets the path of the start item. + /// string Path { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/IApiElement.cs b/src/Umbraco.Core/Models/DeliveryApi/IApiElement.cs index e62525aa3484..3a81fa17d04d 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/IApiElement.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/IApiElement.cs @@ -2,14 +2,29 @@ namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a generic element in the Delivery API. +/// public interface IApiElement { + /// + /// Gets the unique identifier of the element. + /// Guid Id { get; } + /// + /// Gets the content type alias of the element. + /// + /// + /// This property is serialized first to enable use as a discriminator field by System.Text.Json. + /// // Ensure the ContentType property is serialized first // This is needed so it can be used as a discriminator field by System.Text.Json [JsonPropertyOrder(-100)] string ContentType { get; } + /// + /// Gets the property values of the element. + /// IDictionary Properties { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/IApiMedia.cs b/src/Umbraco.Core/Models/DeliveryApi/IApiMedia.cs index f30b7dbc198b..86654771c432 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/IApiMedia.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/IApiMedia.cs @@ -1,22 +1,52 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents media in the Delivery API. +/// public interface IApiMedia { + /// + /// Gets the unique identifier of the media. + /// Guid Id { get; } + /// + /// Gets the name of the media. + /// string Name { get; } + /// + /// Gets the media type alias. + /// string MediaType { get; } + /// + /// Gets the URL of the media. + /// string Url { get; } + /// + /// Gets the file extension of the media. + /// string? Extension { get; } + /// + /// Gets the width of the media in pixels, if applicable. + /// int? Width { get; } + /// + /// Gets the height of the media in pixels, if applicable. + /// int? Height { get; } + /// + /// Gets the size of the media in bytes. + /// int? Bytes { get; } + /// + /// Gets the property values of the media. + /// IDictionary Properties { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/IApiMediaWithCrops.cs b/src/Umbraco.Core/Models/DeliveryApi/IApiMediaWithCrops.cs index 073ea89ca301..4bd63f34bea7 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/IApiMediaWithCrops.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/IApiMediaWithCrops.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents media with image cropping information in the Delivery API. +/// public interface IApiMediaWithCrops : IApiMedia { + /// + /// Gets the focal point of the image. + /// public ImageFocalPoint? FocalPoint { get; } + /// + /// Gets the defined image crops. + /// public IEnumerable? Crops { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/IApiMediaWithCropsResponse.cs b/src/Umbraco.Core/Models/DeliveryApi/IApiMediaWithCropsResponse.cs index 34912bbec779..a7fe63aff1c9 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/IApiMediaWithCropsResponse.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/IApiMediaWithCropsResponse.cs @@ -1,10 +1,22 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a media response with cropping information in the Delivery API. +/// public interface IApiMediaWithCropsResponse : IApiMediaWithCrops { + /// + /// Gets the path of the media file. + /// public string Path { get; } + /// + /// Gets the date and time when the media was created. + /// public DateTime CreateDate { get; } + /// + /// Gets the date and time when the media was last updated. + /// public DateTime UpdateDate { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/IRichTextElement.cs b/src/Umbraco.Core/Models/DeliveryApi/IRichTextElement.cs index ab97ba7f91ba..01321f6572f0 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/IRichTextElement.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/IRichTextElement.cs @@ -1,6 +1,12 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents an element within rich text content in the Delivery API. +/// public interface IRichTextElement { + /// + /// Gets the tag name of the element (e.g., "p", "h1", "#text", "#root"). + /// string Tag { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ImageCrop.cs b/src/Umbraco.Core/Models/DeliveryApi/ImageCrop.cs index eda02d8fa72b..f6978323dda9 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ImageCrop.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ImageCrop.cs @@ -1,7 +1,17 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents an image crop definition in the Delivery API. +/// public class ImageCrop { + /// + /// Initializes a new instance of the class. + /// + /// The alias of the crop. + /// The width of the crop in pixels. + /// The height of the crop in pixels. + /// The coordinates of the crop area. public ImageCrop(string? alias, int width, int height, ImageCropCoordinates? coordinates) { Alias = alias; @@ -10,11 +20,23 @@ public ImageCrop(string? alias, int width, int height, ImageCropCoordinates? coo Coordinates = coordinates; } + /// + /// Gets the alias of the crop. + /// public string? Alias { get; } + /// + /// Gets the width of the crop in pixels. + /// public int Width { get; } + /// + /// Gets the height of the crop in pixels. + /// public int Height { get; } + /// + /// Gets the coordinates of the crop area. + /// public ImageCropCoordinates? Coordinates { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ImageCropCoordinates.cs b/src/Umbraco.Core/Models/DeliveryApi/ImageCropCoordinates.cs index 48ad0b62019c..9ab604612d19 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ImageCropCoordinates.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ImageCropCoordinates.cs @@ -1,7 +1,17 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents the coordinates of an image crop area in the Delivery API. +/// public class ImageCropCoordinates { + /// + /// Initializes a new instance of the class. + /// + /// The X coordinate of the top-left corner. + /// The Y coordinate of the top-left corner. + /// The X coordinate of the bottom-right corner. + /// The Y coordinate of the bottom-right corner. public ImageCropCoordinates(decimal x1, decimal y1, decimal x2, decimal y2) { X1 = x1; @@ -10,11 +20,23 @@ public ImageCropCoordinates(decimal x1, decimal y1, decimal x2, decimal y2) Y2 = y2; } + /// + /// Gets the X coordinate of the top-left corner. + /// public decimal X1 { get; } + /// + /// Gets the Y coordinate of the top-left corner. + /// public decimal Y1 { get; } + /// + /// Gets the X coordinate of the bottom-right corner. + /// public decimal X2 { get; } + /// + /// Gets the Y coordinate of the bottom-right corner. + /// public decimal Y2 { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ImageFocalPoint.cs b/src/Umbraco.Core/Models/DeliveryApi/ImageFocalPoint.cs index d3ae5e65cd7b..4ad8b158437b 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ImageFocalPoint.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ImageFocalPoint.cs @@ -1,14 +1,34 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents the focal point of an image in the Delivery API. +/// public class ImageFocalPoint { + /// + /// Initializes a new instance of the class. + /// + /// The horizontal position of the focal point (0-1, where 0 is left edge and 1 is right edge). + /// The vertical position of the focal point (0-1, where 0 is top edge and 1 is bottom edge). public ImageFocalPoint(decimal left, decimal top) { Left = left; Top = top; } + /// + /// Gets the horizontal position of the focal point. + /// + /// + /// Value ranges from 0 (left edge) to 1 (right edge). + /// public decimal Left { get; } + /// + /// Gets the vertical position of the focal point. + /// + /// + /// Value ranges from 0 (top edge) to 1 (bottom edge). + /// public decimal Top { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/ProtectedAccess.cs b/src/Umbraco.Core/Models/DeliveryApi/ProtectedAccess.cs index f87db9d79537..19cdc0b0e048 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/ProtectedAccess.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/ProtectedAccess.cs @@ -1,16 +1,33 @@ namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents protected access information for content in the Delivery API. +/// public sealed class ProtectedAccess { + /// + /// Gets a instance representing no protection. + /// public static ProtectedAccess None => new(null, null); + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier of the member who has access. + /// The member roles that have access. public ProtectedAccess(Guid? memberKey, string[]? memberRoles) { MemberKey = memberKey; MemberRoles = memberRoles; } + /// + /// Gets the unique identifier of the member who has access. + /// public Guid? MemberKey { get; } + /// + /// Gets the member roles that have access. + /// public string[]? MemberRoles { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/RichTextGenericElement.cs b/src/Umbraco.Core/Models/DeliveryApi/RichTextGenericElement.cs index 70e454567d62..3166d978c15c 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/RichTextGenericElement.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/RichTextGenericElement.cs @@ -1,7 +1,16 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a generic HTML element within rich text content in the Delivery API. +/// public sealed class RichTextGenericElement : IRichTextElement { + /// + /// Initializes a new instance of the class. + /// + /// The tag name of the element (e.g., "p", "h1", "strong"). + /// The HTML attributes of the element. + /// The child elements of the element. public RichTextGenericElement(string tag, Dictionary attributes, IEnumerable elements) { Tag = tag; @@ -9,9 +18,16 @@ public RichTextGenericElement(string tag, Dictionary attributes, Elements = elements; } + /// public string Tag { get; } + /// + /// Gets the HTML attributes of the element. + /// public Dictionary Attributes { get; } + /// + /// Gets the child elements of the element. + /// public IEnumerable Elements { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/RichTextModel.cs b/src/Umbraco.Core/Models/DeliveryApi/RichTextModel.cs index 6280343c034c..3491f88db873 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/RichTextModel.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/RichTextModel.cs @@ -1,10 +1,23 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a rich text model in the Delivery API. +/// public class RichTextModel { + /// + /// Gets or sets the HTML markup of the rich text content. + /// public required string Markup { get; set; } + /// + /// Gets or sets the block items embedded in the rich text content. + /// public required IEnumerable Blocks { get; set; } + /// + /// Creates an empty instance. + /// + /// A new instance with empty markup and no blocks. public static RichTextModel Empty() => new() { Markup = string.Empty, Blocks = Array.Empty() }; } diff --git a/src/Umbraco.Core/Models/DeliveryApi/RichTextRootElement.cs b/src/Umbraco.Core/Models/DeliveryApi/RichTextRootElement.cs index 8174d288d2f2..2137aa249dad 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/RichTextRootElement.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/RichTextRootElement.cs @@ -1,7 +1,16 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents the root element of rich text content in the Delivery API. +/// public sealed class RichTextRootElement : IRichTextElement { + /// + /// Initializes a new instance of the class. + /// + /// The HTML attributes of the root element. + /// The child elements of the root element. + /// The block items embedded in the rich text content. public RichTextRootElement(Dictionary attributes, IEnumerable elements, IEnumerable blocks) { Attributes = attributes; @@ -9,11 +18,21 @@ public RichTextRootElement(Dictionary attributes, IEnumerable public string Tag => "#root"; + /// + /// Gets the HTML attributes of the root element. + /// public Dictionary Attributes { get; } + /// + /// Gets the child elements of the root element. + /// public IEnumerable Elements { get; } + /// + /// Gets the block items embedded in the rich text content. + /// public IEnumerable Blocks { get; } } diff --git a/src/Umbraco.Core/Models/DeliveryApi/RichTextTextElement.cs b/src/Umbraco.Core/Models/DeliveryApi/RichTextTextElement.cs index 3900d7b3d691..e986ada95f54 100644 --- a/src/Umbraco.Core/Models/DeliveryApi/RichTextTextElement.cs +++ b/src/Umbraco.Core/Models/DeliveryApi/RichTextTextElement.cs @@ -1,11 +1,22 @@ -namespace Umbraco.Cms.Core.Models.DeliveryApi; +namespace Umbraco.Cms.Core.Models.DeliveryApi; +/// +/// Represents a text node within rich text content in the Delivery API. +/// public sealed class RichTextTextElement : IRichTextElement { + /// + /// Initializes a new instance of the class. + /// + /// The text content of the element. public RichTextTextElement(string text) => Text = text; + /// + /// Gets the text content of the element. + /// public string Text { get; } + /// public string Tag => "#text"; } diff --git a/src/Umbraco.Core/Models/DictionaryItem.cs b/src/Umbraco.Core/Models/DictionaryItem.cs index 0f0d2c3d0ba7..1fdfd500e592 100644 --- a/src/Umbraco.Core/Models/DictionaryItem.cs +++ b/src/Umbraco.Core/Models/DictionaryItem.cs @@ -22,11 +22,20 @@ private static readonly DelegateEqualityComparer _translations; + /// + /// Initializes a new instance of the class with the specified key. + /// + /// The key for the dictionary item. public DictionaryItem(string itemKey) : this(null, itemKey) { } + /// + /// Initializes a new instance of the class with a parent and key. + /// + /// The unique identifier of the parent dictionary item. + /// The key for the dictionary item. public DictionaryItem(Guid? parentId, string itemKey) { _parentId = parentId; diff --git a/src/Umbraco.Core/Models/DictionaryItemExtensions.cs b/src/Umbraco.Core/Models/DictionaryItemExtensions.cs index 84f6b74fc0f1..eb54aaa582d6 100644 --- a/src/Umbraco.Core/Models/DictionaryItemExtensions.cs +++ b/src/Umbraco.Core/Models/DictionaryItemExtensions.cs @@ -2,6 +2,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class DictionaryItemExtensions { /// diff --git a/src/Umbraco.Core/Models/DictionaryTranslation.cs b/src/Umbraco.Core/Models/DictionaryTranslation.cs index 70b75bd44bea..0ab2f176932c 100644 --- a/src/Umbraco.Core/Models/DictionaryTranslation.cs +++ b/src/Umbraco.Core/Models/DictionaryTranslation.cs @@ -13,16 +13,28 @@ public class DictionaryTranslation : EntityBase, IDictionaryTranslation // note: this will be memberwise cloned private string _value; + /// + /// Initializes a new instance of the class. + /// + /// The language for this translation. + /// The translated text. public DictionaryTranslation(ILanguage language, string value) { LanguageIsoCode = language.IsoCode; _value = value; } + /// + /// Initializes a new instance of the class with a unique identifier. + /// + /// The language for this translation. + /// The translated text. + /// The unique identifier for the translation. public DictionaryTranslation(ILanguage language, string value, Guid uniqueId) : this(language, value) => Key = uniqueId; + /// public string LanguageIsoCode { get; private set; } /// diff --git a/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs b/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs index 51910815b50e..067307423316 100644 --- a/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs +++ b/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs @@ -9,6 +9,11 @@ namespace Umbraco.Cms.Core.Models.Editors; /// public class ContentPropertyData { + /// + /// Initializes a new instance of the class. + /// + /// The value submitted for the property. + /// The data type configuration for the property. public ContentPropertyData(object? value, object? dataTypeConfiguration) { Value = value; diff --git a/src/Umbraco.Core/Models/Email/EmailMessage.cs b/src/Umbraco.Core/Models/Email/EmailMessage.cs index 141928541767..0c3537e9d3c3 100644 --- a/src/Umbraco.Core/Models/Email/EmailMessage.cs +++ b/src/Umbraco.Core/Models/Email/EmailMessage.cs @@ -1,12 +1,35 @@ namespace Umbraco.Cms.Core.Models.Email; +/// +/// Represents an email message with sender, recipients, subject, body, and optional attachments. +/// public class EmailMessage { + /// + /// Initializes a new instance of the class with a single recipient. + /// + /// The sender's email address. + /// The recipient's email address. + /// The email subject. + /// The email body content. + /// A value indicating whether the body is HTML formatted. public EmailMessage(string? from, string? to, string? subject, string? body, bool isBodyHtml) : this(from, new[] { to }, null, null, null, subject, body, isBodyHtml, null) { } + /// + /// Initializes a new instance of the class with multiple recipients and optional CC, BCC, and reply-to addresses. + /// + /// The sender's email address. + /// The array of recipient email addresses. + /// The array of CC email addresses. + /// The array of BCC email addresses. + /// The array of reply-to email addresses. + /// The email subject. + /// The email body content. + /// A value indicating whether the body is HTML formatted. + /// The collection of email attachments. public EmailMessage( string? from, string?[] to, @@ -33,26 +56,63 @@ public EmailMessage( Attachments = attachments?.ToList(); } + /// + /// Gets the sender's email address. + /// public string? From { get; } + /// + /// Gets the array of recipient email addresses. + /// public string?[] To { get; } + /// + /// Gets the array of CC email addresses. + /// public string[]? Cc { get; } + /// + /// Gets the array of BCC email addresses. + /// public string[]? Bcc { get; } + /// + /// Gets the array of reply-to email addresses. + /// public string[]? ReplyTo { get; } + /// + /// Gets the email subject. + /// public string? Subject { get; } + /// + /// Gets the email body content. + /// public string? Body { get; } + /// + /// Gets a value indicating whether the body is HTML formatted. + /// public bool IsBodyHtml { get; } + /// + /// Gets the collection of email attachments. + /// public IList? Attachments { get; } + /// + /// Gets a value indicating whether the email has any attachments. + /// public bool HasAttachments => Attachments != null && Attachments.Count > 0; + /// + /// Validates that the specified string argument is not null or empty. + /// + /// The string argument to validate. + /// The name of the argument for exception messages. + /// Thrown when the argument is null. + /// Thrown when the argument is empty. private static void ArgumentIsNotNullOrEmpty(string? arg, string argName) { if (arg == null) @@ -66,6 +126,13 @@ private static void ArgumentIsNotNullOrEmpty(string? arg, string argName) } } + /// + /// Validates that the specified string array argument is not null, empty, or contains only null or empty elements. + /// + /// The string array argument to validate. + /// The name of the argument for exception messages. + /// Thrown when the argument is null. + /// Thrown when the argument is an empty array or contains only null or empty elements. private static void ArgumentIsNotNullOrEmpty(string?[]? arg, string argName) { if (arg == null) diff --git a/src/Umbraco.Core/Models/Email/EmailMessageAttachment.cs b/src/Umbraco.Core/Models/Email/EmailMessageAttachment.cs index 96c52ef9e751..a853acc79406 100644 --- a/src/Umbraco.Core/Models/Email/EmailMessageAttachment.cs +++ b/src/Umbraco.Core/Models/Email/EmailMessageAttachment.cs @@ -1,14 +1,28 @@ namespace Umbraco.Cms.Core.Models.Email; +/// +/// Represents an email attachment with its content stream and file name. +/// public class EmailMessageAttachment { + /// + /// Initializes a new instance of the class. + /// + /// The stream containing the attachment content. + /// The name of the attachment file. public EmailMessageAttachment(Stream stream, string fileName) { Stream = stream; FileName = fileName; } + /// + /// Gets the stream containing the attachment content. + /// public Stream Stream { get; } + /// + /// Gets the name of the attachment file. + /// public string FileName { get; } } diff --git a/src/Umbraco.Core/Models/Email/NotificationEmailAddress.cs b/src/Umbraco.Core/Models/Email/NotificationEmailAddress.cs index c9488f0798de..fcacd2644425 100644 --- a/src/Umbraco.Core/Models/Email/NotificationEmailAddress.cs +++ b/src/Umbraco.Core/Models/Email/NotificationEmailAddress.cs @@ -5,13 +5,24 @@ namespace Umbraco.Cms.Core.Models.Email; /// public class NotificationEmailAddress { + /// + /// Initializes a new instance of the class. + /// + /// The email address. + /// The display name for the email address. public NotificationEmailAddress(string address, string displayName) { Address = address; DisplayName = displayName; } + /// + /// Gets the display name for the email address. + /// public string DisplayName { get; } + /// + /// Gets the email address. + /// public string Address { get; } } diff --git a/src/Umbraco.Core/Models/Email/NotificationEmailModel.cs b/src/Umbraco.Core/Models/Email/NotificationEmailModel.cs index abfea360d919..5d0ab4de1f40 100644 --- a/src/Umbraco.Core/Models/Email/NotificationEmailModel.cs +++ b/src/Umbraco.Core/Models/Email/NotificationEmailModel.cs @@ -5,6 +5,18 @@ namespace Umbraco.Cms.Core.Models.Email; /// public class NotificationEmailModel { + /// + /// Initializes a new instance of the class. + /// + /// The sender's email address. + /// The collection of recipient email addresses. + /// The collection of CC email addresses. + /// The collection of BCC email addresses. + /// The collection of reply-to email addresses. + /// The email subject. + /// The email body content. + /// The collection of email attachments. + /// A value indicating whether the body is HTML formatted. public NotificationEmailModel( NotificationEmailAddress? from, IEnumerable? to, @@ -27,23 +39,53 @@ public NotificationEmailModel( Attachments = attachments?.ToList(); } + /// + /// Gets the sender's email address. + /// public NotificationEmailAddress? From { get; } + /// + /// Gets the collection of recipient email addresses. + /// public IEnumerable? To { get; } + /// + /// Gets the collection of CC email addresses. + /// public IEnumerable? Cc { get; } + /// + /// Gets the collection of BCC email addresses. + /// public IEnumerable? Bcc { get; } + /// + /// Gets the collection of reply-to email addresses. + /// public IEnumerable? ReplyTo { get; } + /// + /// Gets the email subject. + /// public string? Subject { get; } + /// + /// Gets the email body content. + /// public string? Body { get; } + /// + /// Gets a value indicating whether the body is HTML formatted. + /// public bool IsBodyHtml { get; } + /// + /// Gets the collection of email attachments. + /// public IList? Attachments { get; } + /// + /// Gets a value indicating whether the email has any attachments. + /// public bool HasAttachments => Attachments != null && Attachments.Count > 0; } diff --git a/src/Umbraco.Core/Models/Entities/BeingDirtyBase.cs b/src/Umbraco.Core/Models/Entities/BeingDirtyBase.cs index 7a9764703ee9..c5e0a12762ba 100644 --- a/src/Umbraco.Core/Models/Entities/BeingDirtyBase.cs +++ b/src/Umbraco.Core/Models/Entities/BeingDirtyBase.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using System.ComponentModel; using System.Runtime.Serialization; @@ -85,6 +85,9 @@ public virtual IEnumerable GetWereDirtyProperties() => /// public event PropertyChangedEventHandler? PropertyChanged; + /// + /// Clears all event handlers attached to the event. + /// protected void ClearPropertyChangedEvents() => PropertyChanged = null; /// diff --git a/src/Umbraco.Core/Models/Entities/ContentEntitySlim.cs b/src/Umbraco.Core/Models/Entities/ContentEntitySlim.cs index 065d35229c5a..0d3bdef0997e 100644 --- a/src/Umbraco.Core/Models/Entities/ContentEntitySlim.cs +++ b/src/Umbraco.Core/Models/Entities/ContentEntitySlim.cs @@ -11,6 +11,7 @@ public class ContentEntitySlim : EntitySlim, IContentEntitySlim /// public Guid ContentTypeKey { get; set; } + /// public Guid? ListViewKey { get; set; } /// diff --git a/src/Umbraco.Core/Models/Entities/DocumentEntitySlim.cs b/src/Umbraco.Core/Models/Entities/DocumentEntitySlim.cs index a5c0ca23c990..e4ae5a5a13ed 100644 --- a/src/Umbraco.Core/Models/Entities/DocumentEntitySlim.cs +++ b/src/Umbraco.Core/Models/Entities/DocumentEntitySlim.cs @@ -32,6 +32,7 @@ public IEnumerable EditedCultures set => _editedCultures = value; } + /// public ContentVariation Variations { get; set; } /// diff --git a/src/Umbraco.Core/Models/Entities/EntityBase.cs b/src/Umbraco.Core/Models/Entities/EntityBase.cs index df60d97a1e21..87b600140180 100644 --- a/src/Umbraco.Core/Models/Entities/EntityBase.cs +++ b/src/Umbraco.Core/Models/Entities/EntityBase.cs @@ -84,12 +84,19 @@ public virtual void ResetIdentity() _hasIdentity = false; } + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// true if the specified entity is equal to this instance; otherwise, false. public virtual bool Equals(EntityBase? other) => other != null && (ReferenceEquals(this, other) || SameIdentityAs(other)); + /// public override bool Equals(object? obj) => obj != null && (ReferenceEquals(this, obj) || SameIdentityAs(obj as EntityBase)); + /// public override int GetHashCode() { unchecked @@ -101,6 +108,11 @@ public override int GetHashCode() } } + /// + /// Determines whether this entity has the same identity as another entity. + /// + /// The other entity to compare. + /// true if the entities have the same identity; otherwise, false. private bool SameIdentityAs(EntityBase? other) { if (other == null) @@ -119,6 +131,7 @@ private bool SameIdentityAs(EntityBase? other) return GetType() == other.GetType() && HasIdentity && other.HasIdentity && Id == other.Id; } + /// public object DeepClone() { // memberwise-clone (ie shallow clone) the entity diff --git a/src/Umbraco.Core/Models/Entities/EntityExtensions.cs b/src/Umbraco.Core/Models/Entities/EntityExtensions.cs index 2fe26b78fbe3..16c8fdfd08c9 100644 --- a/src/Umbraco.Core/Models/Entities/EntityExtensions.cs +++ b/src/Umbraco.Core/Models/Entities/EntityExtensions.cs @@ -5,6 +5,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class EntityExtensions { /// diff --git a/src/Umbraco.Core/Models/Entities/EntitySlim.cs b/src/Umbraco.Core/Models/Entities/EntitySlim.cs index 494e6abf6e43..5e0bd01703b8 100644 --- a/src/Umbraco.Core/Models/Entities/EntitySlim.cs +++ b/src/Umbraco.Core/Models/Entities/EntitySlim.cs @@ -1,3 +1,4 @@ +using System.ComponentModel; using System.Runtime.Serialization; namespace Umbraco.Cms.Core.Models.Entities; @@ -96,13 +97,38 @@ public void SetParent(ITreeEntity? parent) => [DataMember] public virtual bool IsContainer { get; set; } + /// + /// Occurs when a property value changes. + /// + /// + /// This event is declared to satisfy the interface but is never raised + /// since does not track changes. + /// + public event PropertyChangedEventHandler? PropertyChanged; + + /// + /// Not implemented. Always throws . + /// + /// Always thrown as this method is not implemented. + public void DisableChangeTracking() => throw new InvalidOperationException("This method won't be implemented."); + + /// + /// Not implemented. Always throws . + /// + /// Always thrown as this method is not implemented. + public void EnableChangeTracking() => throw new InvalidOperationException("This method won't be implemented."); + #region IDeepCloneable - /// + /// + /// Not implemented. Always throws . + /// + /// Always thrown as this method is not implemented. public object DeepClone() => throw new InvalidOperationException("This method won't be implemented."); #endregion + /// public void ResetIdentity() { Id = default; @@ -113,26 +139,66 @@ public void ResetIdentity() // IEntitySlim does *not* track changes, but since it indirectly implements IUmbracoEntity, // and therefore IRememberBeingDirty, we have to have those methods - which all throw. + + /// + /// Not implemented. Always throws . + /// + /// Always thrown as this method is not implemented. public bool IsDirty() => throw new InvalidOperationException("This method won't be implemented."); + /// + /// Not implemented. Always throws . + /// + /// The property name. + /// Always thrown as this method is not implemented. public bool IsPropertyDirty(string propName) => throw new InvalidOperationException("This method won't be implemented."); + /// + /// Not implemented. Always throws . + /// + /// Always thrown as this method is not implemented. public IEnumerable GetDirtyProperties() => throw new InvalidOperationException("This method won't be implemented."); + /// + /// Not implemented. Always throws . + /// + /// Always thrown as this method is not implemented. public void ResetDirtyProperties() => throw new InvalidOperationException("This method won't be implemented."); + /// + /// Not implemented. Always throws . + /// + /// Always thrown as this method is not implemented. public bool WasDirty() => throw new InvalidOperationException("This method won't be implemented."); + /// + /// Not implemented. Always throws . + /// + /// The property name. + /// Always thrown as this method is not implemented. public bool WasPropertyDirty(string propertyName) => throw new InvalidOperationException("This method won't be implemented."); + /// + /// Not implemented. Always throws . + /// + /// Always thrown as this method is not implemented. public void ResetWereDirtyProperties() => throw new InvalidOperationException("This method won't be implemented."); + /// + /// Not implemented. Always throws . + /// + /// A value indicating whether to remember dirty properties. + /// Always thrown as this method is not implemented. public void ResetDirtyProperties(bool rememberDirty) => throw new InvalidOperationException("This method won't be implemented."); + /// + /// Not implemented. Always throws . + /// + /// Always thrown as this method is not implemented. public IEnumerable GetWereDirtyProperties() => throw new InvalidOperationException("This method won't be implemented."); diff --git a/src/Umbraco.Core/Models/Entities/ICanBeDirty.cs b/src/Umbraco.Core/Models/Entities/ICanBeDirty.cs index 23d50d54d918..c405f3eb17b2 100644 --- a/src/Umbraco.Core/Models/Entities/ICanBeDirty.cs +++ b/src/Umbraco.Core/Models/Entities/ICanBeDirty.cs @@ -7,6 +7,9 @@ namespace Umbraco.Cms.Core.Models.Entities; /// public interface ICanBeDirty { + /// + /// Occurs when a property value changes. + /// event PropertyChangedEventHandler PropertyChanged; /// diff --git a/src/Umbraco.Core/Models/Entities/IEntity.cs b/src/Umbraco.Core/Models/Entities/IEntity.cs index 859975adfb9d..23fb97086de2 100644 --- a/src/Umbraco.Core/Models/Entities/IEntity.cs +++ b/src/Umbraco.Core/Models/Entities/IEntity.cs @@ -42,5 +42,8 @@ public interface IEntity : IDeepCloneable /// bool HasIdentity { get; } + /// + /// Resets the entity identity by clearing the and properties. + /// void ResetIdentity(); } diff --git a/src/Umbraco.Core/Models/Entities/IMemberEntitySlim.cs b/src/Umbraco.Core/Models/Entities/IMemberEntitySlim.cs index 0ded5370355f..f1a7eac00dfb 100644 --- a/src/Umbraco.Core/Models/Entities/IMemberEntitySlim.cs +++ b/src/Umbraco.Core/Models/Entities/IMemberEntitySlim.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models.Entities; +/// +/// Represents a lightweight member entity, managed by the entity service. +/// public interface IMemberEntitySlim : IContentEntitySlim { } diff --git a/src/Umbraco.Core/Models/Entities/MediaEntitySlim.cs b/src/Umbraco.Core/Models/Entities/MediaEntitySlim.cs index fb73e2332dd1..c8f8ce6a19ff 100644 --- a/src/Umbraco.Core/Models/Entities/MediaEntitySlim.cs +++ b/src/Umbraco.Core/Models/Entities/MediaEntitySlim.cs @@ -5,5 +5,6 @@ namespace Umbraco.Cms.Core.Models.Entities; /// public class MediaEntitySlim : ContentEntitySlim, IMediaEntitySlim { + /// public string? MediaPath { get; set; } } diff --git a/src/Umbraco.Core/Models/Entities/MemberEntitySlim.cs b/src/Umbraco.Core/Models/Entities/MemberEntitySlim.cs index 923fef2477e7..d2d499463f2b 100644 --- a/src/Umbraco.Core/Models/Entities/MemberEntitySlim.cs +++ b/src/Umbraco.Core/Models/Entities/MemberEntitySlim.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models.Entities; +/// +/// Implements . +/// public class MemberEntitySlim : ContentEntitySlim, IMemberEntitySlim { } diff --git a/src/Umbraco.Core/Models/EntityDataPickerValue.cs b/src/Umbraco.Core/Models/EntityDataPickerValue.cs index 2b4274c3ef71..c97d0ae805da 100644 --- a/src/Umbraco.Core/Models/EntityDataPickerValue.cs +++ b/src/Umbraco.Core/Models/EntityDataPickerValue.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a value selected from an entity data picker. +/// public sealed class EntityDataPickerValue { + /// + /// Gets or sets the collection of selected entity identifiers. + /// public required IEnumerable Ids { get; set; } + /// + /// Gets or sets the data source from which the entities were selected. + /// public required string DataSource { get; set; } } diff --git a/src/Umbraco.Core/Models/File.cs b/src/Umbraco.Core/Models/File.cs index 8abfdd1ef559..907d5da89856 100644 --- a/src/Umbraco.Core/Models/File.cs +++ b/src/Umbraco.Core/Models/File.cs @@ -20,6 +20,11 @@ public abstract class File : EntityBase, IFile private string? _name; private string _path; + /// + /// Initializes a new instance of the class with the specified path. + /// + /// The path to the file. + /// An optional function to lazily load file content. protected File(string path, Func? getFileContent = null) { _path = SanitizePath(path); @@ -28,6 +33,9 @@ protected File(string path, Func? getFileContent = null) _content = getFileContent != null ? null : string.Empty; } + /// + /// Gets or sets the function used to lazily load file content. + /// public Func? GetFileContent { get; set; } /// @@ -122,11 +130,14 @@ public virtual string? Content /// public string? VirtualPath { get; set; } - // Don't strip the start - this was a bug fixed in 7.3, see ScriptRepositoryTests.PathTests - // .TrimStart(System.IO.Path.DirectorySeparatorChar) - // .TrimStart('/'); - // this exists so that class that manage name and alias differently, eg Template, - // can implement their own cloning - (though really, not sure it's even needed) + /// + /// Performs deep cloning of the name and alias properties. + /// + /// The cloned file instance. + /// + /// This exists so that classes that manage name and alias differently, e.g. Template, + /// can implement their own cloning. + /// protected virtual void DeepCloneNameAndAlias(File clone) { // set fields that have a lazy value, by forcing evaluation of the lazy @@ -139,6 +150,7 @@ private static string SanitizePath(string path) => .Replace('\\', System.IO.Path.DirectorySeparatorChar) .Replace('/', System.IO.Path.DirectorySeparatorChar); + /// protected override void PerformDeepClone(object clone) { base.PerformDeepClone(clone); diff --git a/src/Umbraco.Core/Models/FileSystem/FolderCreateModel.cs b/src/Umbraco.Core/Models/FileSystem/FolderCreateModel.cs index dbff5aa46b58..5f04c12491fc 100644 --- a/src/Umbraco.Core/Models/FileSystem/FolderCreateModel.cs +++ b/src/Umbraco.Core/Models/FileSystem/FolderCreateModel.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.FileSystem; +namespace Umbraco.Cms.Core.Models.FileSystem; +/// +/// Represents the base model for creating a new folder in the file system. +/// public abstract class FolderCreateModel { + /// + /// Gets or sets the name of the folder to create. + /// public required string Name { get; set; } + /// + /// Gets or sets the path of the parent folder, or null to create at the root. + /// public string? ParentPath { get; set; } } diff --git a/src/Umbraco.Core/Models/FileSystem/FolderModelBase.cs b/src/Umbraco.Core/Models/FileSystem/FolderModelBase.cs index 2e0e9b88a0d4..72376212885e 100644 --- a/src/Umbraco.Core/Models/FileSystem/FolderModelBase.cs +++ b/src/Umbraco.Core/Models/FileSystem/FolderModelBase.cs @@ -1,10 +1,22 @@ namespace Umbraco.Cms.Core.Models.FileSystem; +/// +/// Represents the base model for a folder in the file system. +/// public abstract class FolderModelBase { + /// + /// Gets or sets the name of the folder. + /// public string Name { get; set; } = string.Empty; + /// + /// Gets or sets the full path to the folder. + /// public string Path { get; set; } = string.Empty; + /// + /// Gets or sets the path of the parent folder, or null if the folder is at the root. + /// public string? ParentPath { get; set; } } diff --git a/src/Umbraco.Core/Models/FileSystem/PartialViewFolderCreateModel.cs b/src/Umbraco.Core/Models/FileSystem/PartialViewFolderCreateModel.cs index f3eef5f1573c..ca0a4652d36f 100644 --- a/src/Umbraco.Core/Models/FileSystem/PartialViewFolderCreateModel.cs +++ b/src/Umbraco.Core/Models/FileSystem/PartialViewFolderCreateModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.FileSystem; +namespace Umbraco.Cms.Core.Models.FileSystem; +/// +/// Represents a model for creating a new partial view folder in the file system. +/// public class PartialViewFolderCreateModel : FolderCreateModel { } diff --git a/src/Umbraco.Core/Models/FileSystem/PartialViewFolderModel.cs b/src/Umbraco.Core/Models/FileSystem/PartialViewFolderModel.cs index bb3750e552d5..605d0bd957a5 100644 --- a/src/Umbraco.Core/Models/FileSystem/PartialViewFolderModel.cs +++ b/src/Umbraco.Core/Models/FileSystem/PartialViewFolderModel.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models.FileSystem; +/// +/// Represents a model for a partial view folder in the file system. +/// public class PartialViewFolderModel : FolderModelBase { } diff --git a/src/Umbraco.Core/Models/FileSystem/ScriptFolderCreateModel.cs b/src/Umbraco.Core/Models/FileSystem/ScriptFolderCreateModel.cs index 437851b191bc..7e838b1464f8 100644 --- a/src/Umbraco.Core/Models/FileSystem/ScriptFolderCreateModel.cs +++ b/src/Umbraco.Core/Models/FileSystem/ScriptFolderCreateModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.FileSystem; +namespace Umbraco.Cms.Core.Models.FileSystem; +/// +/// Represents a model for creating a new script folder in the file system. +/// public class ScriptFolderCreateModel : FolderCreateModel { } diff --git a/src/Umbraco.Core/Models/FileSystem/ScriptFolderModel.cs b/src/Umbraco.Core/Models/FileSystem/ScriptFolderModel.cs index 8e0b669551a5..90371da6a3b2 100644 --- a/src/Umbraco.Core/Models/FileSystem/ScriptFolderModel.cs +++ b/src/Umbraco.Core/Models/FileSystem/ScriptFolderModel.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models.FileSystem; +/// +/// Represents a model for a script folder in the file system. +/// public class ScriptFolderModel : FolderModelBase { } diff --git a/src/Umbraco.Core/Models/FileSystem/StylesheetFolderCreateModel.cs b/src/Umbraco.Core/Models/FileSystem/StylesheetFolderCreateModel.cs index 3051f932565e..3cf810c79ddd 100644 --- a/src/Umbraco.Core/Models/FileSystem/StylesheetFolderCreateModel.cs +++ b/src/Umbraco.Core/Models/FileSystem/StylesheetFolderCreateModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.FileSystem; +namespace Umbraco.Cms.Core.Models.FileSystem; +/// +/// Represents a model for creating a new stylesheet folder in the file system. +/// public class StylesheetFolderCreateModel : FolderCreateModel { } diff --git a/src/Umbraco.Core/Models/FileSystem/StylesheetFolderModel.cs b/src/Umbraco.Core/Models/FileSystem/StylesheetFolderModel.cs index bd954767d237..2265f2b3af14 100644 --- a/src/Umbraco.Core/Models/FileSystem/StylesheetFolderModel.cs +++ b/src/Umbraco.Core/Models/FileSystem/StylesheetFolderModel.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models.FileSystem; +/// +/// Represents a model for a stylesheet folder in the file system. +/// public class StylesheetFolderModel : FolderModelBase { } diff --git a/src/Umbraco.Core/Models/Folder.cs b/src/Umbraco.Core/Models/Folder.cs index 60e636ca6e50..70447213f241 100644 --- a/src/Umbraco.Core/Models/Folder.cs +++ b/src/Umbraco.Core/Models/Folder.cs @@ -2,9 +2,19 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a folder entity in the file system. +/// public sealed class Folder : EntityBase { + /// + /// Initializes a new instance of the class. + /// + /// The path of the folder. public Folder(string folderPath) => Path = folderPath; + /// + /// Gets or sets the path of the folder. + /// public string Path { get; set; } } diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index 9e36306cfc78..c76659c131eb 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -19,6 +19,9 @@ public interface IContent : IContentBase /// The property tells you which version of the content is currently published. bool Published { get; set; } + /// + /// Gets or sets the published state of the content. + /// PublishedState PublishedState { get; set; } /// diff --git a/src/Umbraco.Core/Models/IDataValueEditor.cs b/src/Umbraco.Core/Models/IDataValueEditor.cs index f1599677d55c..f7d65b9c97d9 100644 --- a/src/Umbraco.Core/Models/IDataValueEditor.cs +++ b/src/Umbraco.Core/Models/IDataValueEditor.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Xml.Linq; using Umbraco.Cms.Core.Models.Editors; using Umbraco.Cms.Core.Models.Validation; @@ -75,7 +75,17 @@ public interface IDataValueEditor /// XNode ConvertDbToXml(IPropertyType propertyType, object value); + /// + /// Converts a database value to a string representation. + /// + /// The property type. + /// The database value. + /// A string representation of the value. string ConvertDbToString(IPropertyType propertyType, object? value); + /// + /// Gets the keys of configured element types (for block-based editors). + /// + /// A collection of element type keys. IEnumerable ConfiguredElementTypeKeys() => Enumerable.Empty(); } diff --git a/src/Umbraco.Core/Models/IDeepCloneable.cs b/src/Umbraco.Core/Models/IDeepCloneable.cs index 171c2a1f4ef3..b31e5251139f 100644 --- a/src/Umbraco.Core/Models/IDeepCloneable.cs +++ b/src/Umbraco.Core/Models/IDeepCloneable.cs @@ -5,5 +5,9 @@ namespace Umbraco.Cms.Core.Models; /// public interface IDeepCloneable { + /// + /// Creates a deep clone of the current object. + /// + /// A deep clone of the current object. object DeepClone(); } diff --git a/src/Umbraco.Core/Models/IDictionaryItem.cs b/src/Umbraco.Core/Models/IDictionaryItem.cs index e47502199b2e..2fa59544223c 100644 --- a/src/Umbraco.Core/Models/IDictionaryItem.cs +++ b/src/Umbraco.Core/Models/IDictionaryItem.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a dictionary item for localization. +/// public interface IDictionaryItem : IEntity, IRememberBeingDirty { /// diff --git a/src/Umbraco.Core/Models/IDictionaryTranslation.cs b/src/Umbraco.Core/Models/IDictionaryTranslation.cs index 02e673665464..cb4d06cad6d9 100644 --- a/src/Umbraco.Core/Models/IDictionaryTranslation.cs +++ b/src/Umbraco.Core/Models/IDictionaryTranslation.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a translation for a dictionary item in a specific language. +/// public interface IDictionaryTranslation : IEntity, IRememberBeingDirty { /// diff --git a/src/Umbraco.Core/Models/IKeyValue.cs b/src/Umbraco.Core/Models/IKeyValue.cs index b893aabf356e..3f5510aa2fe5 100644 --- a/src/Umbraco.Core/Models/IKeyValue.cs +++ b/src/Umbraco.Core/Models/IKeyValue.cs @@ -2,9 +2,18 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a key-value pair entity. +/// public interface IKeyValue : IEntity { + /// + /// Gets or sets the unique identifier (key) for this entry. + /// string Identifier { get; set; } + /// + /// Gets or sets the value associated with the identifier. + /// string? Value { get; set; } } diff --git a/src/Umbraco.Core/Models/ILogViewerQuery.cs b/src/Umbraco.Core/Models/ILogViewerQuery.cs index 61798b1ca353..f84a5596741d 100644 --- a/src/Umbraco.Core/Models/ILogViewerQuery.cs +++ b/src/Umbraco.Core/Models/ILogViewerQuery.cs @@ -2,9 +2,18 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a saved query for the log viewer. +/// public interface ILogViewerQuery : IEntity { + /// + /// Gets or sets the name of the saved query. + /// string Name { get; set; } + /// + /// Gets or sets the query string expression. + /// string Query { get; set; } } diff --git a/src/Umbraco.Core/Models/IMedia.cs b/src/Umbraco.Core/Models/IMedia.cs index 08f206f664e9..b530eb7ee6c6 100644 --- a/src/Umbraco.Core/Models/IMedia.cs +++ b/src/Umbraco.Core/Models/IMedia.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a media item in Umbraco. +/// public interface IMedia : IContentBase { } diff --git a/src/Umbraco.Core/Models/IMember.cs b/src/Umbraco.Core/Models/IMember.cs index e8f4fe998671..d4f92b06dc94 100644 --- a/src/Umbraco.Core/Models/IMember.cs +++ b/src/Umbraco.Core/Models/IMember.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a member in Umbraco. +/// public interface IMember : IContentBase, IMembershipUser { /// diff --git a/src/Umbraco.Core/Models/INavigationModel.cs b/src/Umbraco.Core/Models/INavigationModel.cs index 574d1b7c943e..2d66817c28c9 100644 --- a/src/Umbraco.Core/Models/INavigationModel.cs +++ b/src/Umbraco.Core/Models/INavigationModel.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a model used for content navigation in the tree structure. +/// public interface INavigationModel { /// diff --git a/src/Umbraco.Core/Models/IPartialView.cs b/src/Umbraco.Core/Models/IPartialView.cs index d37b2af41578..6efff9b374df 100644 --- a/src/Umbraco.Core/Models/IPartialView.cs +++ b/src/Umbraco.Core/Models/IPartialView.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a partial view file. +/// public interface IPartialView : IFile { } diff --git a/src/Umbraco.Core/Models/IProperty.cs b/src/Umbraco.Core/Models/IProperty.cs index a70ccb5888f0..989d00c37e4c 100644 --- a/src/Umbraco.Core/Models/IProperty.cs +++ b/src/Umbraco.Core/Models/IProperty.cs @@ -3,8 +3,14 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a property on a content item. +/// public interface IProperty : IEntity, IRememberBeingDirty { + /// + /// Gets the value storage type for this property. + /// ValueStorageType ValueStorageType { get; } /// @@ -22,6 +28,9 @@ public interface IProperty : IEntity, IRememberBeingDirty /// string Alias { get; } + /// + /// Gets the identifier of the property type. + /// int PropertyTypeId { get; } /// @@ -39,9 +48,24 @@ public interface IProperty : IEntity, IRememberBeingDirty /// bool SetValue(object? value, string? culture = null, string? segment = null); + /// + /// Publishes property values for the specified culture and segment. + /// + /// The culture to publish, or "*" for all cultures. + /// The segment to publish, or "*" for all segments. void PublishValues(string? culture = "*", string segment = "*"); + /// + /// Publishes partial property values for a specific data editor and culture. + /// + /// The data editor handling the partial publish. + /// The culture to publish. void PublishPartialValues(IDataEditor dataEditor, string? culture); + /// + /// Unpublishes property values for the specified culture and segment. + /// + /// The culture to unpublish, or "*" for all cultures. + /// The segment to unpublish, or "*" for all segments. void UnpublishValues(string? culture = "*", string segment = "*"); } diff --git a/src/Umbraco.Core/Models/IPropertyCollection.cs b/src/Umbraco.Core/Models/IPropertyCollection.cs index 535756fad86f..3da700ae3dcd 100644 --- a/src/Umbraco.Core/Models/IPropertyCollection.cs +++ b/src/Umbraco.Core/Models/IPropertyCollection.cs @@ -3,8 +3,14 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a collection of properties. +/// public interface IPropertyCollection : IEnumerable, IDeepCloneable, INotifyCollectionChanged { + /// + /// Gets the number of properties in the collection. + /// int Count { get; } /// @@ -17,8 +23,19 @@ public interface IPropertyCollection : IEnumerable, IDeepCloneable, I /// IProperty? this[int index] { get; } + /// + /// Tries to get a property by its alias. + /// + /// The alias of the property type. + /// When this method returns, contains the property if found; otherwise, null. + /// true if a property with the specified alias was found; otherwise, false. bool TryGetValue(string propertyTypeAlias, [MaybeNullWhen(false)] out IProperty property); + /// + /// Determines whether the collection contains a property with the specified alias. + /// + /// The alias of the property to locate. + /// true if the collection contains a property with the specified alias; otherwise, false. bool Contains(string key); /// @@ -36,5 +53,8 @@ public interface IPropertyCollection : IEnumerable, IDeepCloneable, I /// void Add(IProperty property); + /// + /// Clears all collection changed event handlers. + /// void ClearCollectionChangedEvents(); } diff --git a/src/Umbraco.Core/Models/IPropertyType.cs b/src/Umbraco.Core/Models/IPropertyType.cs index 994a174b8e6f..95e94a56392a 100644 --- a/src/Umbraco.Core/Models/IPropertyType.cs +++ b/src/Umbraco.Core/Models/IPropertyType.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a property type definition on a content type. +/// public interface IPropertyType : IEntity, IRememberBeingDirty { /// @@ -65,6 +68,9 @@ public interface IPropertyType : IEntity, IRememberBeingDirty /// string? ValidationRegExp { get; set; } + /// + /// Gets or sets a value indicating whether this property type supports publishing. + /// bool SupportsPublishing { get; set; } /// diff --git a/src/Umbraco.Core/Models/IPropertyValue.cs b/src/Umbraco.Core/Models/IPropertyValue.cs index ef95cd2a01fa..323b9f4a153b 100644 --- a/src/Umbraco.Core/Models/IPropertyValue.cs +++ b/src/Umbraco.Core/Models/IPropertyValue.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a property value with support for culture and segment variations. +/// public interface IPropertyValue { /// diff --git a/src/Umbraco.Core/Models/IReadOnlyContentBase.cs b/src/Umbraco.Core/Models/IReadOnlyContentBase.cs index 37b5a5ddea5e..a358ecdf195f 100644 --- a/src/Umbraco.Core/Models/IReadOnlyContentBase.cs +++ b/src/Umbraco.Core/Models/IReadOnlyContentBase.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a read-only view of content base properties. +/// public interface IReadOnlyContentBase { /// diff --git a/src/Umbraco.Core/Models/IRelation.cs b/src/Umbraco.Core/Models/IRelation.cs index 468a51b89706..c166bb0bfd36 100644 --- a/src/Umbraco.Core/Models/IRelation.cs +++ b/src/Umbraco.Core/Models/IRelation.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a relation between two entities. +/// public interface IRelation : IEntity, IRememberBeingDirty { /// @@ -11,6 +14,9 @@ public interface IRelation : IEntity, IRememberBeingDirty [DataMember] int ParentId { get; set; } + /// + /// Gets or sets the object type of the parent entity. + /// [DataMember] Guid ParentObjectType { get; set; } @@ -20,6 +26,9 @@ public interface IRelation : IEntity, IRememberBeingDirty [DataMember] int ChildId { get; set; } + /// + /// Gets or sets the object type of the child entity. + /// [DataMember] Guid ChildObjectType { get; set; } diff --git a/src/Umbraco.Core/Models/IRelationTypeWithIsDependency.cs b/src/Umbraco.Core/Models/IRelationTypeWithIsDependency.cs index 7675a1c49e65..c2f9afd606a9 100644 --- a/src/Umbraco.Core/Models/IRelationTypeWithIsDependency.cs +++ b/src/Umbraco.Core/Models/IRelationTypeWithIsDependency.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a relation type that includes dependency information. +/// public interface IRelationTypeWithIsDependency : IRelationType { /// @@ -12,6 +15,9 @@ public interface IRelationTypeWithIsDependency : IRelationType bool IsDependency { get; set; } } +/// +/// Represents a type that defines how two entities are related. +/// public interface IRelationType : IEntity, IRememberBeingDirty { /// diff --git a/src/Umbraco.Core/Models/IScript.cs b/src/Umbraco.Core/Models/IScript.cs index f52bdc02864a..c7d26fb90f2e 100644 --- a/src/Umbraco.Core/Models/IScript.cs +++ b/src/Umbraco.Core/Models/IScript.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a script file. +/// public interface IScript : IFile { } diff --git a/src/Umbraco.Core/Models/IServerRegistration.cs b/src/Umbraco.Core/Models/IServerRegistration.cs index 525ed30163e2..bb9b2308eacc 100644 --- a/src/Umbraco.Core/Models/IServerRegistration.cs +++ b/src/Umbraco.Core/Models/IServerRegistration.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a server registration for distributed environments. +/// public interface IServerRegistration : IServerAddress, IEntity, IRememberBeingDirty { /// @@ -10,6 +13,9 @@ public interface IServerRegistration : IServerAddress, IEntity, IRememberBeingDi /// string? ServerIdentity { get; set; } + /// + /// Gets or sets the server address URL. + /// new string? ServerAddress { get; set; } /// diff --git a/src/Umbraco.Core/Models/ISimpleContentType.cs b/src/Umbraco.Core/Models/ISimpleContentType.cs index 15147093c82a..2a5eb316c4c2 100644 --- a/src/Umbraco.Core/Models/ISimpleContentType.cs +++ b/src/Umbraco.Core/Models/ISimpleContentType.cs @@ -5,10 +5,19 @@ namespace Umbraco.Cms.Core.Models; /// public interface ISimpleContentType { + /// + /// Gets the integer identifier of the content type. + /// int Id { get; } + /// + /// Gets the unique identifier of the content type. + /// Guid Key { get; } + /// + /// Gets the name of the content type. + /// string? Name { get; } /// diff --git a/src/Umbraco.Core/Models/IStylesheet.cs b/src/Umbraco.Core/Models/IStylesheet.cs index fbe9a1652b71..1aa49815c9f8 100644 --- a/src/Umbraco.Core/Models/IStylesheet.cs +++ b/src/Umbraco.Core/Models/IStylesheet.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a stylesheet file with support for backoffice-enabled properties. +/// public interface IStylesheet : IFile { /// diff --git a/src/Umbraco.Core/Models/IStylesheetProperty.cs b/src/Umbraco.Core/Models/IStylesheetProperty.cs index c2bb81060da7..6f27469122e2 100644 --- a/src/Umbraco.Core/Models/IStylesheetProperty.cs +++ b/src/Umbraco.Core/Models/IStylesheetProperty.cs @@ -2,11 +2,23 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a property defined in a stylesheet for use in the backoffice RTE. +/// public interface IStylesheetProperty : IRememberBeingDirty { + /// + /// Gets or sets the alias of the stylesheet property. + /// string Alias { get; set; } + /// + /// Gets the name of the stylesheet property. + /// string Name { get; } + /// + /// Gets or sets the CSS value of the stylesheet property. + /// string Value { get; set; } } diff --git a/src/Umbraco.Core/Models/ITwoFactorLogin.cs b/src/Umbraco.Core/Models/ITwoFactorLogin.cs index 3840dcb1746c..329110a1b09d 100644 --- a/src/Umbraco.Core/Models/ITwoFactorLogin.cs +++ b/src/Umbraco.Core/Models/ITwoFactorLogin.cs @@ -2,11 +2,23 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a two-factor authentication login configuration. +/// public interface ITwoFactorLogin : IEntity, IRememberBeingDirty { + /// + /// Gets the name of the two-factor authentication provider. + /// string ProviderName { get; } + /// + /// Gets the secret key used for two-factor authentication. + /// string Secret { get; } + /// + /// Gets the unique identifier of the user or member associated with this login. + /// Guid UserOrMemberKey { get; } } diff --git a/src/Umbraco.Core/Models/IWebhook.cs b/src/Umbraco.Core/Models/IWebhook.cs index 7e64b566472f..85370ed37462 100644 --- a/src/Umbraco.Core/Models/IWebhook.cs +++ b/src/Umbraco.Core/Models/IWebhook.cs @@ -2,28 +2,53 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a webhook configuration for sending HTTP callbacks when events occur. +/// public interface IWebhook : IEntity { // TODO (V16): Remove the default implementations from this interface. + + /// + /// Gets or sets the display name of the webhook. + /// string? Name { get { return null; } set { } } + /// + /// Gets or sets the description of the webhook. + /// string? Description { get { return null; } set { } } + /// + /// Gets or sets the URL to which the webhook payload will be sent. + /// string Url { get; set; } + /// + /// Gets or sets the array of event names that this webhook subscribes to. + /// string[] Events { get; set; } - Guid[] ContentTypeKeys {get; set; } + /// + /// Gets or sets the array of content type keys that this webhook is filtered by. + /// + Guid[] ContentTypeKeys { get; set; } + /// + /// Gets or sets a value indicating whether the webhook is enabled. + /// bool Enabled { get; set; } + /// + /// Gets or sets the custom HTTP headers to include with the webhook request. + /// IDictionary Headers { get; set; } } diff --git a/src/Umbraco.Core/Models/ImageCropAnchor.cs b/src/Umbraco.Core/Models/ImageCropAnchor.cs index 68544289c605..aefb6b3aea99 100644 --- a/src/Umbraco.Core/Models/ImageCropAnchor.cs +++ b/src/Umbraco.Core/Models/ImageCropAnchor.cs @@ -1,14 +1,52 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Defines the anchor point for image cropping operations. +/// public enum ImageCropAnchor { + /// + /// Anchor to the center of the image. + /// Center, + + /// + /// Anchor to the top of the image. + /// Top, + + /// + /// Anchor to the right of the image. + /// Right, + + /// + /// Anchor to the bottom of the image. + /// Bottom, + + /// + /// Anchor to the left of the image. + /// Left, + + /// + /// Anchor to the top-left corner of the image. + /// TopLeft, + + /// + /// Anchor to the top-right corner of the image. + /// TopRight, + + /// + /// Anchor to the bottom-left corner of the image. + /// BottomLeft, + + /// + /// Anchor to the bottom-right corner of the image. + /// BottomRight, } diff --git a/src/Umbraco.Core/Models/ImageCropMode.cs b/src/Umbraco.Core/Models/ImageCropMode.cs index 3ce2f4bfb94b..c5bd916a3190 100644 --- a/src/Umbraco.Core/Models/ImageCropMode.cs +++ b/src/Umbraco.Core/Models/ImageCropMode.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Defines the mode used for image cropping and resizing operations. +/// public enum ImageCropMode { /// diff --git a/src/Umbraco.Core/Models/ImageUrlGenerationOptions.cs b/src/Umbraco.Core/Models/ImageUrlGenerationOptions.cs index 0b79fe30ac67..7179ea03917c 100644 --- a/src/Umbraco.Core/Models/ImageUrlGenerationOptions.cs +++ b/src/Umbraco.Core/Models/ImageUrlGenerationOptions.cs @@ -5,30 +5,73 @@ namespace Umbraco.Cms.Core.Models; /// public class ImageUrlGenerationOptions : IEquatable { + /// + /// Initializes a new instance of the class. + /// + /// The base image URL. public ImageUrlGenerationOptions(string? imageUrl) => ImageUrl = imageUrl; + /// + /// Gets the base image URL. + /// public string? ImageUrl { get; } + /// + /// Gets or sets the source width of the original image in pixels. + /// public int? SourceWidth { get; set; } + + /// + /// Gets or sets the source height of the original image in pixels. + /// public int? SourceHeight { get; set; } + + /// + /// Gets or sets the desired output width in pixels. + /// public int? Width { get; set; } + /// + /// Gets or sets the desired output height in pixels. + /// public int? Height { get; set; } + /// + /// Gets or sets the image quality (typically 0-100). + /// public int? Quality { get; set; } + /// + /// Gets or sets the image crop mode to use. + /// public ImageCropMode? ImageCropMode { get; set; } + /// + /// Gets or sets the image crop anchor position. + /// public ImageCropAnchor? ImageCropAnchor { get; set; } + /// + /// Gets or sets the focal point position for cropping. + /// public FocalPointPosition? FocalPoint { get; set; } + /// + /// Gets or sets the crop coordinates. + /// public CropCoordinates? Crop { get; set; } + /// + /// Gets or sets a cache buster value to append to the URL. + /// public string? CacheBusterValue { get; set; } + /// + /// Gets or sets additional options to append to the generated URL. + /// public string? FurtherOptions { get; set; } + /// public bool Equals(ImageUrlGenerationOptions? other) => other != null && ImageUrl == other.ImageUrl && @@ -42,8 +85,10 @@ public bool Equals(ImageUrlGenerationOptions? other) CacheBusterValue == other.CacheBusterValue && FurtherOptions == other.FurtherOptions; + /// public override bool Equals(object? obj) => Equals(obj as ImageUrlGenerationOptions); + /// public override int GetHashCode() { var hash = default(HashCode); @@ -68,23 +113,37 @@ public override int GetHashCode() /// public class FocalPointPosition : IEquatable { + /// + /// Initializes a new instance of the class. + /// + /// The left position as a percentage (0.0 to 1.0). + /// The top position as a percentage (0.0 to 1.0). public FocalPointPosition(decimal left, decimal top) { Left = left; Top = top; } + /// + /// Gets the left position of the focal point as a percentage of the total image width. + /// public decimal Left { get; } + /// + /// Gets the top position of the focal point as a percentage of the total image height. + /// public decimal Top { get; } + /// public bool Equals(FocalPointPosition? other) => other != null && Left == other.Left && Top == other.Top; + /// public override bool Equals(object? obj) => Equals(obj as FocalPointPosition); + /// public override int GetHashCode() => HashCode.Combine(Left, Top); } @@ -94,6 +153,13 @@ public bool Equals(FocalPointPosition? other) /// public class CropCoordinates : IEquatable { + /// + /// Initializes a new instance of the class. + /// + /// The left coordinate as a percentage (0.0 to 1.0). + /// The top coordinate as a percentage (0.0 to 1.0). + /// The right coordinate as a percentage (0.0 to 1.0). + /// The bottom coordinate as a percentage (0.0 to 1.0). public CropCoordinates(decimal left, decimal top, decimal right, decimal bottom) { Left = left; @@ -102,14 +168,27 @@ public CropCoordinates(decimal left, decimal top, decimal right, decimal bottom) Bottom = bottom; } + /// + /// Gets the left coordinate of the crop as a percentage of the total image width. + /// public decimal Left { get; } + /// + /// Gets the top coordinate of the crop as a percentage of the total image height. + /// public decimal Top { get; } + /// + /// Gets the right coordinate of the crop as a percentage of the total image width. + /// public decimal Right { get; } + /// + /// Gets the bottom coordinate of the crop as a percentage of the total image height. + /// public decimal Bottom { get; } + /// public bool Equals(CropCoordinates? other) => other != null && Left == other.Left && @@ -117,8 +196,10 @@ public bool Equals(CropCoordinates? other) Right == other.Right && Bottom == other.Bottom; + /// public override bool Equals(object? obj) => Equals(obj as CropCoordinates); + /// public override int GetHashCode() => HashCode.Combine(Left, Top, Right, Bottom); } } diff --git a/src/Umbraco.Core/Models/ImportExport/EntityXmlAnalysis.cs b/src/Umbraco.Core/Models/ImportExport/EntityXmlAnalysis.cs index d17488301885..fde9ed387185 100644 --- a/src/Umbraco.Core/Models/ImportExport/EntityXmlAnalysis.cs +++ b/src/Umbraco.Core/Models/ImportExport/EntityXmlAnalysis.cs @@ -2,11 +2,23 @@ namespace Umbraco.Cms.Core.Models.ImportExport; +/// +/// Represents the analysis result of an entity from XML import/export data. +/// public class EntityXmlAnalysis { + /// + /// Gets or sets the type of the entity. + /// public UmbracoEntityTypes EntityType { get; set; } + /// + /// Gets or sets the alias of the entity. + /// public string? Alias { get; set; } + /// + /// Gets or sets the unique key of the entity. + /// public Guid? Key { get; set; } } diff --git a/src/Umbraco.Core/Models/Installer/ConsentLevelModel.cs b/src/Umbraco.Core/Models/Installer/ConsentLevelModel.cs index b5f6182b2a84..cb4862638d7e 100644 --- a/src/Umbraco.Core/Models/Installer/ConsentLevelModel.cs +++ b/src/Umbraco.Core/Models/Installer/ConsentLevelModel.cs @@ -2,9 +2,18 @@ namespace Umbraco.Cms.Core.Models.Installer; +/// +/// Represents a telemetry consent level option available during installation. +/// public class ConsentLevelModel { + /// + /// Gets or sets the telemetry level. + /// public TelemetryLevel Level { get; set; } + /// + /// Gets or sets the description of the telemetry level. + /// public string Description { get; set; } = string.Empty; } diff --git a/src/Umbraco.Core/Models/Installer/DatabaseInstallData.cs b/src/Umbraco.Core/Models/Installer/DatabaseInstallData.cs index 27cab2a735ef..7939fa398b3b 100644 --- a/src/Umbraco.Core/Models/Installer/DatabaseInstallData.cs +++ b/src/Umbraco.Core/Models/Installer/DatabaseInstallData.cs @@ -1,22 +1,52 @@ -namespace Umbraco.Cms.Core.Models.Installer; +namespace Umbraco.Cms.Core.Models.Installer; +/// +/// Represents the database configuration data provided during installation. +/// public class DatabaseInstallData { + /// + /// Gets or sets the unique identifier of the selected database configuration. + /// public Guid Id { get; set; } + /// + /// Gets or sets the database provider name. + /// public string? ProviderName { get; set; } + /// + /// Gets or sets the database server address. + /// public string? Server { get; set; } + /// + /// Gets or sets the database name. + /// public string? Name { get; set; } + /// + /// Gets or sets the database username for authentication. + /// public string? Username { get; set; } + /// + /// Gets or sets the database password for authentication. + /// public string? Password { get; set; } + /// + /// Gets or sets a value indicating whether to use integrated authentication. + /// public bool UseIntegratedAuthentication { get; set; } + /// + /// Gets or sets the full connection string, if provided directly. + /// public string? ConnectionString { get; set; } + /// + /// Gets or sets a value indicating whether to trust the server certificate. + /// public bool TrustServerCertificate { get; set; } } diff --git a/src/Umbraco.Core/Models/Installer/DatabaseSettingsModel.cs b/src/Umbraco.Core/Models/Installer/DatabaseSettingsModel.cs index eff2b883134c..82fcdc58d8e4 100644 --- a/src/Umbraco.Core/Models/Installer/DatabaseSettingsModel.cs +++ b/src/Umbraco.Core/Models/Installer/DatabaseSettingsModel.cs @@ -1,28 +1,67 @@ -namespace Umbraco.Cms.Core.Models.Installer; +namespace Umbraco.Cms.Core.Models.Installer; +/// +/// Represents the configuration settings for a database provider during installation. +/// public class DatabaseSettingsModel { + /// + /// Gets or sets the unique identifier for this database configuration. + /// public Guid Id { get; set; } + /// + /// Gets or sets the sort order for displaying this database option. + /// public int SortOrder { get; set; } + /// + /// Gets or sets the display name of the database provider. + /// public string DisplayName { get; set; } = string.Empty; + /// + /// Gets or sets the default database name to use. + /// public string DefaultDatabaseName { get; set; } = string.Empty; + /// + /// Gets or sets the name of the database provider. + /// public string ProviderName { get; set; } = string.Empty; + /// + /// Gets or sets a value indicating whether the database is already configured. + /// public bool IsConfigured { get; set; } + /// + /// Gets or sets a value indicating whether the database requires a server address. + /// public bool RequiresServer { get; set; } + /// + /// Gets or sets the placeholder text for the server input field. + /// public string ServerPlaceholder { get; set; } = string.Empty; + /// + /// Gets or sets a value indicating whether the database requires credentials. + /// public bool RequiresCredentials { get; set; } + /// + /// Gets or sets a value indicating whether the database supports integrated authentication. + /// public bool SupportsIntegratedAuthentication { get; set; } + /// + /// Gets or sets a value indicating whether the database supports the trust server certificate option. + /// public bool SupportsTrustServerCertificate { get; set; } + /// + /// Gets or sets a value indicating whether the database requires a connection test before proceeding. + /// public bool RequiresConnectionTest { get; set; } } diff --git a/src/Umbraco.Core/Models/Installer/InstallData.cs b/src/Umbraco.Core/Models/Installer/InstallData.cs index 94a93af96c8e..681e3e8e23aa 100644 --- a/src/Umbraco.Core/Models/Installer/InstallData.cs +++ b/src/Umbraco.Core/Models/Installer/InstallData.cs @@ -1,12 +1,24 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Models.Installer; +/// +/// Represents the data provided during the installation process. +/// public class InstallData { + /// + /// Gets or sets the user installation data. + /// public UserInstallData User { get; set; } = null!; + /// + /// Gets or sets the database installation data. + /// public DatabaseInstallData Database { get; set; } = null!; + /// + /// Gets or sets the telemetry consent level. + /// public TelemetryLevel TelemetryLevel { get; set; } = TelemetryLevel.Detailed; } diff --git a/src/Umbraco.Core/Models/Installer/InstallSettingsModel.cs b/src/Umbraco.Core/Models/Installer/InstallSettingsModel.cs index 2e4577df70d5..3856bfb5660b 100644 --- a/src/Umbraco.Core/Models/Installer/InstallSettingsModel.cs +++ b/src/Umbraco.Core/Models/Installer/InstallSettingsModel.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.Models.Installer; +/// +/// Represents the overall settings available during the installation process. +/// public class InstallSettingsModel { + /// + /// Gets or sets the user-related settings. + /// public UserSettingsModel UserSettings { get; set; } = null!; + /// + /// Gets or sets the collection of available database configurations. + /// public ICollection DatabaseSettings { get; set; } = new List(); } diff --git a/src/Umbraco.Core/Models/Installer/InstallationResult.cs b/src/Umbraco.Core/Models/Installer/InstallationResult.cs index 7f2ef6bab78e..547d11a694b5 100644 --- a/src/Umbraco.Core/Models/Installer/InstallationResult.cs +++ b/src/Umbraco.Core/Models/Installer/InstallationResult.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.Installer; +namespace Umbraco.Cms.Core.Models.Installer; +/// +/// Represents the result of an installation operation. +/// public class InstallationResult { /// diff --git a/src/Umbraco.Core/Models/Installer/PasswordSettingsModel.cs b/src/Umbraco.Core/Models/Installer/PasswordSettingsModel.cs index a3e61b3e0c2d..b877ef928ff2 100644 --- a/src/Umbraco.Core/Models/Installer/PasswordSettingsModel.cs +++ b/src/Umbraco.Core/Models/Installer/PasswordSettingsModel.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.Models.Installer; +/// +/// Represents the password policy settings for user account creation. +/// public class PasswordSettingsModel { + /// + /// Gets or sets the minimum character length required for passwords. + /// public int MinCharLength { get; set; } + /// + /// Gets or sets the minimum number of non-alphanumeric characters required in passwords. + /// public int MinNonAlphaNumericLength { get; set; } } diff --git a/src/Umbraco.Core/Models/Installer/UpgradeSettingsModel.cs b/src/Umbraco.Core/Models/Installer/UpgradeSettingsModel.cs index d12e395a92b2..533a100abd16 100644 --- a/src/Umbraco.Core/Models/Installer/UpgradeSettingsModel.cs +++ b/src/Umbraco.Core/Models/Installer/UpgradeSettingsModel.cs @@ -1,15 +1,30 @@ -using Umbraco.Cms.Core.Semver; +using Umbraco.Cms.Core.Semver; using Umbraco.Extensions; namespace Umbraco.Cms.Core.Models.Installer; +/// +/// Represents the settings for an upgrade operation, including version information. +/// public class UpgradeSettingsModel { + /// + /// Gets or sets the current state of the installation before upgrade. + /// public string CurrentState { get; set; } = string.Empty; + /// + /// Gets or sets the new state of the installation after upgrade. + /// public string NewState { get; set; } = string.Empty; + /// + /// Gets or sets the new version being upgraded to. + /// public SemVersion NewVersion { get; set; } = null!; + /// + /// Gets or sets the old version being upgraded from. + /// public SemVersion OldVersion { get; set; } = null!; } diff --git a/src/Umbraco.Core/Models/Installer/UserInstallData.cs b/src/Umbraco.Core/Models/Installer/UserInstallData.cs index a21073e885ad..3c7491c065ef 100644 --- a/src/Umbraco.Core/Models/Installer/UserInstallData.cs +++ b/src/Umbraco.Core/Models/Installer/UserInstallData.cs @@ -1,12 +1,27 @@ -namespace Umbraco.Cms.Core.Models.Installer; +namespace Umbraco.Cms.Core.Models.Installer; +/// +/// Represents the user data provided during the installation process. +/// public class UserInstallData { + /// + /// Gets or sets the name of the user. + /// public string Name { get; set; } = null!; + /// + /// Gets or sets the email address of the user. + /// public string Email { get; set; } = null!; + /// + /// Gets or sets the password for the user. + /// public string Password { get; set; } = null!; + /// + /// Gets or sets a value indicating whether the user wants to subscribe to the newsletter. + /// public bool SubscribeToNewsletter { get; set; } } diff --git a/src/Umbraco.Core/Models/Installer/UserSettingsModel.cs b/src/Umbraco.Core/Models/Installer/UserSettingsModel.cs index 6a6c65218538..062db0ba544d 100644 --- a/src/Umbraco.Core/Models/Installer/UserSettingsModel.cs +++ b/src/Umbraco.Core/Models/Installer/UserSettingsModel.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.Models.Installer; +/// +/// Represents the user-related settings available during installation. +/// public class UserSettingsModel { + /// + /// Gets or sets the password settings configuration. + /// public PasswordSettingsModel PasswordSettings { get; set; } = null!; + /// + /// Gets or sets the collection of consent levels for telemetry. + /// public IEnumerable ConsentLevels { get; set; } = Enumerable.Empty(); } diff --git a/src/Umbraco.Core/Models/KeyValue.cs b/src/Umbraco.Core/Models/KeyValue.cs index bf5b26dbee58..7ceab907a932 100644 --- a/src/Umbraco.Core/Models/KeyValue.cs +++ b/src/Umbraco.Core/Models/KeyValue.cs @@ -27,5 +27,6 @@ public string? Value set => SetPropertyValueAndDetectChanges(value, ref _value, nameof(Value)); } + /// bool IEntity.HasIdentity => !string.IsNullOrEmpty(Identifier); } diff --git a/src/Umbraco.Core/Models/Link.cs b/src/Umbraco.Core/Models/Link.cs index ca65f8850bb4..e0c0444caf36 100644 --- a/src/Umbraco.Core/Models/Link.cs +++ b/src/Umbraco.Core/Models/Link.cs @@ -2,15 +2,33 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a link that can point to content, media, or external URLs. +/// public class Link { + /// + /// Gets or sets the display name of the link. + /// public string? Name { get; set; } + /// + /// Gets or sets the target attribute for the link (e.g., "_blank" for new window). + /// public string? Target { get; set; } + /// + /// Gets or sets the type of link (Content, Media, or External). + /// public LinkType Type { get; set; } + /// + /// Gets or sets the Umbraco Data Identifier for content or media links. + /// public Udi? Udi { get; set; } + /// + /// Gets or sets the URL of the link. + /// public string? Url { get; set; } } diff --git a/src/Umbraco.Core/Models/LinkType.cs b/src/Umbraco.Core/Models/LinkType.cs index 500380504374..62989be9ec4f 100644 --- a/src/Umbraco.Core/Models/LinkType.cs +++ b/src/Umbraco.Core/Models/LinkType.cs @@ -1,8 +1,22 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Defines the type of a link. +/// public enum LinkType { + /// + /// A link to internal content. + /// Content, + + /// + /// A link to media. + /// Media, + + /// + /// A link to an external URL. + /// External, } diff --git a/src/Umbraco.Core/Models/ListViewPagedModel.cs b/src/Umbraco.Core/Models/ListViewPagedModel.cs index e84e7d2405c5..00d1e2e80163 100644 --- a/src/Umbraco.Core/Models/ListViewPagedModel.cs +++ b/src/Umbraco.Core/Models/ListViewPagedModel.cs @@ -2,10 +2,20 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a paged model for list view content items. +/// +/// The type of content that implements . public class ListViewPagedModel where TContent : IContentBase { + /// + /// Gets or sets the paged collection of content items. + /// public required PagedModel Items { get; init; } + /// + /// Gets or sets the list view configuration settings. + /// public required ListViewConfiguration ListViewConfiguration { get; init; } } diff --git a/src/Umbraco.Core/Models/LogViewerQuery.cs b/src/Umbraco.Core/Models/LogViewerQuery.cs index ec0a2af4b70c..65268dde0eda 100644 --- a/src/Umbraco.Core/Models/LogViewerQuery.cs +++ b/src/Umbraco.Core/Models/LogViewerQuery.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a saved query for the log viewer. +/// [Serializable] [DataContract(IsReference = true)] public class LogViewerQuery : EntityBase, ILogViewerQuery @@ -10,12 +13,18 @@ public class LogViewerQuery : EntityBase, ILogViewerQuery private string _name = string.Empty; private string _query = string.Empty; + /// + /// Initializes a new instance of the class. + /// + /// The name of the saved query. + /// The query string expression. public LogViewerQuery(string name, string query) { Name = name; Query = query; } + /// [DataMember] public string Name { @@ -23,6 +32,7 @@ public string Name set => SetPropertyValueAndDetectChanges(value, ref _name!, nameof(Name)); } + /// [DataMember] public string Query { diff --git a/src/Umbraco.Core/Models/Mapping/CommonMapper.cs b/src/Umbraco.Core/Models/Mapping/CommonMapper.cs index e78dbabe6fe2..963252d000ac 100644 --- a/src/Umbraco.Core/Models/Mapping/CommonMapper.cs +++ b/src/Umbraco.Core/Models/Mapping/CommonMapper.cs @@ -5,18 +5,37 @@ namespace Umbraco.Cms.Core.Models.Mapping; +/// +/// Provides common mapping functions for content-related entities. +/// public class CommonMapper { private readonly IUserService _userService; + /// + /// Initializes a new instance of the class. + /// + /// The user service for retrieving user profiles. public CommonMapper(IUserService userService) { _userService = userService; } + /// + /// Gets the name of the owner (creator) of the content. + /// + /// The content base entity. + /// The mapper context. + /// The name of the owner, or null if not found. public string? GetOwnerName(IContentBase source, MapperContext context) => source.GetCreatorProfile(_userService)?.Name; + /// + /// Gets the name of the creator (last writer) of the content. + /// + /// The content entity. + /// The mapper context. + /// The name of the creator, or null if not found. public string? GetCreatorName(IContent source, MapperContext context) => source.GetWriterProfile(_userService)?.Name; } diff --git a/src/Umbraco.Core/Models/Mapping/TagMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/TagMapDefinition.cs index f9c1690c6a46..c956f7b93af1 100644 --- a/src/Umbraco.Core/Models/Mapping/TagMapDefinition.cs +++ b/src/Umbraco.Core/Models/Mapping/TagMapDefinition.cs @@ -2,12 +2,25 @@ namespace Umbraco.Cms.Core.Models.Mapping; +/// +/// Defines the mapping configuration for tag entities to tag models. +/// public class TagMapDefinition : IMapDefinition { + /// + /// Defines the mapping from to . + /// + /// The mapper to configure. public void DefineMaps(IUmbracoMapper mapper) => mapper.Define((source, context) => new TagModel(), Map); // Umbraco.Code.MapAll + /// + /// Maps an source to a target. + /// + /// The source tag entity. + /// The target tag model. + /// The mapper context. private static void Map(ITag source, TagModel target, MapperContext context) { target.Id = source.Id; diff --git a/src/Umbraco.Core/Models/MediaExtensions.cs b/src/Umbraco.Core/Models/MediaExtensions.cs index ee69c25de48b..15301b14a629 100644 --- a/src/Umbraco.Core/Models/MediaExtensions.cs +++ b/src/Umbraco.Core/Models/MediaExtensions.cs @@ -4,6 +4,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class MediaExtensions { /// diff --git a/src/Umbraco.Core/Models/MediaPropertySettings.cs b/src/Umbraco.Core/Models/MediaPropertySettings.cs index e13512aa267c..66871429933c 100644 --- a/src/Umbraco.Core/Models/MediaPropertySettings.cs +++ b/src/Umbraco.Core/Models/MediaPropertySettings.cs @@ -1,15 +1,27 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents settings for media properties including reserved field names. +/// public class MediaPropertySettings { private readonly HashSet _reservedFieldNames = new(); /// - /// Gets a set of standard names for fields that cannot be used for custom properties. + /// Gets a set of standard names for fields that cannot be used for custom properties. /// public ISet ReservedFieldNames => _reservedFieldNames; + /// + /// Adds a single reserved field name. + /// + /// The field name to reserve. + /// true if the name was added; false if it already exists. public bool AddReservedFieldName(string name) => _reservedFieldNames.Add(name); + /// + /// Adds multiple reserved field names. + /// + /// The set of field names to reserve. public void AddReservedFieldNames(ISet names) => _reservedFieldNames.UnionWith(names); } diff --git a/src/Umbraco.Core/Models/MediaType.cs b/src/Umbraco.Core/Models/MediaType.cs index 16cf61c9881b..4ae79c7a1e5b 100644 --- a/src/Umbraco.Core/Models/MediaType.cs +++ b/src/Umbraco.Core/Models/MediaType.cs @@ -11,6 +11,9 @@ namespace Umbraco.Cms.Core.Models; [DataContract(IsReference = true)] public class MediaType : ContentTypeCompositionBase, IMediaType { + /// + /// Constant indicating that media types do not support publishing. + /// public const bool SupportsPublishingConst = false; private bool _isCloning; diff --git a/src/Umbraco.Core/Models/Member.cs b/src/Umbraco.Core/Models/Member.cs index 064026e74ace..93114a99147a 100644 --- a/src/Umbraco.Core/Models/Member.cs +++ b/src/Umbraco.Core/Models/Member.cs @@ -274,6 +274,9 @@ public string Email set => SetPropertyValueAndDetectChanges(value, ref _email!, nameof(Email)); } + /// + /// Gets or sets the date and time when the member's email was confirmed. + /// [DataMember] public DateTime? EmailConfirmedDate { @@ -303,6 +306,9 @@ public string? RawPasswordValue } } + /// + /// Gets or sets the password configuration used for hashing/encrypting the password. + /// [IgnoreDataMember] public string? PasswordConfiguration { @@ -507,6 +513,14 @@ public string? SecurityStamp [EditorBrowsable(EditorBrowsableState.Never)] public string? PropertyTypeAlias { get; set; } + /// + /// Checks if a property type exists and logs a warning if not found when getting a value. + /// + /// The type of value being retrieved. + /// The alias of the property to check. + /// The name of the property for logging purposes. + /// The default value to return if property is not found. + /// An indicating success or failure with a default value. private Attempt WarnIfPropertyTypeNotFoundOnGet(string propertyAlias, string propertyName, T defaultVal) { static void DoLog(string logPropertyAlias, string logPropertyName) @@ -536,6 +550,12 @@ static void DoLog(string logPropertyAlias, string logPropertyName) return Attempt.Succeed(); } + /// + /// Checks if a property type exists and logs a warning if not found when setting a value. + /// + /// The alias of the property to check. + /// The name of the property for logging purposes. + /// true if the property exists; otherwise, false. private bool WarnIfPropertyTypeNotFoundOnSet(string propertyAlias, string propertyName) { static void DoLog(string logPropertyAlias, string logPropertyName) diff --git a/src/Umbraco.Core/Models/MemberGroup.cs b/src/Umbraco.Core/Models/MemberGroup.cs index b36344a002a7..acbfebad1897 100644 --- a/src/Umbraco.Core/Models/MemberGroup.cs +++ b/src/Umbraco.Core/Models/MemberGroup.cs @@ -13,6 +13,9 @@ public class MemberGroup : EntityBase, IMemberGroup private int _creatorId; private string? _name; + /// + /// Gets or sets the name of the member group. + /// [DataMember] public string? Name { @@ -20,6 +23,9 @@ public string? Name set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name)); } + /// + /// Gets or sets the identifier of the user who created this member group. + /// [DataMember] public int CreatorId { diff --git a/src/Umbraco.Core/Models/MemberPropertyModel.cs b/src/Umbraco.Core/Models/MemberPropertyModel.cs index 96466af39747..06480ee6d7ca 100644 --- a/src/Umbraco.Core/Models/MemberPropertyModel.cs +++ b/src/Umbraco.Core/Models/MemberPropertyModel.cs @@ -8,18 +8,29 @@ namespace Umbraco.Cms.Core.Models; /// public class MemberPropertyModel { + /// + /// Gets or sets the alias of the property. + /// [Required] public string Alias { get; set; } = null!; - // NOTE: This has to be a string currently, if it is an object it will bind as an array which we don't want. - // If we want to have this as an 'object' with a true type on it, we have to create a custom model binder - // for an UmbracoProperty and then bind with the correct type based on the property type for this alias. This - // would be a bit long winded and perhaps unnecessary. The reason is because it is always posted as a string anyways - // and when we set this value on the property object that gets sent to the database we do a TryConvertTo to the - // real type anyways. + /// + /// Gets or sets the value of the property as a string. + /// + /// + /// This has to be a string currently, if it is an object it will bind as an array which we don't want. + /// If we want to have this as an 'object' with a true type on it, we have to create a custom model binder + /// for an UmbracoProperty and then bind with the correct type based on the property type for this alias. This + /// would be a bit long winded and perhaps unnecessary. The reason is because it is always posted as a string anyways + /// and when we set this value on the property object that gets sent to the database we do a TryConvertTo to the + /// real type anyways. + /// [DataType(System.ComponentModel.DataAnnotations.DataType.Text)] public string? Value { get; set; } + /// + /// Gets or sets the display name of the property. + /// [ReadOnly(true)] public string? Name { get; set; } diff --git a/src/Umbraco.Core/Models/MemberPropertySettings.cs b/src/Umbraco.Core/Models/MemberPropertySettings.cs index b5271fb75cf2..528c2a7c6f7f 100644 --- a/src/Umbraco.Core/Models/MemberPropertySettings.cs +++ b/src/Umbraco.Core/Models/MemberPropertySettings.cs @@ -1,15 +1,27 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents settings for member properties including reserved field names. +/// public class MemberPropertySettings { private readonly HashSet _reservedFieldNames = new(); /// - /// Gets a set of standard names for fields that cannot be used for custom properties. + /// Gets a set of standard names for fields that cannot be used for custom properties. /// public ISet ReservedFieldNames => _reservedFieldNames; + /// + /// Adds a single reserved field name. + /// + /// The field name to reserve. + /// true if the name was added; false if it already exists. public bool AddReservedFieldName(string name) => _reservedFieldNames.Add(name); + /// + /// Adds multiple reserved field names. + /// + /// The set of field names to reserve. public void AddReservedFieldNames(ISet names) => _reservedFieldNames.UnionWith(names); } diff --git a/src/Umbraco.Core/Models/MemberType.cs b/src/Umbraco.Core/Models/MemberType.cs index 7ed2e3721717..db3af0f1f2e6 100644 --- a/src/Umbraco.Core/Models/MemberType.cs +++ b/src/Umbraco.Core/Models/MemberType.cs @@ -11,6 +11,9 @@ namespace Umbraco.Cms.Core.Models; [DataContract(IsReference = true)] public class MemberType : ContentTypeCompositionBase, IMemberType { + /// + /// Constant indicating that member types do not support publishing. + /// public const bool SupportsPublishingConst = false; private readonly IShortStringHelper _shortStringHelper; @@ -22,6 +25,11 @@ public class MemberType : ContentTypeCompositionBase, IMemberType // Dictionary is divided into string: PropertyTypeAlias, Tuple: MemberCanEdit, VisibleOnProfile, PropertyTypeId private string _alias = string.Empty; + /// + /// Initializes a new instance of the class with the specified parent ID. + /// + /// The short string helper. + /// The identifier of the parent content type. public MemberType(IShortStringHelper shortStringHelper, int parentId) : base(shortStringHelper, parentId) { @@ -29,6 +37,11 @@ public MemberType(IShortStringHelper shortStringHelper, int parentId) _memberTypePropertyTypes = new Dictionary(); } + /// + /// Initializes a new instance of the class with a parent content type. + /// + /// The short string helper. + /// The parent content type composition. public MemberType(IShortStringHelper shortStringHelper, IContentTypeComposition parent) : this( shortStringHelper, @@ -37,6 +50,12 @@ public MemberType(IShortStringHelper shortStringHelper, IContentTypeComposition { } + /// + /// Initializes a new instance of the class with a parent content type and alias. + /// + /// The short string helper. + /// The parent content type composition. + /// The alias for the member type. public MemberType(IShortStringHelper shortStringHelper, IContentTypeComposition parent, string alias) : base(shortStringHelper, parent, alias) { @@ -47,6 +66,14 @@ public MemberType(IShortStringHelper shortStringHelper, IContentTypeComposition /// public override bool SupportsPublishing => SupportsPublishingConst; + /// + /// Gets or sets the content variation mode. Always returns for members. + /// + /// + /// Although technically possible, variations on members don't make much sense + /// and therefore are disabled. They are fully supported at service level, though, + /// but not at published snapshot level. + /// public override ContentVariation Variations { // note: although technically possible, variations on members don't make much sense diff --git a/src/Umbraco.Core/Models/MemberTypePropertyProfileAccess.cs b/src/Umbraco.Core/Models/MemberTypePropertyProfileAccess.cs index e6e619354b97..ed64e1eed765 100644 --- a/src/Umbraco.Core/Models/MemberTypePropertyProfileAccess.cs +++ b/src/Umbraco.Core/Models/MemberTypePropertyProfileAccess.cs @@ -5,6 +5,12 @@ namespace Umbraco.Cms.Core.Models; /// public class MemberTypePropertyProfileAccess { + /// + /// Initializes a new instance of the class. + /// + /// Whether the property is visible on the member profile. + /// Whether the property can be edited by the member. + /// Whether the property contains sensitive data. public MemberTypePropertyProfileAccess(bool isVisible, bool isEditable, bool isSenstive) { IsVisible = isVisible; @@ -12,9 +18,18 @@ public MemberTypePropertyProfileAccess(bool isVisible, bool isEditable, bool isS IsSensitive = isSenstive; } + /// + /// Gets or sets a value indicating whether the property is visible on the member profile. + /// public bool IsVisible { get; set; } + /// + /// Gets or sets a value indicating whether the property can be edited by the member. + /// public bool IsEditable { get; set; } + /// + /// Gets or sets a value indicating whether the property contains sensitive data. + /// public bool IsSensitive { get; set; } } diff --git a/src/Umbraco.Core/Models/Membership/ChangeBackOfficeUserPasswordModel.cs b/src/Umbraco.Core/Models/Membership/ChangeBackOfficeUserPasswordModel.cs index 0292d308093f..0acc322fc619 100644 --- a/src/Umbraco.Core/Models/Membership/ChangeBackOfficeUserPasswordModel.cs +++ b/src/Umbraco.Core/Models/Membership/ChangeBackOfficeUserPasswordModel.cs @@ -1,7 +1,13 @@ -namespace Umbraco.Cms.Core.Models.Membership; +namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents the model for changing a backoffice user's password. +/// public class ChangeBackOfficeUserPasswordModel { + /// + /// Gets or sets the new password to set for the user. + /// public required string NewPassword { get; set; } /// diff --git a/src/Umbraco.Core/Models/Membership/ChangeUserPasswordModel.cs b/src/Umbraco.Core/Models/Membership/ChangeUserPasswordModel.cs index 32d0bbd81786..3eaa1add9044 100644 --- a/src/Umbraco.Core/Models/Membership/ChangeUserPasswordModel.cs +++ b/src/Umbraco.Core/Models/Membership/ChangeUserPasswordModel.cs @@ -1,12 +1,27 @@ -namespace Umbraco.Cms.Core.Models.Membership; +namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents the model for changing a user's password. +/// public class ChangeUserPasswordModel { + /// + /// Gets or sets the new password to set for the user. + /// public required string NewPassword { get; set; } + /// + /// Gets or sets the old password for validation when changing a password. + /// public string? OldPassword { get; set; } + /// + /// Gets or sets the reset password token used for password reset operations. + /// public string? ResetPasswordToken { get; set; } + /// + /// Gets or sets the unique key identifying the user whose password is being changed. + /// public Guid UserKey { get; set; } } diff --git a/src/Umbraco.Core/Models/Membership/ContentPermissionSet.cs b/src/Umbraco.Core/Models/Membership/ContentPermissionSet.cs index c10a3b3da6e9..b66a48f0cf20 100644 --- a/src/Umbraco.Core/Models/Membership/ContentPermissionSet.cs +++ b/src/Umbraco.Core/Models/Membership/ContentPermissionSet.cs @@ -13,30 +13,44 @@ public class ContentPermissionSet : EntityPermissionSet, IEntity { private readonly IContent _content; + /// + /// Initializes a new instance of the class. + /// + /// The content item associated with the permission set. + /// The collection of entity permissions. public ContentPermissionSet(IContent content, EntityPermissionCollection permissionsSet) : base(content.Id, permissionsSet) => _content = content; + /// public override int EntityId => _content.Id; + /// int IEntity.Id { get => EntityId; set => throw new NotImplementedException(); } + /// bool IEntity.HasIdentity => EntityId > 0; + /// Guid IEntity.Key { get; set; } + /// void IEntity.ResetIdentity() => throw new InvalidOperationException($"Resetting identity on {nameof(ContentPermissionSet)} is invalid"); + /// DateTime IEntity.CreateDate { get; set; } + /// DateTime IEntity.UpdateDate { get; set; } + /// DateTime? IEntity.DeleteDate { get; set; } + /// object IDeepCloneable.DeepClone() => throw new NotImplementedException(); } diff --git a/src/Umbraco.Core/Models/Membership/EntityPermission.cs b/src/Umbraco.Core/Models/Membership/EntityPermission.cs index e8ec1f5ab4f6..e8199c6501ff 100644 --- a/src/Umbraco.Core/Models/Membership/EntityPermission.cs +++ b/src/Umbraco.Core/Models/Membership/EntityPermission.cs @@ -5,6 +5,12 @@ namespace Umbraco.Cms.Core.Models.Membership; /// public class EntityPermission : IEquatable { + /// + /// Initializes a new instance of the class. + /// + /// The user group identifier. + /// The entity identifier. + /// The set of assigned permissions. public EntityPermission(int groupId, int entityId, ISet assignedPermissions) { UserGroupId = groupId; @@ -13,6 +19,13 @@ public EntityPermission(int groupId, int entityId, ISet assignedPermissi IsDefaultPermissions = false; } + /// + /// Initializes a new instance of the class. + /// + /// The user group identifier. + /// The entity identifier. + /// The set of assigned permissions. + /// Indicates whether these are default permissions. public EntityPermission(int groupId, int entityId, ISet assignedPermissions, bool isDefaultPermissions) { UserGroupId = groupId; @@ -21,8 +34,14 @@ public EntityPermission(int groupId, int entityId, ISet assignedPermissi IsDefaultPermissions = isDefaultPermissions; } + /// + /// Gets the entity identifier. + /// public int EntityId { get; } + /// + /// Gets the user group identifier. + /// public int UserGroupId { get; } /// @@ -39,6 +58,7 @@ public EntityPermission(int groupId, int entityId, ISet assignedPermissi /// public bool IsDefaultPermissions { get; } + /// public bool Equals(EntityPermission? other) { if (ReferenceEquals(null, other)) @@ -54,6 +74,7 @@ public bool Equals(EntityPermission? other) return EntityId == other.EntityId && UserGroupId == other.UserGroupId; } + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -74,6 +95,7 @@ public override bool Equals(object? obj) return Equals((EntityPermission)obj); } + /// public override int GetHashCode() { unchecked diff --git a/src/Umbraco.Core/Models/Membership/EntityPermissionCollection.cs b/src/Umbraco.Core/Models/Membership/EntityPermissionCollection.cs index 5445a01965ee..eaaaea65c739 100644 --- a/src/Umbraco.Core/Models/Membership/EntityPermissionCollection.cs +++ b/src/Umbraco.Core/Models/Membership/EntityPermissionCollection.cs @@ -9,10 +9,17 @@ public class EntityPermissionCollection : HashSet private ISet? _aggregatePermissions; + /// + /// Initializes a new instance of the class. + /// public EntityPermissionCollection() { } + /// + /// Initializes a new instance of the class with the specified collection. + /// + /// The collection of entity permissions to initialize with. public EntityPermissionCollection(IEnumerable collection) : base(collection) { diff --git a/src/Umbraco.Core/Models/Membership/EntityPermissionSet.cs b/src/Umbraco.Core/Models/Membership/EntityPermissionSet.cs index 26385052cc6c..db0326b04d70 100644 --- a/src/Umbraco.Core/Models/Membership/EntityPermissionSet.cs +++ b/src/Umbraco.Core/Models/Membership/EntityPermissionSet.cs @@ -8,6 +8,11 @@ public class EntityPermissionSet private static readonly Lazy EmptyInstance = new(() => new EntityPermissionSet(-1, new EntityPermissionCollection())); + /// + /// Initializes a new instance of the class. + /// + /// The entity identifier. + /// The collection of entity permissions. public EntityPermissionSet(int entityId, EntityPermissionCollection permissionsSet) { EntityId = entityId; diff --git a/src/Umbraco.Core/Models/Membership/ErrorMessageResult.cs b/src/Umbraco.Core/Models/Membership/ErrorMessageResult.cs index 9dcd15fafa60..b68d3fb37a8b 100644 --- a/src/Umbraco.Core/Models/Membership/ErrorMessageResult.cs +++ b/src/Umbraco.Core/Models/Membership/ErrorMessageResult.cs @@ -1,8 +1,14 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents a base class for operation results that may contain an error message. +/// public abstract class ErrorMessageResult { + /// + /// Gets or sets the validation error result, if any. + /// public ValidationResult? Error { get; set; } } diff --git a/src/Umbraco.Core/Models/Membership/IMembershipUser.cs b/src/Umbraco.Core/Models/Membership/IMembershipUser.cs index 704158a1af8e..96557f1d14dc 100644 --- a/src/Umbraco.Core/Models/Membership/IMembershipUser.cs +++ b/src/Umbraco.Core/Models/Membership/IMembershipUser.cs @@ -7,10 +7,19 @@ namespace Umbraco.Cms.Core.Models.Membership; /// public interface IMembershipUser : IEntity { + /// + /// Gets or sets the username for the membership user. + /// string Username { get; set; } + /// + /// Gets or sets the email address for the membership user. + /// string Email { get; set; } + /// + /// Gets or sets the date and time when the email was confirmed. + /// DateTime? EmailConfirmedDate { get; set; } /// @@ -23,16 +32,34 @@ public interface IMembershipUser : IEntity /// string? PasswordConfiguration { get; set; } + /// + /// Gets or sets any comments associated with the membership user. + /// string? Comments { get; set; } + /// + /// Gets or sets a value indicating whether the membership user is approved. + /// bool IsApproved { get; set; } + /// + /// Gets or sets a value indicating whether the membership user is locked out. + /// bool IsLockedOut { get; set; } + /// + /// Gets or sets the date and time of the user's last login. + /// DateTime? LastLoginDate { get; set; } + /// + /// Gets or sets the date and time when the password was last changed. + /// DateTime? LastPasswordChangeDate { get; set; } + /// + /// Gets or sets the date and time when the user was last locked out. + /// DateTime? LastLockoutDate { get; set; } /// diff --git a/src/Umbraco.Core/Models/Membership/IProfile.cs b/src/Umbraco.Core/Models/Membership/IProfile.cs index f30bfd122524..1268ffa6c19b 100644 --- a/src/Umbraco.Core/Models/Membership/IProfile.cs +++ b/src/Umbraco.Core/Models/Membership/IProfile.cs @@ -5,7 +5,13 @@ namespace Umbraco.Cms.Core.Models.Membership; /// public interface IProfile { + /// + /// Gets the unique identifier for the profile. + /// int Id { get; } + /// + /// Gets the name of the profile. + /// string? Name { get; } } diff --git a/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs b/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs index 9799412b453e..1a95e002ca11 100644 --- a/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs +++ b/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs @@ -7,33 +7,81 @@ namespace Umbraco.Cms.Core.Models.Membership; /// public interface IReadOnlyUserGroup { + /// + /// Gets the name of the user group. + /// string? Name { get; } + /// + /// Gets the alias of the user group. + /// string Alias { get; } - // TODO (V18): Remove the default implementations. + /// + /// Gets the description of the user group. + /// + /// + /// TODO (V18): Remove the default implementations. + /// string? Description { get { return null; } } + /// + /// Gets the icon for the user group. + /// string? Icon { get; } + /// + /// Gets the unique identifier for the user group. + /// int Id { get; } + /// + /// Gets the unique key for the user group. + /// Guid Key => Guid.Empty; + /// + /// Gets the starting content node identifier for this user group. + /// int? StartContentId { get; } + /// + /// Gets the starting media node identifier for this user group. + /// int? StartMediaId { get; } - // This is set to return true as default to avoid breaking changes. + /// + /// Gets a value indicating whether this user group has access to all languages. + /// + /// + /// This is set to return true as default to avoid breaking changes. + /// bool HasAccessToAllLanguages => true; + /// + /// Gets the set of permissions assigned to this user group. + /// ISet Permissions { get; } + /// + /// Gets the set of granular permissions assigned to this user group. + /// ISet GranularPermissions { get; } + /// + /// Gets the collection of section aliases that this user group has access to. + /// IEnumerable AllowedSections { get; } + /// + /// Gets the collection of language identifiers that this user group has access to. + /// IEnumerable AllowedLanguages => Enumerable.Empty(); + /// + /// Determines whether this user group has access to the specified language. + /// + /// The language identifier to check. + /// true if the user group has access to the language; otherwise, false. public bool HasAccessToLanguage( int languageId) => HasAccessToAllLanguages || AllowedLanguages.Contains(languageId); } diff --git a/src/Umbraco.Core/Models/Membership/IUser.cs b/src/Umbraco.Core/Models/Membership/IUser.cs index 868daee42609..62f0ca417657 100644 --- a/src/Umbraco.Core/Models/Membership/IUser.cs +++ b/src/Umbraco.Core/Models/Membership/IUser.cs @@ -8,18 +8,39 @@ namespace Umbraco.Cms.Core.Models.Membership; /// Will be left internal until a proper Membership implementation is part of the roadmap public interface IUser : IMembershipUser, IRememberBeingDirty { + /// + /// Gets the current state of the user. + /// UserState UserState { get; } + /// + /// Gets or sets the display name of the user. + /// string? Name { get; set; } + /// + /// Gets or sets the session timeout in minutes. + /// int SessionTimeout { get; set; } + /// + /// Gets or sets the starting content node identifiers for this user. + /// int[]? StartContentIds { get; set; } + /// + /// Gets or sets the starting media node identifiers for this user. + /// int[]? StartMediaIds { get; set; } + /// + /// Gets or sets the preferred language for the user's backoffice UI. + /// string? Language { get; set; } + /// + /// Gets or sets the date and time when the user was invited. + /// DateTime? InvitedDate { get; set; } /// @@ -27,6 +48,9 @@ public interface IUser : IMembershipUser, IRememberBeingDirty /// IEnumerable Groups { get; } + /// + /// Gets the collection of section aliases that this user has access to. + /// IEnumerable AllowedSections { get; } /// @@ -44,9 +68,20 @@ public interface IUser : IMembershipUser, IRememberBeingDirty /// UserKind Kind { get; set; } + /// + /// Removes the user from the specified group. + /// + /// The alias of the group to remove the user from. void RemoveGroup(string group); + /// + /// Removes the user from all groups. + /// void ClearGroups(); + /// + /// Adds the user to the specified group. + /// + /// The group to add the user to. void AddGroup(IReadOnlyUserGroup group); } diff --git a/src/Umbraco.Core/Models/Membership/IUserData.cs b/src/Umbraco.Core/Models/Membership/IUserData.cs index f12fb962be17..c0689f132b6e 100644 --- a/src/Umbraco.Core/Models/Membership/IUserData.cs +++ b/src/Umbraco.Core/Models/Membership/IUserData.cs @@ -1,14 +1,32 @@ namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Defines the contract for user-specific data storage. +/// public interface IUserData { + /// + /// Gets or sets the unique key for the user data entry. + /// public Guid Key { get; set; } + /// + /// Gets or sets the key of the user this data belongs to. + /// public Guid UserKey { get; set; } + /// + /// Gets or sets the group category for the user data. + /// public string Group { get; set; } + /// + /// Gets or sets the identifier for the user data within the group. + /// public string Identifier { get; set; } + /// + /// Gets or sets the value of the user data. + /// public string Value { get; set; } } diff --git a/src/Umbraco.Core/Models/Membership/IdentityCreationResult.cs b/src/Umbraco.Core/Models/Membership/IdentityCreationResult.cs index d31d48574a75..738b98e55d28 100644 --- a/src/Umbraco.Core/Models/Membership/IdentityCreationResult.cs +++ b/src/Umbraco.Core/Models/Membership/IdentityCreationResult.cs @@ -1,13 +1,30 @@ -namespace Umbraco.Cms.Core.Models.Membership; +namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents the result of an identity creation operation. +/// public class IdentityCreationResult { + /// + /// Creates a failed identity creation result with the specified error message. + /// + /// The error message describing the failure. + /// A failed instance. public static IdentityCreationResult Fail(string errorMessage) => new IdentityCreationResult { ErrorMessage = errorMessage, Succeded = false }; + /// + /// Gets or initializes a value indicating whether the identity creation succeeded. + /// public bool Succeded { get; init; } + /// + /// Gets or initializes the error message if the operation failed. + /// public string? ErrorMessage { get; init; } + /// + /// Gets or initializes the initial password generated for the new identity. + /// public string? InitialPassword { get; init; } } diff --git a/src/Umbraco.Core/Models/Membership/MemberCountType.cs b/src/Umbraco.Core/Models/Membership/MemberCountType.cs index 6ff29bdee2ee..d80471c3eeae 100644 --- a/src/Umbraco.Core/Models/Membership/MemberCountType.cs +++ b/src/Umbraco.Core/Models/Membership/MemberCountType.cs @@ -5,7 +5,18 @@ namespace Umbraco.Cms.Core.Models.Membership; /// public enum MemberCountType { + /// + /// Count all members. + /// All, + + /// + /// Count only locked out members. + /// LockedOut, + + /// + /// Count only approved members. + /// Approved, } diff --git a/src/Umbraco.Core/Models/Membership/MemberExportModel.cs b/src/Umbraco.Core/Models/Membership/MemberExportModel.cs index 25ec9730d244..45f3eb09cf6e 100644 --- a/src/Umbraco.Core/Models/Membership/MemberExportModel.cs +++ b/src/Umbraco.Core/Models/Membership/MemberExportModel.cs @@ -1,16 +1,58 @@ namespace Umbraco.Cms.Core.Models.Membership { + /// + /// Represents the model for exporting member data. + /// public class MemberExportModel { + /// + /// Gets or sets the unique identifier for the member. + /// public int Id { get; set; } + + /// + /// Gets or sets the unique key for the member. + /// public Guid Key { get; set; } + + /// + /// Gets or sets the name of the member. + /// public string? Name { get; set; } + + /// + /// Gets or sets the username of the member. + /// public string? Username { get; set; } + + /// + /// Gets or sets the email address of the member. + /// public string? Email { get; set; } + + /// + /// Gets or sets the list of group names the member belongs to. + /// public List Groups { get; set; } = new (); + + /// + /// Gets or sets the content type alias of the member. + /// public string? ContentTypeAlias { get; set; } + + /// + /// Gets or sets the date and time when the member was created. + /// public DateTime CreateDate { get; set; } + + /// + /// Gets or sets the date and time when the member was last updated. + /// public DateTime UpdateDate { get; set; } + + /// + /// Gets or sets the list of custom properties for the member. + /// public List Properties { get; set; } = new (); } } diff --git a/src/Umbraco.Core/Models/Membership/MemberExportProperty.cs b/src/Umbraco.Core/Models/Membership/MemberExportProperty.cs index a34f1a8d1dc6..b3d057556cfd 100644 --- a/src/Umbraco.Core/Models/Membership/MemberExportProperty.cs +++ b/src/Umbraco.Core/Models/Membership/MemberExportProperty.cs @@ -1,16 +1,37 @@ namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents a property for member export data. +/// public class MemberExportProperty { + /// + /// Gets or sets the unique identifier for the property. + /// public int Id { get; set; } + /// + /// Gets or sets the alias of the property. + /// public string? Alias { get; set; } + /// + /// Gets or sets the name of the property. + /// public string? Name { get; set; } + /// + /// Gets or sets the value of the property. + /// public object? Value { get; set; } + /// + /// Gets or sets the date and time when the property was created. + /// public DateTime? CreateDate { get; set; } + /// + /// Gets or sets the date and time when the property was last updated. + /// public DateTime? UpdateDate { get; set; } } diff --git a/src/Umbraco.Core/Models/Membership/MemberFilter.cs b/src/Umbraco.Core/Models/Membership/MemberFilter.cs index d65a1bb9ca84..24b9672163ac 100644 --- a/src/Umbraco.Core/Models/Membership/MemberFilter.cs +++ b/src/Umbraco.Core/Models/Membership/MemberFilter.cs @@ -1,14 +1,32 @@ -namespace Umbraco.Cms.Core.Models.Membership; +namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents filter criteria for querying members. +/// public class MemberFilter { + /// + /// Gets or sets the member type identifier to filter by. + /// public Guid? MemberTypeId { get; set; } + /// + /// Gets or sets the member group name to filter by. + /// public string? MemberGroupName { get; set; } + /// + /// Gets or sets a value to filter by approval status. + /// public bool? IsApproved { get; set; } + /// + /// Gets or sets a value to filter by locked out status. + /// public bool? IsLockedOut { get; set; } + /// + /// Gets or sets a text filter to search members by name, email, or username. + /// public string? Filter { get; set; } } diff --git a/src/Umbraco.Core/Models/Membership/MemberKind.cs b/src/Umbraco.Core/Models/Membership/MemberKind.cs index 640abcbac12d..ab61b46e92cb 100644 --- a/src/Umbraco.Core/Models/Membership/MemberKind.cs +++ b/src/Umbraco.Core/Models/Membership/MemberKind.cs @@ -1,7 +1,17 @@ -namespace Umbraco.Cms.Core.Models.Membership; +namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents the kind or type of member. +/// public enum MemberKind { + /// + /// A default member created through standard registration. + /// Default = 0, + + /// + /// A member created through the API. + /// Api } diff --git a/src/Umbraco.Core/Models/Membership/Permissions/DocumentGranularPermission.cs b/src/Umbraco.Core/Models/Membership/Permissions/DocumentGranularPermission.cs index 488a98529f55..2347d303f546 100644 --- a/src/Umbraco.Core/Models/Membership/Permissions/DocumentGranularPermission.cs +++ b/src/Umbraco.Core/Models/Membership/Permissions/DocumentGranularPermission.cs @@ -1,18 +1,32 @@ namespace Umbraco.Cms.Core.Models.Membership.Permissions; - +/// +/// Represents a granular permission for a document (content) node. +/// public class DocumentGranularPermission : INodeGranularPermission { + /// + /// The context type identifier for document permissions. + /// public const string ContextType = "Document"; + /// public required Guid Key { get; set; } + /// public string Context => ContextType; + /// public required string Permission { get; set; } + /// + /// Determines whether this instance is equal to another . + /// + /// The other instance to compare. + /// true if equal; otherwise, false. protected bool Equals(DocumentGranularPermission other) => Key.Equals(other.Key) && Permission == other.Permission; + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -33,5 +47,6 @@ public override bool Equals(object? obj) return Equals((DocumentGranularPermission)obj); } + /// public override int GetHashCode() => HashCode.Combine(Key, Permission); } diff --git a/src/Umbraco.Core/Models/Membership/Permissions/DocumentPropertyValueGranularPermission.cs b/src/Umbraco.Core/Models/Membership/Permissions/DocumentPropertyValueGranularPermission.cs index 0f386ea6d11e..491567eade4c 100644 --- a/src/Umbraco.Core/Models/Membership/Permissions/DocumentPropertyValueGranularPermission.cs +++ b/src/Umbraco.Core/Models/Membership/Permissions/DocumentPropertyValueGranularPermission.cs @@ -1,17 +1,32 @@ namespace Umbraco.Cms.Core.Models.Membership.Permissions; +/// +/// Represents a granular permission for a document type property value. +/// public class DocumentPropertyValueGranularPermission : INodeGranularPermission { + /// + /// The context type identifier for document type property permissions. + /// public const string ContextType = "DocumentTypeProperty"; + /// public required Guid Key { get; set; } + /// public string Context => ContextType; + /// public required string Permission { get; set; } + /// + /// Determines whether this instance is equal to another . + /// + /// The other instance to compare. + /// true if equal; otherwise, false. protected bool Equals(DocumentPropertyValueGranularPermission other) => Key.Equals(other.Key) && Permission == other.Permission; + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -32,5 +47,6 @@ public override bool Equals(object? obj) return Equals((DocumentPropertyValueGranularPermission)obj); } + /// public override int GetHashCode() => HashCode.Combine(Key, Permission); } diff --git a/src/Umbraco.Core/Models/Membership/Permissions/IGranularPermission.cs b/src/Umbraco.Core/Models/Membership/Permissions/IGranularPermission.cs index 752e912969da..aa2234e6c907 100644 --- a/src/Umbraco.Core/Models/Membership/Permissions/IGranularPermission.cs +++ b/src/Umbraco.Core/Models/Membership/Permissions/IGranularPermission.cs @@ -1,10 +1,22 @@ namespace Umbraco.Cms.Core.Models.Membership.Permissions; +/// +/// Defines the contract for a granular permission that can be assigned to user groups. +/// public interface IGranularPermission { + /// + /// Gets the context type identifier for this permission. + /// public string Context { get; } + /// + /// Gets the unique key associated with this permission, if applicable. + /// public Guid? Key => null; + /// + /// Gets or sets the permission identifier. + /// public string Permission { get; set; } } diff --git a/src/Umbraco.Core/Models/Membership/Permissions/INodeGranularPermission.cs b/src/Umbraco.Core/Models/Membership/Permissions/INodeGranularPermission.cs index 3c0a05042408..f999823b04b4 100644 --- a/src/Umbraco.Core/Models/Membership/Permissions/INodeGranularPermission.cs +++ b/src/Umbraco.Core/Models/Membership/Permissions/INodeGranularPermission.cs @@ -1,9 +1,16 @@ namespace Umbraco.Cms.Core.Models.Membership.Permissions; +/// +/// Defines the contract for a granular permission that is associated with a specific node. +/// public interface INodeGranularPermission : IGranularPermission { + /// + /// Gets or sets the unique key of the node this permission applies to. + /// new Guid Key { get; set; } + /// Guid? IGranularPermission.Key { get => Key; diff --git a/src/Umbraco.Core/Models/Membership/Permissions/UnknownTypeGranularPermission.cs b/src/Umbraco.Core/Models/Membership/Permissions/UnknownTypeGranularPermission.cs index caf75f279695..006a564bc67f 100644 --- a/src/Umbraco.Core/Models/Membership/Permissions/UnknownTypeGranularPermission.cs +++ b/src/Umbraco.Core/Models/Membership/Permissions/UnknownTypeGranularPermission.cs @@ -1,13 +1,24 @@ namespace Umbraco.Cms.Core.Models.Membership.Permissions; +/// +/// Represents a granular permission with an unknown or unrecognized context type. +/// public class UnknownTypeGranularPermission : IGranularPermission { + /// public required string Context { get; set; } + /// public required string Permission { get; set; } + /// + /// Determines whether this instance is equal to another . + /// + /// The other instance to compare. + /// true if equal; otherwise, false. protected bool Equals(UnknownTypeGranularPermission other) => Context == other.Context && Permission == other.Permission; + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -28,5 +39,6 @@ public override bool Equals(object? obj) return Equals((UnknownTypeGranularPermission)obj); } + /// public override int GetHashCode() => HashCode.Combine(Context, Permission); } diff --git a/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs b/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs index 407edf23b4d2..a9fd3a0bc512 100644 --- a/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs +++ b/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs @@ -2,8 +2,26 @@ namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents a read-only implementation of a user group providing basic information. +/// public class ReadOnlyUserGroup : IReadOnlyUserGroup, IEquatable { + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier for the user group. + /// The unique key for the user group. + /// The name of the user group. + /// The icon for the user group. + /// The starting content node identifier. + /// The starting media node identifier. + /// The alias of the user group. + /// The collection of allowed language identifiers. + /// The collection of allowed section aliases. + /// The set of permissions. + /// The set of granular permissions. + /// Indicates whether the group has access to all languages. [Obsolete("Please use the constructor that includes all parameters. Scheduled for removal in Umbraco 19.")] public ReadOnlyUserGroup( int id, @@ -35,6 +53,22 @@ public ReadOnlyUserGroup( { } + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier for the user group. + /// The unique key for the user group. + /// The name of the user group. + /// The description of the user group. + /// The icon for the user group. + /// The starting content node identifier. + /// The starting media node identifier. + /// The alias of the user group. + /// The collection of allowed language identifiers. + /// The collection of allowed section aliases. + /// The set of permissions. + /// The set of granular permissions. + /// Indicates whether the group has access to all languages. public ReadOnlyUserGroup( int id, Guid key, @@ -67,34 +101,54 @@ public ReadOnlyUserGroup( GranularPermissions = granularPermissions; } + /// public int Id { get; } + /// public Guid Key { get; } + /// public string Name { get; } + /// public string? Description { get; } + /// public string? Icon { get; } + /// public int? StartContentId { get; } + /// public int? StartMediaId { get; } + /// public string Alias { get; } + /// public bool HasAccessToAllLanguages { get; set; } + /// public IEnumerable AllowedLanguages { get; private set; } + /// public ISet Permissions { get; private set; } + /// public ISet GranularPermissions { get; private set; } + /// public IEnumerable AllowedSections { get; private set; } + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(ReadOnlyUserGroup left, ReadOnlyUserGroup right) => Equals(left, right); + /// public override bool Equals(object? obj) { if (obj is null) @@ -115,6 +169,7 @@ public override bool Equals(object? obj) return Equals((ReadOnlyUserGroup)obj); } + /// public bool Equals(ReadOnlyUserGroup? other) { if (other is null) @@ -130,7 +185,14 @@ public bool Equals(ReadOnlyUserGroup? other) return string.Equals(Alias, other.Alias); } + /// public override int GetHashCode() => Alias?.GetHashCode() ?? base.GetHashCode(); + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(ReadOnlyUserGroup left, ReadOnlyUserGroup right) => !Equals(left, right); } diff --git a/src/Umbraco.Core/Models/Membership/User.cs b/src/Umbraco.Core/Models/Membership/User.cs index 571449dcc38b..1e771bd6e0fe 100644 --- a/src/Umbraco.Core/Models/Membership/User.cs +++ b/src/Umbraco.Core/Models/Membership/User.cs @@ -46,6 +46,7 @@ public class User : EntityBase, IUser, IProfile /// /// Constructor for creating a new/empty user /// + /// The global settings for default values. public User(GlobalSettings globalSettings) { SessionTimeout = 60; @@ -66,11 +67,11 @@ public User(GlobalSettings globalSettings) /// /// Constructor for creating a new/empty user /// - /// - /// - /// - /// - /// + /// The global settings for default values. + /// The display name of the user. + /// The email address of the user. + /// The username for the user. + /// The raw password value for the user. public User(GlobalSettings globalSettings, string? name, string email, string username, string rawPasswordValue) : this(globalSettings) { @@ -108,16 +109,16 @@ public User(GlobalSettings globalSettings, string? name, string email, string us /// /// Constructor for creating a new User instance for an existing user /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// + /// The global settings for default values. + /// The unique identifier for the user. + /// The display name of the user. + /// The email address of the user. + /// The username for the user. + /// The raw password value for the user. + /// The password configuration for the user. + /// The user groups the user belongs to. + /// The starting content node identifiers. + /// The starting media node identifiers. public User( GlobalSettings globalSettings, int id, @@ -165,6 +166,7 @@ public User( _startMediaIds = startMediaIds ?? throw new ArgumentNullException(nameof(startMediaIds)); } + /// [DataMember] public DateTime? EmailConfirmedDate { @@ -172,6 +174,7 @@ public DateTime? EmailConfirmedDate set => SetPropertyValueAndDetectChanges(value, ref _emailConfirmedDate, nameof(EmailConfirmedDate)); } + /// [DataMember] public DateTime? InvitedDate { @@ -179,6 +182,7 @@ public DateTime? InvitedDate set => SetPropertyValueAndDetectChanges(value, ref _invitedDate, nameof(InvitedDate)); } + /// [DataMember] public string Username { @@ -186,6 +190,7 @@ public string Username set => SetPropertyValueAndDetectChanges(value, ref _username!, nameof(Username)); } + /// [DataMember] public string Email { @@ -193,6 +198,7 @@ public string Email set => SetPropertyValueAndDetectChanges(value, ref _email!, nameof(Email)); } + /// [IgnoreDataMember] public string? RawPasswordValue { @@ -200,6 +206,7 @@ public string? RawPasswordValue set => SetPropertyValueAndDetectChanges(value, ref _rawPasswordValue, nameof(RawPasswordValue)); } + /// [IgnoreDataMember] public string? PasswordConfiguration { @@ -207,6 +214,7 @@ public string? PasswordConfiguration set => SetPropertyValueAndDetectChanges(value, ref _passwordConfig, nameof(PasswordConfiguration)); } + /// [DataMember] public bool IsApproved { @@ -214,6 +222,7 @@ public bool IsApproved set => SetPropertyValueAndDetectChanges(value, ref _isApproved, nameof(IsApproved)); } + /// [IgnoreDataMember] public bool IsLockedOut { @@ -221,6 +230,7 @@ public bool IsLockedOut set => SetPropertyValueAndDetectChanges(value, ref _isLockedOut, nameof(IsLockedOut)); } + /// [IgnoreDataMember] public DateTime? LastLoginDate { @@ -228,6 +238,7 @@ public DateTime? LastLoginDate set => SetPropertyValueAndDetectChanges(value, ref _lastLoginDate, nameof(LastLoginDate)); } + /// [IgnoreDataMember] public DateTime? LastPasswordChangeDate { @@ -235,6 +246,7 @@ public DateTime? LastPasswordChangeDate set => SetPropertyValueAndDetectChanges(value, ref _lastPasswordChangedDate, nameof(LastPasswordChangeDate)); } + /// [IgnoreDataMember] public DateTime? LastLockoutDate { @@ -242,6 +254,7 @@ public DateTime? LastLockoutDate set => SetPropertyValueAndDetectChanges(value, ref _lastLockoutDate, nameof(LastLockoutDate)); } + /// [IgnoreDataMember] public int FailedPasswordAttempts { @@ -249,9 +262,11 @@ public int FailedPasswordAttempts set => SetPropertyValueAndDetectChanges(value, ref _failedLoginAttempts, nameof(FailedPasswordAttempts)); } + /// [IgnoreDataMember] public string? Comments { get; set; } + /// public UserState UserState { get @@ -281,6 +296,7 @@ public UserState UserState } } + /// [DataMember] public string? Name { @@ -288,9 +304,11 @@ public string? Name set => SetPropertyValueAndDetectChanges(value, ref _name!, nameof(Name)); } + /// public IEnumerable AllowedSections => _allowedSections ??= new List(_userGroups .SelectMany(x => x.AllowedSections).Distinct()); + /// public IProfile ProfileData => new WrappedUserProfile(this); /// @@ -303,6 +321,7 @@ public string? SecurityStamp set => SetPropertyValueAndDetectChanges(value, ref _securityStamp, nameof(SecurityStamp)); } + /// [DataMember] public string? Avatar { @@ -351,6 +370,7 @@ public int[]? StartMediaIds set => SetPropertyValueAndDetectChanges(value, ref _startMediaIds, nameof(StartMediaIds), IntegerEnumerableComparer); } + /// [DataMember] public string? Language { @@ -358,6 +378,7 @@ public string? Language set => SetPropertyValueAndDetectChanges(value, ref _language, nameof(Language)); } + /// [DataMember] public UserKind Kind { @@ -371,6 +392,7 @@ public UserKind Kind [DataMember] public IEnumerable Groups => _userGroups; + /// public void RemoveGroup(string group) { foreach (IReadOnlyUserGroup userGroup in _userGroups.ToArray()) @@ -386,6 +408,7 @@ public void RemoveGroup(string group) } } + /// public void ClearGroups() { if (_userGroups.Count > 0) @@ -398,6 +421,7 @@ public void ClearGroups() } } + /// public void AddGroup(IReadOnlyUserGroup group) { if (_userGroups.Add(group)) @@ -408,6 +432,7 @@ public void AddGroup(IReadOnlyUserGroup group) } } + /// protected override void PerformDeepClone(object clone) { base.PerformDeepClone(clone); @@ -430,12 +455,19 @@ private sealed class WrappedUserProfile : IProfile { private readonly IUser _user; + /// + /// Initializes a new instance of the class. + /// + /// The user to wrap. public WrappedUserProfile(IUser user) => _user = user; + /// public int Id => _user.Id; + /// public string? Name => _user.Name; + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -458,6 +490,7 @@ public override bool Equals(object? obj) private bool Equals(WrappedUserProfile other) => _user.Equals(other._user); + /// public override int GetHashCode() => _user.GetHashCode(); } } diff --git a/src/Umbraco.Core/Models/Membership/UserCreationResult.cs b/src/Umbraco.Core/Models/Membership/UserCreationResult.cs index 7efdddbedef4..dd71962b1e7b 100644 --- a/src/Umbraco.Core/Models/Membership/UserCreationResult.cs +++ b/src/Umbraco.Core/Models/Membership/UserCreationResult.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Models.Membership; +namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents the result of a user creation operation. +/// public class UserCreationResult : ErrorMessageResult { + /// + /// Gets or initializes the newly created user, if the operation succeeded. + /// public IUser? CreatedUser { get; init; } + /// + /// Gets or initializes the initial password generated for the new user. + /// public string? InitialPassword { get; init; } } diff --git a/src/Umbraco.Core/Models/Membership/UserData.cs b/src/Umbraco.Core/Models/Membership/UserData.cs index 035994b90d68..94fa2842ee5e 100644 --- a/src/Umbraco.Core/Models/Membership/UserData.cs +++ b/src/Umbraco.Core/Models/Membership/UserData.cs @@ -1,14 +1,22 @@ namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents user-specific data storage. +/// public class UserData : IUserData { + /// public Guid Key { get; set; } + /// public Guid UserKey { get; set; } + /// public string Group { get; set; } = string.Empty; + /// public string Identifier { get; set; } = string.Empty; + /// public string Value { get; set; } = string.Empty; } diff --git a/src/Umbraco.Core/Models/Membership/UserFilter.cs b/src/Umbraco.Core/Models/Membership/UserFilter.cs index 9ce61bc830b3..b02c96386076 100644 --- a/src/Umbraco.Core/Models/Membership/UserFilter.cs +++ b/src/Umbraco.Core/Models/Membership/UserFilter.cs @@ -1,15 +1,30 @@ -using Umbraco.Cms.Core.Persistence.Querying; +using Umbraco.Cms.Core.Persistence.Querying; namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents filter criteria for querying users. +/// public class UserFilter { + /// + /// Gets or sets the set of user group keys to include in the filter. + /// public ISet? IncludedUserGroups { get; set; } + /// + /// Gets or sets the set of user group keys to exclude from the filter. + /// public ISet? ExcludeUserGroups { get; set; } + /// + /// Gets or sets the set of user states to include in the filter. + /// public ISet? IncludeUserStates { get; set; } + /// + /// Gets or sets the set of name filters to apply. + /// public ISet? NameFilters { get; set; } @@ -27,6 +42,13 @@ public UserFilter Merge(UserFilter target) => NameFilters = MergeSet(NameFilters, target.NameFilters) }; + /// + /// Merges two sets into a single set containing the union of both. + /// + /// The type of elements in the sets. + /// The source set. + /// The target set to merge with. + /// A new set containing elements from both sets, or null if both are empty. private ISet? MergeSet(ISet? source, ISet? target) { var set = new HashSet(); diff --git a/src/Umbraco.Core/Models/Membership/UserGroup.cs b/src/Umbraco.Core/Models/Membership/UserGroup.cs index 0b500f9bd3f6..d984527af190 100644 --- a/src/Umbraco.Core/Models/Membership/UserGroup.cs +++ b/src/Umbraco.Core/Models/Membership/UserGroup.cs @@ -42,6 +42,7 @@ public class UserGroup : EntityBase, IUserGroup, IReadOnlyUserGroup /// /// Constructor to create a new user group /// + /// The short string helper for alias processing. public UserGroup(IShortStringHelper shortStringHelper) { _alias = string.Empty; @@ -75,6 +76,7 @@ public UserGroup( _icon = icon; } + /// [DataMember] public int? StartMediaId { @@ -82,6 +84,7 @@ public int? StartMediaId set => SetPropertyValueAndDetectChanges(value, ref _startMediaId, nameof(StartMediaId)); } + /// [DataMember] public int? StartContentId { @@ -89,6 +92,7 @@ public int? StartContentId set => SetPropertyValueAndDetectChanges(value, ref _startContentId, nameof(StartContentId)); } + /// [DataMember] public string? Icon { @@ -96,6 +100,7 @@ public string? Icon set => SetPropertyValueAndDetectChanges(value, ref _icon, nameof(Icon)); } + /// [DataMember] public string Alias { @@ -106,6 +111,7 @@ public string Alias nameof(Alias)); } + /// [DataMember] public string? Name { @@ -113,6 +119,7 @@ public string? Name set => SetPropertyValueAndDetectChanges(value, ref _name!, nameof(Name)); } + /// [DataMember] public string? Description { @@ -120,6 +127,7 @@ public string? Description set => SetPropertyValueAndDetectChanges(value, ref _description!, nameof(Description)); } + /// [DataMember] public bool HasAccessToAllLanguages { @@ -134,6 +142,7 @@ public ISet Permissions set => SetPropertyValueAndDetectChanges(value, ref _permissions!, nameof(Permissions), _stringEnumerableComparer); } + /// public ISet GranularPermissions { get => _granularPermissions; @@ -141,10 +150,13 @@ public ISet GranularPermissions } + /// public IEnumerable AllowedSections => _sectionCollection; + /// public int UserCount { get; } + /// public void RemoveAllowedSection(string sectionAlias) { if (_sectionCollection.Contains(sectionAlias)) @@ -153,6 +165,7 @@ public void RemoveAllowedSection(string sectionAlias) } } + /// public void AddAllowedSection(string sectionAlias) { if (_sectionCollection.Contains(sectionAlias) == false) @@ -161,11 +174,13 @@ public void AddAllowedSection(string sectionAlias) } } + /// public IEnumerable AllowedLanguages { get => _languageCollection; } + /// public void RemoveAllowedLanguage(int languageId) { if (_languageCollection.Contains(languageId)) @@ -174,6 +189,7 @@ public void RemoveAllowedLanguage(int languageId) } } + /// public void AddAllowedLanguage(int languageId) { if (_languageCollection.Contains(languageId) == false) @@ -182,10 +198,13 @@ public void AddAllowedLanguage(int languageId) } } + /// public void ClearAllowedLanguages() => _languageCollection.Clear(); + /// public void ClearAllowedSections() => _sectionCollection.Clear(); + /// protected override void PerformDeepClone(object clone) { base.PerformDeepClone(clone); diff --git a/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs b/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs index cd6db258970f..df5cd984ee01 100644 --- a/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs +++ b/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs @@ -3,8 +3,16 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for and . +/// public static class UserGroupExtensions { + /// + /// Converts an to an . + /// + /// The user group to convert. + /// A read-only representation of the user group. public static IReadOnlyUserGroup ToReadOnlyGroup(this IUserGroup group) { // this will generally always be the case @@ -30,9 +38,19 @@ public static IReadOnlyUserGroup ToReadOnlyGroup(this IUserGroup group) group.HasAccessToAllLanguages); } + /// + /// Determines whether the specified user group is a system user group. + /// + /// The user group to check. + /// true if the user group is a system user group; otherwise, false. public static bool IsSystemUserGroup(this IUserGroup group) => IsSystemUserGroup(group.Key); + /// + /// Determines whether the specified read-only user group is a system user group. + /// + /// The user group to check. + /// true if the user group is a system user group; otherwise, false. public static bool IsSystemUserGroup(this IReadOnlyUserGroup group) => IsSystemUserGroup(group.Key); diff --git a/src/Umbraco.Core/Models/Membership/UserInvitationResult.cs b/src/Umbraco.Core/Models/Membership/UserInvitationResult.cs index 4a614a01abf8..e5fe54332aae 100644 --- a/src/Umbraco.Core/Models/Membership/UserInvitationResult.cs +++ b/src/Umbraco.Core/Models/Membership/UserInvitationResult.cs @@ -1,6 +1,12 @@ -namespace Umbraco.Cms.Core.Models.Membership; +namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents the result of a user invitation operation. +/// public class UserInvitationResult: ErrorMessageResult { + /// + /// Gets or initializes the invited user, if the operation succeeded. + /// public IUser? InvitedUser { get; init; } } diff --git a/src/Umbraco.Core/Models/Membership/UserKind.cs b/src/Umbraco.Core/Models/Membership/UserKind.cs index 46cc0edb21fb..17c2ac30c05a 100644 --- a/src/Umbraco.Core/Models/Membership/UserKind.cs +++ b/src/Umbraco.Core/Models/Membership/UserKind.cs @@ -1,7 +1,17 @@ -namespace Umbraco.Cms.Core.Models.Membership; +namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents the kind or type of user. +/// public enum UserKind { + /// + /// A default backoffice user. + /// Default = 0, + + /// + /// An API-only user that cannot log in to the backoffice. + /// Api } diff --git a/src/Umbraco.Core/Models/Membership/UserOrder.cs b/src/Umbraco.Core/Models/Membership/UserOrder.cs index 6a72212945a8..b2af17e9c0c4 100644 --- a/src/Umbraco.Core/Models/Membership/UserOrder.cs +++ b/src/Umbraco.Core/Models/Membership/UserOrder.cs @@ -1,15 +1,57 @@ -namespace Umbraco.Cms.Core.Models.Membership; +namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Specifies the field by which to order user query results. +/// public enum UserOrder { + /// + /// Order by username. + /// UserName, + + /// + /// Order by preferred language. + /// Language, + + /// + /// Order by display name. + /// Name, + + /// + /// Order by email address. + /// Email, + + /// + /// Order by user identifier. + /// Id, + + /// + /// Order by creation date. + /// CreateDate, + + /// + /// Order by last update date. + /// UpdateDate, + + /// + /// Order by approval status. + /// IsApproved, + + /// + /// Order by locked out status. + /// IsLockedOut, + + /// + /// Order by last login date. + /// LastLoginDate, } diff --git a/src/Umbraco.Core/Models/Membership/UserProfile.cs b/src/Umbraco.Core/Models/Membership/UserProfile.cs index 51eb882a6b16..164a5b2a73a4 100644 --- a/src/Umbraco.Core/Models/Membership/UserProfile.cs +++ b/src/Umbraco.Core/Models/Membership/UserProfile.cs @@ -1,21 +1,44 @@ namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents a user profile containing basic user information. +/// public class UserProfile : IProfile, IEquatable { + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier for the profile. + /// The name of the profile. public UserProfile(int id, string? name) { Id = id; Name = name; } + /// public int Id { get; } + /// public string? Name { get; } + /// + /// Determines whether two instances are equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(UserProfile left, UserProfile right) => Equals(left, right); + /// + /// Determines whether two instances are not equal. + /// + /// The first instance to compare. + /// The second instance to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(UserProfile left, UserProfile right) => Equals(left, right) == false; + /// public bool Equals(UserProfile? other) { if (ReferenceEquals(null, other)) @@ -31,6 +54,7 @@ public bool Equals(UserProfile? other) return Id == other.Id; } + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -51,5 +75,6 @@ public override bool Equals(object? obj) return Equals((UserProfile)obj); } + /// public override int GetHashCode() => Id; } diff --git a/src/Umbraco.Core/Models/Membership/UserState.cs b/src/Umbraco.Core/Models/Membership/UserState.cs index e59e4d25c854..0cbdee6d2b42 100644 --- a/src/Umbraco.Core/Models/Membership/UserState.cs +++ b/src/Umbraco.Core/Models/Membership/UserState.cs @@ -5,10 +5,33 @@ namespace Umbraco.Cms.Core.Models.Membership; /// public enum UserState { + /// + /// Represents all user states (used for filtering). + /// All = -1, + + /// + /// The user is active and can log in. + /// Active = 0, + + /// + /// The user is disabled and cannot log in. + /// Disabled = 1, + + /// + /// The user is locked out due to too many failed login attempts. + /// LockedOut = 2, + + /// + /// The user has been invited but has not yet accepted. + /// Invited = 3, + + /// + /// The user has never logged in. + /// Inactive = 4, } diff --git a/src/Umbraco.Core/Models/Membership/UserUnlockResult.cs b/src/Umbraco.Core/Models/Membership/UserUnlockResult.cs index a37cb3587cc6..66fe086f0207 100644 --- a/src/Umbraco.Core/Models/Membership/UserUnlockResult.cs +++ b/src/Umbraco.Core/Models/Membership/UserUnlockResult.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.Membership; +namespace Umbraco.Cms.Core.Models.Membership; +/// +/// Represents the result of a user unlock operation. +/// public class UserUnlockResult : ErrorMessageResult { } diff --git a/src/Umbraco.Core/Models/Navigation/NavigationNode.cs b/src/Umbraco.Core/Models/Navigation/NavigationNode.cs index 385abfa62fbd..1e7596c6e939 100644 --- a/src/Umbraco.Core/Models/Navigation/NavigationNode.cs +++ b/src/Umbraco.Core/Models/Navigation/NavigationNode.cs @@ -3,20 +3,44 @@ namespace Umbraco.Cms.Core.Models.Navigation; +/// +/// Represents a node in the content navigation structure. +/// public sealed class NavigationNode { private ConcurrentHashSet _children; + /// + /// Gets the unique key of this navigation node. + /// public Guid Key { get; private set; } + /// + /// Gets the unique key of the content type for this node. + /// public Guid ContentTypeKey { get; private set; } + /// + /// Gets the sort order of this node among its siblings. + /// public int SortOrder { get; private set; } + /// + /// Gets the key of the parent node, or null if this is a root node. + /// public Guid? Parent { get; private set; } + /// + /// Gets the set of child node keys. + /// public ISet Children => _children; + /// + /// Initializes a new instance of the class. + /// + /// The unique key of the node. + /// The unique key of the content type. + /// The sort order of the node. public NavigationNode(Guid key, Guid contentTypeKey, int sortOrder = 0) { Key = key; @@ -25,8 +49,18 @@ public NavigationNode(Guid key, Guid contentTypeKey, int sortOrder = 0) _children = new ConcurrentHashSet(); } + /// + /// Updates the sort order of this node. + /// + /// The new sort order value. public void UpdateSortOrder(int newSortOrder) => SortOrder = newSortOrder; + /// + /// Adds a child node to this node. + /// + /// The navigation structure dictionary containing all nodes. + /// The key of the child node to add. + /// Thrown when the child key is not found in the navigation structure. public void AddChild(ConcurrentDictionary navigationStructure, Guid childKey) { if (navigationStructure.TryGetValue(childKey, out NavigationNode? child) is false) @@ -42,6 +76,12 @@ public void AddChild(ConcurrentDictionary navigationStruct _children.Add(childKey); } + /// + /// Removes a child node from this node. + /// + /// The navigation structure dictionary containing all nodes. + /// The key of the child node to remove. + /// Thrown when the child key is not found in the navigation structure. public void RemoveChild(ConcurrentDictionary navigationStructure, Guid childKey) { if (navigationStructure.TryGetValue(childKey, out NavigationNode? child) is false) diff --git a/src/Umbraco.Core/Models/NodePermissions.cs b/src/Umbraco.Core/Models/NodePermissions.cs index b5a48b3e9f2c..96aa756a59ba 100644 --- a/src/Umbraco.Core/Models/NodePermissions.cs +++ b/src/Umbraco.Core/Models/NodePermissions.cs @@ -1,11 +1,17 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; /// /// A model representing a set of permissions for a given node. /// public class NodePermissions { + /// + /// Gets or sets the unique identifier of the node. + /// public Guid NodeKey { get; set; } + /// + /// Gets or sets the collection of permission identifiers assigned to this node. + /// public ISet Permissions { get; set; } = new HashSet(); } diff --git a/src/Umbraco.Core/Models/Notification.cs b/src/Umbraco.Core/Models/Notification.cs index e93a3bdeb6d4..402e27d6f1e9 100644 --- a/src/Umbraco.Core/Models/Notification.cs +++ b/src/Umbraco.Core/Models/Notification.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a notification subscription for a user on an entity. +/// public class Notification { + /// + /// Initializes a new instance of the class. + /// + /// The identifier of the entity being watched. + /// The identifier of the user subscribing to the notification. + /// The action that triggers the notification. + /// The type of entity being watched. public Notification(int entityId, int userId, string action, Guid entityType) { EntityId = entityId; @@ -10,11 +20,23 @@ public Notification(int entityId, int userId, string action, Guid entityType) EntityType = entityType; } + /// + /// Gets the identifier of the entity being watched. + /// public int EntityId { get; } + /// + /// Gets the identifier of the user subscribing to the notification. + /// public int UserId { get; } + /// + /// Gets the action that triggers the notification. + /// public string Action { get; } + /// + /// Gets the type of entity being watched. + /// public Guid EntityType { get; } } diff --git a/src/Umbraco.Core/Models/NotificationEmailBodyParams.cs b/src/Umbraco.Core/Models/NotificationEmailBodyParams.cs index 85e2cfdcd68c..f3b239b9d86a 100644 --- a/src/Umbraco.Core/Models/NotificationEmailBodyParams.cs +++ b/src/Umbraco.Core/Models/NotificationEmailBodyParams.cs @@ -1,7 +1,22 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents the parameters used for generating a notification email body. +/// public class NotificationEmailBodyParams { + /// + /// Initializes a new instance of the class. + /// + /// The name of the email recipient. + /// The action that triggered the notification (e.g., "published", "updated"). + /// The name of the content item affected. + /// The unique identifier of the content item. + /// The URL to the content item in the backoffice. + /// The name of the user who performed the action. + /// The base URL of the site. + /// The summary of changes, either HTML or text based depending on email type. + /// Thrown when any parameter is null. public NotificationEmailBodyParams(string? recipientName, string? action, string? itemName, string itemId, string itemUrl, string? editedUser, string siteUrl, string summary) { RecipientName = recipientName ?? throw new ArgumentNullException(nameof(recipientName)); @@ -14,14 +29,29 @@ public NotificationEmailBodyParams(string? recipientName, string? action, string SiteUrl = siteUrl ?? throw new ArgumentNullException(nameof(siteUrl)); } + /// + /// Gets the name of the email recipient. + /// public string RecipientName { get; } + /// + /// Gets the action that triggered the notification (e.g., "published", "updated"). + /// public string Action { get; } + /// + /// Gets the name of the content item affected. + /// public string ItemName { get; } + /// + /// Gets the unique identifier of the content item. + /// public string ItemId { get; } + /// + /// Gets the URL to the content item in the backoffice. + /// public string ItemUrl { get; } /// @@ -29,7 +59,13 @@ public NotificationEmailBodyParams(string? recipientName, string? action, string /// public string Summary { get; } + /// + /// Gets the name of the user who performed the action. + /// public string EditedUser { get; } + /// + /// Gets the base URL of the site. + /// public string SiteUrl { get; } } diff --git a/src/Umbraco.Core/Models/NotificationEmailSubjectParams.cs b/src/Umbraco.Core/Models/NotificationEmailSubjectParams.cs index 51b1e4031ee8..830f47161ec3 100644 --- a/src/Umbraco.Core/Models/NotificationEmailSubjectParams.cs +++ b/src/Umbraco.Core/Models/NotificationEmailSubjectParams.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents the parameters used to construct a notification email subject line. +/// public class NotificationEmailSubjectParams { + /// + /// Initializes a new instance of the class. + /// + /// The URL of the site. + /// The action that triggered the notification. + /// The name of the item involved in the action. + /// Thrown when any parameter is null. public NotificationEmailSubjectParams(string siteUrl, string? action, string? itemName) { SiteUrl = siteUrl ?? throw new ArgumentNullException(nameof(siteUrl)); @@ -9,9 +19,18 @@ public NotificationEmailSubjectParams(string siteUrl, string? action, string? it ItemName = itemName ?? throw new ArgumentNullException(nameof(itemName)); } + /// + /// Gets the URL of the site. + /// public string SiteUrl { get; } + /// + /// Gets the action that triggered the notification. + /// public string Action { get; } + /// + /// Gets the name of the item involved in the action. + /// public string ItemName { get; } } diff --git a/src/Umbraco.Core/Models/OutOfDateType.cs b/src/Umbraco.Core/Models/OutOfDateType.cs index 3dd68b1b3c6a..4aee57a174fb 100644 --- a/src/Umbraco.Core/Models/OutOfDateType.cs +++ b/src/Umbraco.Core/Models/OutOfDateType.cs @@ -1,8 +1,22 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Defines the status of whether something is up to date. +/// public enum OutOfDateType { + /// + /// Indicates the item is out of date and needs updating. + /// OutOfDate, + + /// + /// Indicates the item is current and up to date. + /// Current, + + /// + /// Indicates the status could not be determined. + /// Unknown = 100 } diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs index eb6aa1c0608f..d719a95d749c 100644 --- a/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackage.cs @@ -7,31 +7,73 @@ namespace Umbraco.Cms.Core.Models.Packaging; /// public class CompiledPackage { + /// + /// Gets or sets the package file information. + /// public FileInfo? PackageFile { get; set; } + /// + /// Gets or sets the name of the package. + /// public string Name { get; set; } = null!; + /// + /// Gets or sets the installation warnings for the package. + /// public InstallWarnings Warnings { get; set; } = new(); + /// + /// Gets or sets the collection of template XML elements. + /// public IEnumerable Templates { get; set; } = null!; // TODO: make strongly typed + /// + /// Gets or sets the collection of stylesheet XML elements. + /// public IEnumerable Stylesheets { get; set; } = null!; // TODO: make strongly typed + /// + /// Gets or sets the collection of script XML elements. + /// public IEnumerable Scripts { get; set; } = null!; // TODO: make strongly typed + /// + /// Gets or sets the collection of partial view XML elements. + /// public IEnumerable PartialViews { get; set; } = null!; // TODO: make strongly typed + /// + /// Gets or sets the collection of data type XML elements. + /// public IEnumerable DataTypes { get; set; } = null!; // TODO: make strongly typed + /// + /// Gets or sets the collection of language XML elements. + /// public IEnumerable Languages { get; set; } = null!; // TODO: make strongly typed + /// + /// Gets or sets the collection of dictionary item XML elements. + /// public IEnumerable DictionaryItems { get; set; } = null!; // TODO: make strongly typed + /// + /// Gets or sets the collection of document type XML elements. + /// public IEnumerable DocumentTypes { get; set; } = null!; // TODO: make strongly typed + /// + /// Gets or sets the collection of media type XML elements. + /// public IEnumerable MediaTypes { get; set; } = null!; // TODO: make strongly typed + /// + /// Gets or sets the collection of compiled document content. + /// public IEnumerable Documents { get; set; } = null!; + /// + /// Gets or sets the collection of compiled media content. + /// public IEnumerable Media { get; set; } = null!; } diff --git a/src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs b/src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs index 794262406a69..4a34f8160e16 100644 --- a/src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs +++ b/src/Umbraco.Core/Models/Packaging/CompiledPackageContentBase.cs @@ -8,6 +8,9 @@ namespace Umbraco.Cms.Core.Models.Packaging; /// public class CompiledPackageContentBase { + /// + /// Gets or sets the import mode for the content. + /// public string? ImportMode { get; set; } // this is never used /// @@ -15,6 +18,11 @@ public class CompiledPackageContentBase /// public XElement XmlData { get; set; } = null!; + /// + /// Creates a new from an XML element. + /// + /// The XML element containing the content data. + /// A new compiled package content base instance. public static CompiledPackageContentBase Create(XElement xml) => new() { XmlData = xml, ImportMode = xml.AttributeValue("importMode") }; } diff --git a/src/Umbraco.Core/Models/Packaging/InstallWarnings.cs b/src/Umbraco.Core/Models/Packaging/InstallWarnings.cs index 545e009cb2cf..dad8dd5ddec0 100644 --- a/src/Umbraco.Core/Models/Packaging/InstallWarnings.cs +++ b/src/Umbraco.Core/Models/Packaging/InstallWarnings.cs @@ -1,9 +1,18 @@ namespace Umbraco.Cms.Core.Models.Packaging; +/// +/// Represents warnings that may occur during package installation due to conflicting entities. +/// public class InstallWarnings { // TODO: Shouldn't we detect other conflicting entities too ? + /// + /// Gets or sets the collection of templates that conflict with existing templates. + /// public IEnumerable? ConflictingTemplates { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of stylesheets that conflict with existing stylesheets. + /// public IEnumerable? ConflictingStylesheets { get; set; } = Enumerable.Empty(); } diff --git a/src/Umbraco.Core/Models/PagedModel.cs b/src/Umbraco.Core/Models/PagedModel.cs index f7b9d0226042..779f8a21bf60 100644 --- a/src/Umbraco.Core/Models/PagedModel.cs +++ b/src/Umbraco.Core/Models/PagedModel.cs @@ -1,18 +1,36 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents a paged collection of items with total count information. +/// +/// The type of items in the collection. public class PagedModel { + /// + /// Initializes a new instance of the class. + /// public PagedModel() { } + /// + /// Initializes a new instance of the class with the specified total and items. + /// + /// The total number of items available. + /// The items for the current page. public PagedModel(long total, IEnumerable items) { Total = total; Items = items; } + /// + /// Gets the items for the current page. + /// public IEnumerable Items { get; init; } = Enumerable.Empty(); + /// + /// Gets the total number of items available across all pages. + /// public long Total { get; init; } } diff --git a/src/Umbraco.Core/Models/PagedResult.cs b/src/Umbraco.Core/Models/PagedResult.cs index 15e057620243..3693d12225dc 100644 --- a/src/Umbraco.Core/Models/PagedResult.cs +++ b/src/Umbraco.Core/Models/PagedResult.cs @@ -9,6 +9,12 @@ namespace Umbraco.Cms.Core.Models; [DataContract(Name = "pagedCollection", Namespace = "")] public abstract class PagedResult { + /// + /// Initializes a new instance of the class. + /// + /// The total number of items. + /// The current page number (1-based). + /// The number of items per page. public PagedResult(long totalItems, long pageNumber, long pageSize) { TotalItems = totalItems; @@ -25,15 +31,27 @@ public PagedResult(long totalItems, long pageNumber, long pageSize) } } + /// + /// Gets the current page number (1-based). + /// [DataMember(Name = "pageNumber")] public long PageNumber { get; private set; } + /// + /// Gets the number of items per page. + /// [DataMember(Name = "pageSize")] public long PageSize { get; private set; } + /// + /// Gets the total number of pages. + /// [DataMember(Name = "totalPages")] public long TotalPages { get; private set; } + /// + /// Gets the total number of items across all pages. + /// [DataMember(Name = "totalItems")] public long TotalItems { get; private set; } diff --git a/src/Umbraco.Core/Models/PagedResult{T}.cs b/src/Umbraco.Core/Models/PagedResult{T}.cs index f84dd89f7d44..1c78aecdbe44 100644 --- a/src/Umbraco.Core/Models/PagedResult{T}.cs +++ b/src/Umbraco.Core/Models/PagedResult{T}.cs @@ -10,11 +10,20 @@ namespace Umbraco.Cms.Core.Models; [Obsolete ("Superseded by PagedModel for service layer and below OR PagedViewModel in apis. Expected to be removed when skip/take pattern has been fully implemented v14+")] public class PagedResult : PagedResult { + /// + /// Initializes a new instance of the class. + /// + /// The total number of items. + /// The current page number (1-based). + /// The number of items per page. public PagedResult(long totalItems, long pageNumber, long pageSize) : base(totalItems, pageNumber, pageSize) { } + /// + /// Gets or sets the items for the current page. + /// [DataMember(Name = "items")] public IEnumerable? Items { get; set; } } diff --git a/src/Umbraco.Core/Models/PartialView.cs b/src/Umbraco.Core/Models/PartialView.cs index 07e2e1750aa1..cdb5fcca1ea1 100644 --- a/src/Umbraco.Core/Models/PartialView.cs +++ b/src/Umbraco.Core/Models/PartialView.cs @@ -9,11 +9,20 @@ namespace Umbraco.Cms.Core.Models; [DataContract(IsReference = true)] public class PartialView : File, IPartialView { + /// + /// Initializes a new instance of the class with the specified path. + /// + /// The path to the partial view file. public PartialView(string path) : this(path, null) { } + /// + /// Initializes a new instance of the class with the specified path and content retrieval function. + /// + /// The path to the partial view file. + /// A function to retrieve the file content. public PartialView(string path, Func? getFileContent) : base(path, getFileContent) { diff --git a/src/Umbraco.Core/Models/PartialViewCreateModel.cs b/src/Umbraco.Core/Models/PartialViewCreateModel.cs index 2b7bfe941738..34fbdb7d11bd 100644 --- a/src/Umbraco.Core/Models/PartialViewCreateModel.cs +++ b/src/Umbraco.Core/Models/PartialViewCreateModel.cs @@ -1,6 +1,8 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents the model for creating a new partial view. +/// public class PartialViewCreateModel : TextFileCreateModel { - } diff --git a/src/Umbraco.Core/Models/PartialViewRenameModel.cs b/src/Umbraco.Core/Models/PartialViewRenameModel.cs index da339e40c4b1..c5acbee8df95 100644 --- a/src/Umbraco.Core/Models/PartialViewRenameModel.cs +++ b/src/Umbraco.Core/Models/PartialViewRenameModel.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents the model for renaming a partial view. +/// public class PartialViewRenameModel : TextFileRenameModel { } diff --git a/src/Umbraco.Core/Models/PartialViewUpdateModel.cs b/src/Umbraco.Core/Models/PartialViewUpdateModel.cs index 29ac5018439d..9dcb11515323 100644 --- a/src/Umbraco.Core/Models/PartialViewUpdateModel.cs +++ b/src/Umbraco.Core/Models/PartialViewUpdateModel.cs @@ -1,6 +1,8 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents the model for updating a partial view. +/// public class PartialViewUpdateModel : TextFileUpdateModel { - } diff --git a/src/Umbraco.Core/Models/Property.cs b/src/Umbraco.Core/Models/Property.cs index 05b93f2f5776..c11a09969dbb 100644 --- a/src/Umbraco.Core/Models/Property.cs +++ b/src/Umbraco.Core/Models/Property.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using System.Runtime.Serialization; using Umbraco.Cms.Core.Collections; using Umbraco.Cms.Core.Models.Entities; @@ -175,8 +175,16 @@ public static Property CreateWithValues(int id, IPropertyType propertyType, para : null; } - // internal - must be invoked by the content item - // does *not* validate the value - content item must validate first + /// + /// Publishes partial property values for a specific culture by merging edited and published values. + /// + /// The data editor used for merging values. + /// The culture to publish values for. + /// + /// This method is for internal use and must be invoked by the content item. + /// It does not validate the value - the content item must validate first. + /// + /// Thrown when attempting to publish merged culture values for culture variant properties. public void PublishPartialValues(IDataEditor dataEditor, string? culture) { if (PropertyType.VariesByCulture()) @@ -190,8 +198,15 @@ public void PublishPartialValues(IDataEditor dataEditor, string? culture) PublishValue(_pvalue, value); } - // internal - must be invoked by the content item - // does *not* validate the value - content item must validate first + /// + /// Publishes property values for the specified culture and segment. + /// + /// The culture to publish, or "*" for all cultures, or null for invariant. + /// The segment to publish, or "*" for all segments, or null for neutral. + /// + /// This method is for internal use and must be invoked by the content item. + /// It does not validate the value - the content item must validate first. + /// public void PublishValues(string? culture = "*", string? segment = "*") { culture = culture?.NullOrWhiteSpaceAsNull(); @@ -224,7 +239,14 @@ public void PublishValues(string? culture = "*", string? segment = "*") } } - // internal - must be invoked by the content item + /// + /// Unpublishes property values for the specified culture and segment. + /// + /// The culture to unpublish, or "*" for all cultures, or null for invariant. + /// The segment to unpublish, or "*" for all segments, or null for neutral. + /// + /// This method is for internal use and must be invoked by the content item. + /// public void UnpublishValues(string? culture = "*", string? segment = "*") { culture = culture?.NullOrWhiteSpaceAsNull(); @@ -285,9 +307,15 @@ public bool SetValue(object? value, string? culture = null, string? segment = nu return changed; } + /// + /// Converts an assigned value to the appropriate type for this property. + /// + /// The value to convert. + /// The converted value, or null if conversion fails. public object? ConvertAssignedValue(object? value) => TryConvertAssignedValue(value, true, out var converted) ? converted : null; + /// protected override void PerformDeepClone(object clone) { base.PerformDeepClone(clone); @@ -570,6 +598,13 @@ private bool IsOfExpectedPropertyType(object? value) /// public class InitialPropertyValue { + /// + /// Initializes a new instance of the class. + /// + /// The culture for this value. + /// The segment for this value. + /// Whether this is a published value. + /// The property value. public InitialPropertyValue(string? culture, string? segment, bool published, object? value) { Culture = culture; @@ -578,12 +613,24 @@ public InitialPropertyValue(string? culture, string? segment, bool published, ob Value = value; } + /// + /// Gets the culture for this value. + /// public string? Culture { get; } + /// + /// Gets the segment for this value. + /// public string? Segment { get; } + /// + /// Gets a value indicating whether this is a published value. + /// public bool Published { get; } + /// + /// Gets the property value. + /// public object? Value { get; } } @@ -604,8 +651,10 @@ public class PropertyValue : IPropertyValue, IDeepCloneable, IEquatable public string? Culture { get; set; } + /// public object DeepClone() => Clone(); + /// public bool Equals(PropertyValue? other) => other != null && Culture == other.Culture && @@ -644,8 +693,10 @@ public IPropertyValue Clone() EditedValue = EditedValue, }; + /// public override bool Equals(object? obj) => Equals(obj as PropertyValue); + /// public override int GetHashCode() { var hashCode = 1885328050; diff --git a/src/Umbraco.Core/Models/PropertyCollection.cs b/src/Umbraco.Core/Models/PropertyCollection.cs index 330869f7172c..3b0b5537da1b 100644 --- a/src/Umbraco.Core/Models/PropertyCollection.cs +++ b/src/Umbraco.Core/Models/PropertyCollection.cs @@ -77,12 +77,14 @@ public PropertyCollection(IEnumerable properties) } } + /// public new bool TryGetValue(string propertyTypeAlias, [MaybeNullWhen(false)] out IProperty property) { property = this.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias)); return property != null; } + /// public void ClearCollectionChangedEvents() => CollectionChanged = null; /// @@ -194,6 +196,7 @@ protected override void ClearItems() OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } + /// protected override string GetKeyForItem(IProperty item) => item.Alias; /// @@ -212,6 +215,10 @@ private int IndexOfKey(string key) return -1; } + /// + /// Raises the event. + /// + /// The event arguments. protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs args) => CollectionChanged?.Invoke(this, args); } diff --git a/src/Umbraco.Core/Models/PropertyGroup.cs b/src/Umbraco.Core/Models/PropertyGroup.cs index 9d23c85a9b93..5d093f229d2e 100644 --- a/src/Umbraco.Core/Models/PropertyGroup.cs +++ b/src/Umbraco.Core/Models/PropertyGroup.cs @@ -15,6 +15,9 @@ namespace Umbraco.Cms.Core.Models; [DebuggerDisplay("Id: {Id}, Name: {Name}, Alias: {Alias}")] public class PropertyGroup : EntityBase, IEquatable { + /// + /// The parent collection this group belongs to. Internal use only. + /// [SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "This field is for internal use only (to allow changing item keys).")] internal PropertyGroupCollection? Collection; @@ -25,11 +28,19 @@ public class PropertyGroup : EntityBase, IEquatable private PropertyGroupType _type; + /// + /// Initializes a new instance of the class. + /// + /// A value indicating whether the property types support publishing. public PropertyGroup(bool isPublishing) : this(new PropertyTypeCollection(isPublishing)) { } + /// + /// Initializes a new instance of the class with a property type collection. + /// + /// The collection of property types for this group. public PropertyGroup(PropertyTypeCollection propertyTypeCollection) { PropertyTypes = propertyTypeCollection; @@ -132,11 +143,14 @@ public PropertyTypeCollection? PropertyTypes } } + /// public bool Equals(PropertyGroup? other) => base.Equals(other) || (other != null && Type == other.Type && Alias == other.Alias && Id == other.Id); + /// public override int GetHashCode() => (base.GetHashCode(), Type, Alias).GetHashCode(); + /// protected override void PerformDeepClone(object clone) { base.PerformDeepClone(clone); diff --git a/src/Umbraco.Core/Models/PropertyGroupCollection.cs b/src/Umbraco.Core/Models/PropertyGroupCollection.cs index 5e4479ec378a..46ca61e32eea 100644 --- a/src/Umbraco.Core/Models/PropertyGroupCollection.cs +++ b/src/Umbraco.Core/Models/PropertyGroupCollection.cs @@ -27,8 +27,10 @@ public PropertyGroupCollection() /// The groups. public PropertyGroupCollection(IEnumerable groups) => Reset(groups); + /// public event NotifyCollectionChangedEventHandler? CollectionChanged; + /// public object DeepClone() { var clone = new PropertyGroupCollection(); @@ -40,6 +42,12 @@ public object DeepClone() return clone; } + /// + /// Adds a property group to the collection. + /// + /// The property group to add. + /// Thrown when the property group does not have an alias set. + /// Thrown when changing the alias would result in duplicates. public new void Add(PropertyGroup item) { // Ensure alias is set @@ -81,6 +89,11 @@ public object DeepClone() base.Add(item); } + /// + /// Determines whether the collection contains a property group with the specified identifier. + /// + /// The identifier to search for. + /// true if a property group with the specified identifier exists; otherwise, false. public bool Contains(int id) => IndexOfKey(id) != -1; /// @@ -101,6 +114,7 @@ internal void Reset(IEnumerable groups) } } + /// protected override void SetItem(int index, PropertyGroup item) { PropertyGroup oldItem = index >= 0 ? this[index] : item; @@ -113,6 +127,7 @@ protected override void SetItem(int index, PropertyGroup item) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, oldItem)); } + /// protected override void RemoveItem(int index) { PropertyGroup removed = this[index]; @@ -124,6 +139,7 @@ protected override void RemoveItem(int index) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removed)); } + /// protected override void InsertItem(int index, PropertyGroup item) { base.InsertItem(index, item); @@ -133,6 +149,7 @@ protected override void InsertItem(int index, PropertyGroup item) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); } + /// protected override void ClearItems() { foreach (PropertyGroup item in this) @@ -144,10 +161,25 @@ protected override void ClearItems() OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } + /// + /// Changes the key (alias) of a property group in the collection. + /// + /// The property group to update. + /// The new key (alias) value. internal void ChangeKey(PropertyGroup item, string newKey) => ChangeItemKey(item, newKey); + /// + /// Gets the index of the property group with the specified alias. + /// + /// The alias to search for. + /// The zero-based index of the property group, or -1 if not found. public int IndexOfKey(string key) => this.FindIndex(x => x.Alias == key); + /// + /// Gets the index of the property group with the specified identifier. + /// + /// The identifier to search for. + /// The zero-based index of the property group, or -1 if not found. public int IndexOfKey(int id) => this.FindIndex(x => x.Id == id); /// @@ -155,8 +187,13 @@ protected override void ClearItems() /// public void ClearCollectionChangedEvents() => CollectionChanged = null; + /// protected override string GetKeyForItem(PropertyGroup item) => item.Alias; + /// + /// Raises the event. + /// + /// The event arguments. protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs args) => CollectionChanged?.Invoke(this, args); } diff --git a/src/Umbraco.Core/Models/PropertyGroupExtensions.cs b/src/Umbraco.Core/Models/PropertyGroupExtensions.cs index 95f3bce75bc2..1e95d068d5bd 100644 --- a/src/Umbraco.Core/Models/PropertyGroupExtensions.cs +++ b/src/Umbraco.Core/Models/PropertyGroupExtensions.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Provides extension methods for . +/// public static class PropertyGroupExtensions { private const char AliasSeparator = '/'; @@ -13,6 +16,11 @@ public static class PropertyGroupExtensions /// public static string? GetLocalAlias(this PropertyGroup propertyGroup) => GetLocalAlias(propertyGroup.Alias); + /// + /// Gets the local alias from a full alias string. + /// + /// The full alias. + /// The local alias portion after the last separator. internal static string? GetLocalAlias(string alias) { var lastIndex = alias?.LastIndexOf(AliasSeparator) ?? -1; @@ -24,6 +32,11 @@ public static class PropertyGroupExtensions return alias; } + /// + /// Gets the parent alias from a full alias string. + /// + /// The full alias. + /// The parent alias portion before the last separator, or null if there is no separator. internal static string? GetParentAlias(string? alias) { var lastIndex = alias?.LastIndexOf(AliasSeparator) ?? -1; diff --git a/src/Umbraco.Core/Models/PropertyTagsExtensions.cs b/src/Umbraco.Core/Models/PropertyTagsExtensions.cs index 9a39d19cd7d7..3d900738fd23 100644 --- a/src/Umbraco.Core/Models/PropertyTagsExtensions.cs +++ b/src/Umbraco.Core/Models/PropertyTagsExtensions.cs @@ -12,8 +12,13 @@ namespace Umbraco.Extensions; /// public static class PropertyTagsExtensions { - // gets the tag configuration for a property - // from the datatype configuration, and the editor tag configuration attribute + /// + /// Gets the tag configuration for a property from the datatype configuration and editor tag configuration attribute. + /// + /// The property. + /// The property editors collection. + /// The data type service. + /// The tag configuration if available; otherwise, null. public static TagConfiguration? GetTagConfiguration(this IProperty property, PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService) { if (property == null) @@ -37,6 +42,9 @@ public static class PropertyTagsExtensions return configuration; } + /// + /// Gets the tags property editor attribute from the data editor. + /// private static TagsPropertyEditorAttribute? GetTagAttribute(IDataEditor? editor) => editor?.GetType().GetCustomAttribute(false); @@ -91,7 +99,15 @@ public static void RemoveTags(this IProperty property, PropertyEditorCollection property.RemoveTags(tags, configuration.StorageType, serializer, configuration.Delimiter, culture); } - // used by ContentRepositoryBase + /// + /// Gets the tags value from a property. Used by ContentRepositoryBase. + /// + /// The property. + /// The property editors collection. + /// The data type service. + /// The JSON serializer. + /// A culture, for multi-lingual properties. + /// An enumeration of tag values. public static IEnumerable GetTagsValue(this IProperty property, PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService, IJsonSerializer serializer, string? culture = null) { if (property == null) diff --git a/src/Umbraco.Core/Models/PropertyTypeCollection.cs b/src/Umbraco.Core/Models/PropertyTypeCollection.cs index 77a5d84421a0..62f9f3c7e490 100644 --- a/src/Umbraco.Core/Models/PropertyTypeCollection.cs +++ b/src/Umbraco.Core/Models/PropertyTypeCollection.cs @@ -17,14 +17,27 @@ namespace Umbraco.Cms.Core.Models; public class PropertyTypeCollection : KeyedCollection, INotifyCollectionChanged, IDeepCloneable, ICollection { + /// + /// Initializes a new instance of the class. + /// + /// A value indicating whether the property types in this collection support publishing. public PropertyTypeCollection(bool supportsPublishing) => SupportsPublishing = supportsPublishing; + /// + /// Initializes a new instance of the class with initial property types. + /// + /// A value indicating whether the property types in this collection support publishing. + /// The initial property types to add to the collection. public PropertyTypeCollection(bool supportsPublishing, IEnumerable properties) : this(supportsPublishing) => Reset(properties); + /// public event NotifyCollectionChangedEventHandler? CollectionChanged; + /// + /// Gets a value indicating whether the property types in this collection support publishing. + /// public bool SupportsPublishing { get; } // This baseclass calling is needed, else compiler will complain about nullability @@ -32,8 +45,15 @@ public PropertyTypeCollection(bool supportsPublishing, IEnumerable public bool IsReadOnly => false; - // 'new' keyword is required! we can explicitly implement ICollection.Add BUT since normally a concrete PropertyType type - // is passed in, the explicit implementation doesn't get called, this ensures it does get called. + /// + /// Adds a property type to the collection. + /// + /// The property type to add. + /// + /// The 'new' keyword is required because we can explicitly implement , + /// but since normally a concrete PropertyType type is passed in, the explicit implementation doesn't get called. + /// This ensures it does get called. + /// public new void Add(IPropertyType item) { item.SupportsPublishing = SupportsPublishing; @@ -62,6 +82,7 @@ public PropertyTypeCollection(bool supportsPublishing, IEnumerable public object DeepClone() { var clone = new PropertyTypeCollection(SupportsPublishing); @@ -100,6 +121,7 @@ internal void Reset(IEnumerable properties) } } + /// protected override void SetItem(int index, IPropertyType item) { item.SupportsPublishing = SupportsPublishing; @@ -109,6 +131,7 @@ protected override void SetItem(int index, IPropertyType item) item.PropertyChanged += Item_PropertyChanged; } + /// protected override void RemoveItem(int index) { IPropertyType removed = this[index]; @@ -117,6 +140,7 @@ protected override void RemoveItem(int index) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removed)); } + /// protected override void InsertItem(int index, IPropertyType item) { item.SupportsPublishing = SupportsPublishing; @@ -125,6 +149,7 @@ protected override void InsertItem(int index, IPropertyType item) item.PropertyChanged += Item_PropertyChanged; } + /// protected override void ClearItems() { base.ClearItems(); @@ -148,6 +173,11 @@ private void Item_PropertyChanged(object? sender, PropertyChangedEventArgs e) new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, propType, propType)); } + /// + /// Removes the property type with the specified alias from the collection. + /// + /// The alias of the property type to remove. + /// true if the property type was found and removed; otherwise, false. public bool RemoveItem(string propertyTypeAlias) { var key = IndexOfKey(propertyTypeAlias); @@ -159,6 +189,11 @@ public bool RemoveItem(string propertyTypeAlias) return key != -1; } + /// + /// Gets the index of the property type with the specified alias. + /// + /// The alias to search for. + /// The zero-based index of the property type, or -1 if not found. public int IndexOfKey(string key) { for (var i = 0; i < Count; i++) @@ -177,8 +212,13 @@ public int IndexOfKey(string key) /// public void ClearCollectionChangedEvents() => CollectionChanged = null; + /// protected override string GetKeyForItem(IPropertyType item) => item.Alias; + /// + /// Raises the event. + /// + /// The event arguments. protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs args) => CollectionChanged?.Invoke(this, args); } diff --git a/src/Umbraco.Core/Models/PublicAccessEntry.cs b/src/Umbraco.Core/Models/PublicAccessEntry.cs index fdf376136625..3f8e3958c462 100644 --- a/src/Umbraco.Core/Models/PublicAccessEntry.cs +++ b/src/Umbraco.Core/Models/PublicAccessEntry.cs @@ -5,6 +5,13 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a public access entry that defines protection rules for a content node. +/// +/// +/// Public access entries define which content nodes are protected, which node serves as the login page, +/// which node is displayed when access is denied, and the rules that determine access permissions. +/// [Serializable] [DataContract(IsReference = true)] public class PublicAccessEntry : EntityBase @@ -15,6 +22,14 @@ public class PublicAccessEntry : EntityBase private int _noAccessNodeId; private int _protectedNodeId; + /// + /// Initializes a new instance of the class. + /// + /// The content node to protect. + /// The content node to redirect to for login. + /// The content node to display when access is denied. + /// The collection of access rules. + /// Thrown when any of the required parameters is null. public PublicAccessEntry(IContent protectedNode, IContent loginNode, IContent noAccessNode, IEnumerable ruleCollection) { if (protectedNode == null) @@ -45,6 +60,14 @@ public PublicAccessEntry(IContent protectedNode, IContent loginNode, IContent no } } + /// + /// Initializes a new instance of the class with explicit identifiers. + /// + /// The unique identifier for this entry. + /// The identifier of the protected content node. + /// The identifier of the login content node. + /// The identifier of the no-access content node. + /// The collection of access rules. public PublicAccessEntry(Guid id, int protectedNodeId, int loginNodeId, int noAccessNodeId, IEnumerable ruleCollection) { Key = id; @@ -63,10 +86,19 @@ public PublicAccessEntry(Guid id, int protectedNodeId, int loginNodeId, int noAc } } + /// + /// Gets the keys of rules that have been removed from this entry. + /// public IEnumerable RemovedRules => _removedRules; + /// + /// Gets the collection of access rules for this entry. + /// public IEnumerable Rules => _ruleCollection; + /// + /// Gets or sets the identifier of the login content node. + /// [DataMember] public int LoginNodeId { @@ -74,6 +106,9 @@ public int LoginNodeId set => SetPropertyValueAndDetectChanges(value, ref _loginNodeId, nameof(LoginNodeId)); } + /// + /// Gets or sets the identifier of the content node displayed when access is denied. + /// [DataMember] public int NoAccessNodeId { @@ -81,6 +116,9 @@ public int NoAccessNodeId set => SetPropertyValueAndDetectChanges(value, ref _noAccessNodeId, nameof(NoAccessNodeId)); } + /// + /// Gets or sets the identifier of the protected content node. + /// [DataMember] public int ProtectedNodeId { @@ -88,6 +126,12 @@ public int ProtectedNodeId set => SetPropertyValueAndDetectChanges(value, ref _protectedNodeId, nameof(ProtectedNodeId)); } + /// + /// Adds a new access rule to this entry. + /// + /// The value of the rule (e.g., a member group name or username). + /// The type of the rule (e.g., "RoleName" or "Username"). + /// The newly created access rule. public PublicAccessRule AddRule(string ruleValue, string ruleType) { var rule = new PublicAccessRule { AccessEntryId = Key, RuleValue = ruleValue, RuleType = ruleType }; @@ -122,10 +166,18 @@ private void RuleCollection_CollectionChanged(object? sender, NotifyCollectionCh } } + /// + /// Removes an access rule from this entry. + /// + /// The rule to remove. public void RemoveRule(PublicAccessRule rule) => _ruleCollection.Remove(rule); + /// + /// Removes all access rules from this entry. + /// public void ClearRules() => _ruleCollection.Clear(); + /// public override void ResetDirtyProperties(bool rememberDirty) { _removedRules.Clear(); @@ -136,8 +188,12 @@ public override void ResetDirtyProperties(bool rememberDirty) } } + /// + /// Clears the list of removed rules. + /// internal void ClearRemovedRules() => _removedRules.Clear(); + /// protected override void PerformDeepClone(object clone) { base.PerformDeepClone(clone); diff --git a/src/Umbraco.Core/Models/PublicAccessEntrySlim.cs b/src/Umbraco.Core/Models/PublicAccessEntrySlim.cs index 3ff92260dbb0..5648c3c23165 100644 --- a/src/Umbraco.Core/Models/PublicAccessEntrySlim.cs +++ b/src/Umbraco.Core/Models/PublicAccessEntrySlim.cs @@ -1,14 +1,32 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents a lightweight public access entry containing essential access control information. +/// public class PublicAccessEntrySlim { + /// + /// Gets or sets the unique identifier of the protected content. + /// public Guid ContentId { get; set; } + /// + /// Gets or sets the usernames of members allowed to access the content. + /// public string[] MemberUserNames { get; set; } = Array.Empty(); + /// + /// Gets or sets the names of member groups allowed to access the content. + /// public string[] MemberGroupNames { get; set; } = Array.Empty(); + /// + /// Gets or sets the unique identifier of the login page. + /// public Guid LoginPageId { get; set; } + /// + /// Gets or sets the unique identifier of the error page shown for unauthorized access. + /// public Guid ErrorPageId { get; set; } } diff --git a/src/Umbraco.Core/Models/PublicAccessNodesValidationResult.cs b/src/Umbraco.Core/Models/PublicAccessNodesValidationResult.cs index 68166b90bd4f..49e54745a2f7 100644 --- a/src/Umbraco.Core/Models/PublicAccessNodesValidationResult.cs +++ b/src/Umbraco.Core/Models/PublicAccessNodesValidationResult.cs @@ -1,11 +1,22 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents the validation result containing resolved content nodes for public access configuration. +/// public class PublicAccessNodesValidationResult { + /// + /// Gets or sets the content node that is being protected. + /// public IContent? ProtectedNode { get; set; } + /// + /// Gets or sets the login page content node. + /// public IContent? LoginNode { get; set; } + /// + /// Gets or sets the error page content node shown for unauthorized access. + /// public IContent? ErrorNode { get; set; } - } diff --git a/src/Umbraco.Core/Models/PublicAccessRule.cs b/src/Umbraco.Core/Models/PublicAccessRule.cs index f8af1a6d980e..908417a3be38 100644 --- a/src/Umbraco.Core/Models/PublicAccessRule.cs +++ b/src/Umbraco.Core/Models/PublicAccessRule.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a rule that defines access permissions for a public access entry. +/// [Serializable] [DataContract(IsReference = true)] public class PublicAccessRule : EntityBase @@ -10,6 +13,11 @@ public class PublicAccessRule : EntityBase private string? _ruleType; private string? _ruleValue; + /// + /// Initializes a new instance of the class with the specified identifiers. + /// + /// The unique identifier of the rule. + /// The unique identifier of the associated access entry. public PublicAccessRule(Guid id, Guid accessEntryId) { AccessEntryId = accessEntryId; @@ -17,18 +25,30 @@ public PublicAccessRule(Guid id, Guid accessEntryId) Id = Key.GetHashCode(); } + /// + /// Initializes a new instance of the class. + /// public PublicAccessRule() { } + /// + /// Gets or sets the unique identifier of the associated public access entry. + /// public Guid AccessEntryId { get; set; } + /// + /// Gets or sets the value of the rule (e.g., member username or group name). + /// public string? RuleValue { get => _ruleValue; set => SetPropertyValueAndDetectChanges(value, ref _ruleValue, nameof(RuleValue)); } + /// + /// Gets or sets the type of the rule (e.g., "Username" or "MemberType"). + /// public string? RuleType { get => _ruleType; diff --git a/src/Umbraco.Core/Models/PublishedContent/HybridVariationContextAccessor.cs b/src/Umbraco.Core/Models/PublishedContent/HybridVariationContextAccessor.cs index 2be963843856..1e3692490f1c 100644 --- a/src/Umbraco.Core/Models/PublishedContent/HybridVariationContextAccessor.cs +++ b/src/Umbraco.Core/Models/PublishedContent/HybridVariationContextAccessor.cs @@ -7,6 +7,10 @@ namespace Umbraco.Cms.Core.Models.PublishedContent; /// public class HybridVariationContextAccessor : HybridAccessorBase, IVariationContextAccessor { + /// + /// Initializes a new instance of the class. + /// + /// The request cache. public HybridVariationContextAccessor(IRequestCache requestCache) : base(requestCache) { diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedMember.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedMember.cs index 0d028961f6d2..0ae329aa1cc2 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedMember.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedMember.cs @@ -1,22 +1,56 @@ namespace Umbraco.Cms.Core.Models.PublishedContent; +/// +/// Represents a published member. +/// +/// +/// Extends with member-specific properties such as email, +/// username, and account status information. +/// public interface IPublishedMember : IPublishedContent { + /// + /// Gets the email address of the member. + /// public string Email { get; } + /// + /// Gets the username of the member. + /// public string UserName { get; } + /// + /// Gets the comments associated with the member account. + /// public string? Comments { get; } + /// + /// Gets a value indicating whether the member account is approved. + /// public bool IsApproved { get; } + /// + /// Gets a value indicating whether the member account is locked out. + /// public bool IsLockedOut { get; } + /// + /// Gets the date and time when the member account was last locked out. + /// public DateTime? LastLockoutDate { get; } + /// + /// Gets the date and time when the member account was created. + /// public DateTime CreationDate { get; } + /// + /// Gets the date and time of the member's last login. + /// public DateTime? LastLoginDate { get; } + /// + /// Gets the date and time when the member's password was last changed. + /// public DateTime? LastPasswordChangedDate { get; } } diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedMemberCache.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedMemberCache.cs index f7902676b743..f5a28838b1fe 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedMemberCache.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedMemberCache.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.PublishedCache; +/// +/// Provides a cache for published member content. +/// public interface IPublishedMemberCache { /// diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedProperty.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedProperty.cs index 23ca385da060..dfc430d74f7b 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedProperty.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedProperty.cs @@ -5,6 +5,9 @@ namespace Umbraco.Cms.Core.Models.PublishedContent; /// public interface IPublishedProperty { + /// + /// Gets the property type. + /// IPublishedPropertyType PropertyType { get; } /// diff --git a/src/Umbraco.Core/Models/PublishedContent/ModelType.cs b/src/Umbraco.Core/Models/PublishedContent/ModelType.cs index 56df7dae233f..ab404aab9a7e 100644 --- a/src/Umbraco.Core/Models/PublishedContent/ModelType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/ModelType.cs @@ -1,4 +1,4 @@ -using System.Globalization; +using System.Globalization; using System.Reflection; using Umbraco.Cms.Core.Exceptions; @@ -15,6 +15,10 @@ namespace Umbraco.Cms.Core.Models.PublishedContent; /// public class ModelType : Type { + /// + /// Initializes a new instance of the class. + /// + /// The content type alias. private ModelType(string? contentTypeAlias) { if (contentTypeAlias == null) @@ -86,6 +90,13 @@ public override string ToString() public static Type Map(Type type, Dictionary? modelTypes) => Map(type, modelTypes, false); + /// + /// Gets the actual CLR type by replacing model types, if any. + /// + /// The type. + /// The model types map. + /// A value indicating whether the dictionary is case-insensitive. + /// The actual CLR type. public static Type Map(Type type, Dictionary? modelTypes, bool dictionaryIsInvariant) { // it may be that senders forgot to send an invariant dictionary (garbage-in) @@ -372,11 +383,20 @@ public override Type MakeArrayType() => new ModelTypeArrayType(this); } -/// +/// +/// Represents an array type of a . +/// +/// +/// This class is used internally to represent array types of model types. +/// internal sealed class ModelTypeArrayType : Type { private readonly Type _elementType; + /// + /// Initializes a new instance of the class. + /// + /// The model type. public ModelTypeArrayType(ModelType type) { _elementType = type; @@ -384,38 +404,55 @@ public ModelTypeArrayType(ModelType type) Name = "{" + type.ContentTypeAlias + "}[*]"; } + /// + /// Gets the content type alias. + /// public string ContentTypeAlias { get; } + /// public override Type UnderlyingSystemType => this; + /// public override Type? BaseType => null; + /// public override string Name { get; } + /// public override Guid GUID { get; } = Guid.NewGuid(); + /// public override Module Module => GetType().Module; // hackish but FullName requires something + /// public override Assembly Assembly => GetType().Assembly; // hackish but FullName requires something + /// public override string FullName => Name; + /// public override string Namespace => string.Empty; + /// public override string AssemblyQualifiedName => Name; + /// public override string ToString() => Name; + /// public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) => Array.Empty(); + /// public override Type[] GetInterfaces() => Array.Empty(); + /// protected override TypeAttributes GetAttributeFlagsImpl() => TypeAttributes.Class; + /// protected override ConstructorInfo? GetConstructorImpl( BindingFlags bindingAttr, Binder? binder, @@ -424,30 +461,39 @@ protected override TypeAttributes GetAttributeFlagsImpl() ParameterModifier[]? modifiers) => null; + /// public override Type? GetInterface(string name, bool ignoreCase) => null; + /// public override EventInfo[] GetEvents(BindingFlags bindingAttr) => Array.Empty(); + /// public override EventInfo? GetEvent(string name, BindingFlags bindingAttr) => null; + /// public override Type[] GetNestedTypes(BindingFlags bindingAttr) => Array.Empty(); + /// public override Type? GetNestedType(string name, BindingFlags bindingAttr) => null; + /// public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) => Array.Empty(); + /// public override MethodInfo[] GetMethods(BindingFlags bindingAttr) => Array.Empty(); + /// public override FieldInfo[] GetFields(BindingFlags bindingAttr) => Array.Empty(); + /// protected override PropertyInfo? GetPropertyImpl( string name, BindingFlags bindingAttr, @@ -457,6 +503,7 @@ public override FieldInfo[] GetFields(BindingFlags bindingAttr) ParameterModifier[]? modifiers) => null; + /// protected override MethodInfo? GetMethodImpl( string name, BindingFlags bindingAttr, @@ -466,24 +513,31 @@ public override FieldInfo[] GetFields(BindingFlags bindingAttr) ParameterModifier[]? modifiers) => null; + /// public override FieldInfo? GetField(string name, BindingFlags bindingAttr) => null; + /// public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => Array.Empty(); + /// public override object[] GetCustomAttributes(Type attributeType, bool inherit) => Array.Empty(); + /// public override object[] GetCustomAttributes(bool inherit) => Array.Empty(); + /// public override bool IsDefined(Type attributeType, bool inherit) => false; + /// public override Type GetElementType() => _elementType; + /// public override object InvokeMember( string name, BindingFlags invokeAttr, @@ -495,24 +549,31 @@ public override object InvokeMember( string[]? namedParameters) => throw new NotSupportedException(); + /// protected override bool HasElementTypeImpl() => true; + /// protected override bool IsArrayImpl() => true; + /// protected override bool IsByRefImpl() => false; + /// protected override bool IsPointerImpl() => false; + /// protected override bool IsPrimitiveImpl() => false; + /// protected override bool IsCOMObjectImpl() => false; + /// public override int GetArrayRank() => 1; } diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentBase.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentBase.cs index 3687e1b7f3f2..df8d859f6464 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentBase.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentBase.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.PublishedCache; @@ -17,8 +17,13 @@ public abstract class PublishedContentBase : IPublishedContent { private readonly IVariationContextAccessor? _variationContextAccessor; + /// + /// Initializes a new instance of the class. + /// + /// The variation context accessor. protected PublishedContentBase(IVariationContextAccessor? variationContextAccessor) => _variationContextAccessor = variationContextAccessor; + /// public abstract IPublishedContentType ContentType { get; } /// @@ -87,6 +92,10 @@ public abstract class PublishedContentBase : IPublishedContent /// public abstract IPublishedProperty? GetProperty(string alias); + /// + /// Gets the children of the current content item. + /// + /// The children of the current content item. private IEnumerable GetChildren() { INavigationQueryService? navigationQueryService; diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeConverter.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeConverter.cs index c2b1cae7d7bf..56319ab937da 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeConverter.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeConverter.cs @@ -3,14 +3,22 @@ namespace Umbraco.Cms.Core.Models.PublishedContent; +/// +/// Provides a type converter for instances. +/// +/// +/// This converter allows converting to integer (Id). +/// internal sealed class PublishedContentTypeConverter : TypeConverter { private static readonly Type[] ConvertingTypes = { typeof(int) }; + /// public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType) => ConvertingTypes.Any(x => x.IsAssignableFrom(destinationType)) || (destinationType is not null && CanConvertFrom(context, destinationType)); + /// public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType) { if (!(value is IPublishedContent publishedContent)) diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs index 7ea877971848..dc7297310ac3 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentTypeFactory.cs @@ -14,6 +14,12 @@ public class PublishedContentTypeFactory : IPublishedContentTypeFactory private object _publishedDataTypesLocker = new(); private Dictionary? _publishedDataTypes; + /// + /// Initializes a new instance of the class. + /// + /// The published model factory. + /// The property value converters. + /// The data type service. public PublishedContentTypeFactory( IPublishedModelFactory publishedModelFactory, PropertyValueConverterCollection propertyValueConverters, diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedSearchResult.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedSearchResult.cs index f0c2626f906c..2d6c04f5c5e8 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedSearchResult.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedSearchResult.cs @@ -2,16 +2,30 @@ namespace Umbraco.Cms.Core.Models.PublishedContent; +/// +/// Represents a search result containing published content and its relevance score. +/// [DebuggerDisplay("{Content?.Name} ({Score})")] public class PublishedSearchResult { + /// + /// Initializes a new instance of the class. + /// + /// The published content item. + /// The relevance score of the search result. public PublishedSearchResult(IPublishedContent content, float score) { Content = content; Score = score; } + /// + /// Gets the published content item. + /// public IPublishedContent Content { get; } + /// + /// Gets the relevance score of the search result. + /// public float Score { get; } } diff --git a/src/Umbraco.Core/Models/PublishedContent/RawValueProperty.cs b/src/Umbraco.Core/Models/PublishedContent/RawValueProperty.cs index 926bc05420d4..85def8f5fd92 100644 --- a/src/Umbraco.Core/Models/PublishedContent/RawValueProperty.cs +++ b/src/Umbraco.Core/Models/PublishedContent/RawValueProperty.cs @@ -23,6 +23,14 @@ public class RawValueProperty : PublishedPropertyBase private readonly object _sourceValue; // the value in the db private readonly Lazy _deliveryApiValue; + /// + /// Initializes a new instance of the class. + /// + /// The property type. + /// The published element that owns this property. + /// The source value from the database. + /// A value indicating whether the content is being previewed. + /// Thrown when the property type supports variations. public RawValueProperty(IPublishedPropertyType propertyType, IPublishedElement content, object sourceValue, bool isPreviewing = false) : base(propertyType, PropertyCacheLevel.Unknown) // cache level is ignored { @@ -43,18 +51,23 @@ public RawValueProperty(IPublishedPropertyType propertyType, IPublishedElement c // RawValueProperty does not (yet?) support variants, // only manages the current "default" value + + /// public override object? GetSourceValue(string? culture = null, string? segment = null) => string.IsNullOrEmpty(culture) & string.IsNullOrEmpty(segment) ? _sourceValue : null; + /// public override bool HasValue(string? culture = null, string? segment = null) { var sourceValue = GetSourceValue(culture, segment); return sourceValue is string s ? !string.IsNullOrWhiteSpace(s) : sourceValue != null; } + /// public override object? GetValue(string? culture = null, string? segment = null) => string.IsNullOrEmpty(culture) & string.IsNullOrEmpty(segment) ? _objectValue.Value : null; + /// public override object? GetDeliveryApiValue(bool expanding, string? culture = null, string? segment = null) => string.IsNullOrEmpty(culture) & string.IsNullOrEmpty(segment) ? _deliveryApiValue.Value : null; } diff --git a/src/Umbraco.Core/Models/PublishedContent/ThreadCultureVariationContextAccessor.cs b/src/Umbraco.Core/Models/PublishedContent/ThreadCultureVariationContextAccessor.cs index 591937079262..6a8af3f41dd8 100644 --- a/src/Umbraco.Core/Models/PublishedContent/ThreadCultureVariationContextAccessor.cs +++ b/src/Umbraco.Core/Models/PublishedContent/ThreadCultureVariationContextAccessor.cs @@ -12,6 +12,7 @@ public class ThreadCultureVariationContextAccessor : IVariationContextAccessor { private readonly ConcurrentDictionary _contexts = new(); + /// public VariationContext? VariationContext { get => _contexts.GetOrAdd(Thread.CurrentThread.CurrentUICulture.Name, culture => new VariationContext(culture)); diff --git a/src/Umbraco.Core/Models/PublishedContent/VariationContextAccessorExtensions.cs b/src/Umbraco.Core/Models/PublishedContent/VariationContextAccessorExtensions.cs index 566d5e45af08..4a5182486067 100644 --- a/src/Umbraco.Core/Models/PublishedContent/VariationContextAccessorExtensions.cs +++ b/src/Umbraco.Core/Models/PublishedContent/VariationContextAccessorExtensions.cs @@ -6,8 +6,18 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class VariationContextAccessorExtensions { + /// + /// Contextualizes the variation based on the content variation settings. + /// + /// The variation context accessor. + /// The content variation settings. + /// The culture, which may be set based on the variation context. + /// The segment, which may be set based on the variation context. [Obsolete("Please use the method overload that accepts all parameters. Scheduled for removal in Umbraco 18.")] public static void ContextualizeVariation( this IVariationContextAccessor variationContextAccessor, @@ -16,6 +26,14 @@ public static void ContextualizeVariation( ref string? segment) => variationContextAccessor.ContextualizeVariation(variations, null, null, ref culture, ref segment); + /// + /// Contextualizes the variation based on the content variation settings and property alias. + /// + /// The variation context accessor. + /// The content variation settings. + /// The property alias. + /// The culture, which may be set based on the variation context. + /// The segment, which may be set based on the variation context. public static void ContextualizeVariation( this IVariationContextAccessor variationContextAccessor, ContentVariation variations, @@ -24,6 +42,14 @@ public static void ContextualizeVariation( ref string? segment) => variationContextAccessor.ContextualizeVariation(variations, null, propertyAlias, ref culture, ref segment); + /// + /// Contextualizes the variation based on the content variation settings and content ID. + /// + /// The variation context accessor. + /// The content variation settings. + /// The content ID. + /// The culture, which may be set based on the variation context. + /// The segment, which may be set based on the variation context. [Obsolete("Please use the method overload that accepts all parameters. Scheduled for removal in Umbraco 18.")] public static void ContextualizeVariation( this IVariationContextAccessor variationContextAccessor, @@ -33,6 +59,15 @@ public static void ContextualizeVariation( ref string? segment) => variationContextAccessor.ContextualizeVariation(variations, (int?)contentId, null, ref culture, ref segment); + /// + /// Contextualizes the variation based on the content variation settings, content ID, and property alias. + /// + /// The variation context accessor. + /// The content variation settings. + /// The content ID. + /// The property alias. + /// The culture, which may be set based on the variation context. + /// The segment, which may be set based on the variation context. public static void ContextualizeVariation( this IVariationContextAccessor variationContextAccessor, ContentVariation variations, diff --git a/src/Umbraco.Core/Models/ReadOnlyContentBaseAdapter.cs b/src/Umbraco.Core/Models/ReadOnlyContentBaseAdapter.cs index b0018dc17945..989d8ad1f25c 100644 --- a/src/Umbraco.Core/Models/ReadOnlyContentBaseAdapter.cs +++ b/src/Umbraco.Core/Models/ReadOnlyContentBaseAdapter.cs @@ -1,5 +1,12 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Provides a read-only adapter for instances. +/// +/// +/// This struct wraps an instance and exposes its properties +/// through the interface without allowing modifications. +/// public struct ReadOnlyContentBaseAdapter : IReadOnlyContentBase { private readonly IContentBase _content; @@ -7,31 +14,49 @@ public struct ReadOnlyContentBaseAdapter : IReadOnlyContentBase private ReadOnlyContentBaseAdapter(IContentBase content) => _content = content ?? throw new ArgumentNullException(nameof(content)); + /// public int Id => _content.Id; + /// + /// Creates a new instance from an . + /// + /// The content base to wrap. + /// A read-only adapter for the specified content. public static ReadOnlyContentBaseAdapter Create(IContentBase content) => new(content); + /// public Guid Key => _content.Key; + /// public DateTime CreateDate => _content.CreateDate; + /// public DateTime UpdateDate => _content.UpdateDate; + /// public string? Name => _content.Name; + /// public int CreatorId => _content.CreatorId; + /// public int ParentId => _content.ParentId; + /// public int Level => _content.Level; + /// public string Path => _content.Path; + /// public int SortOrder => _content.SortOrder; + /// public int ContentTypeId => _content.ContentTypeId; + /// public int WriterId => _content.WriterId; + /// public int VersionId => _content.VersionId; } diff --git a/src/Umbraco.Core/Models/ReadOnlyRelation.cs b/src/Umbraco.Core/Models/ReadOnlyRelation.cs index 8729dd50f5b3..e23caf0999ae 100644 --- a/src/Umbraco.Core/Models/ReadOnlyRelation.cs +++ b/src/Umbraco.Core/Models/ReadOnlyRelation.cs @@ -6,6 +6,15 @@ namespace Umbraco.Cms.Core.Models; /// public class ReadOnlyRelation { + /// + /// Initializes a new instance of the class with all properties. + /// + /// The identifier of the relation. + /// The identifier of the parent entity. + /// The identifier of the child entity. + /// The identifier of the relation type. + /// The date and time when the relation was created. + /// An optional comment about the relation. public ReadOnlyRelation(int id, int parentId, int childId, int relationTypeId, DateTime createDate, string comment) { Id = id; @@ -16,22 +25,49 @@ public ReadOnlyRelation(int id, int parentId, int childId, int relationTypeId, D Comment = comment; } + /// + /// Initializes a new instance of the class for a new relation. + /// + /// The identifier of the parent entity. + /// The identifier of the child entity. + /// The identifier of the relation type. public ReadOnlyRelation(int parentId, int childId, int relationTypeId) : this(0, parentId, childId, relationTypeId, DateTime.UtcNow, string.Empty) { } + /// + /// Gets the identifier of the relation. + /// public int Id { get; } + /// + /// Gets the identifier of the parent entity. + /// public int ParentId { get; } + /// + /// Gets the identifier of the child entity. + /// public int ChildId { get; } + /// + /// Gets the identifier of the relation type. + /// public int RelationTypeId { get; } + /// + /// Gets the date and time when the relation was created. + /// public DateTime CreateDate { get; } + /// + /// Gets the comment associated with the relation. + /// public string Comment { get; } + /// + /// Gets a value indicating whether this relation has been persisted and has an identity. + /// public bool HasIdentity => Id != 0; } diff --git a/src/Umbraco.Core/Models/RedirectUrlManagement/RedirectStatus.cs b/src/Umbraco.Core/Models/RedirectUrlManagement/RedirectStatus.cs index e58634b7b210..07949ab104fa 100644 --- a/src/Umbraco.Core/Models/RedirectUrlManagement/RedirectStatus.cs +++ b/src/Umbraco.Core/Models/RedirectUrlManagement/RedirectStatus.cs @@ -1,7 +1,17 @@ -namespace Umbraco.Cms.Core.Models.RedirectUrlManagement; +namespace Umbraco.Cms.Core.Models.RedirectUrlManagement; +/// +/// Represents the status of redirect URL tracking. +/// public enum RedirectStatus { + /// + /// Redirect URL tracking is enabled. + /// Enabled, + + /// + /// Redirect URL tracking is disabled. + /// Disabled, } diff --git a/src/Umbraco.Core/Models/Relation.cs b/src/Umbraco.Core/Models/Relation.cs index c495ed39fb4c..d0d8a2370f8e 100644 --- a/src/Umbraco.Core/Models/Relation.cs +++ b/src/Umbraco.Core/Models/Relation.cs @@ -58,6 +58,7 @@ public int ParentId set => SetPropertyValueAndDetectChanges(value, ref _parentId, nameof(ParentId)); } + /// [DataMember] public Guid ParentObjectType { get; set; } @@ -71,6 +72,7 @@ public int ChildId set => SetPropertyValueAndDetectChanges(value, ref _childId, nameof(ChildId)); } + /// [DataMember] public Guid ChildObjectType { get; set; } diff --git a/src/Umbraco.Core/Models/RelationDirectionFilter.cs b/src/Umbraco.Core/Models/RelationDirectionFilter.cs index 1a71f8e07002..e9ac75f81871 100644 --- a/src/Umbraco.Core/Models/RelationDirectionFilter.cs +++ b/src/Umbraco.Core/Models/RelationDirectionFilter.cs @@ -6,7 +6,18 @@ namespace Umbraco.Cms.Core.Models; [Flags] public enum RelationDirectionFilter { + /// + /// Filter to include relations where the item is the parent. + /// Parent = 1, + + /// + /// Filter to include relations where the item is the child. + /// Child = 2, + + /// + /// Filter to include relations where the item is either the parent or the child. + /// Any = Parent | Child } diff --git a/src/Umbraco.Core/Models/RelationItem.cs b/src/Umbraco.Core/Models/RelationItem.cs index 41fde0e867be..6cb259476136 100644 --- a/src/Umbraco.Core/Models/RelationItem.cs +++ b/src/Umbraco.Core/Models/RelationItem.cs @@ -2,45 +2,90 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents an item in a relation, containing node and content type information. +/// [DataContract(Name = "relationItem", Namespace = "")] public class RelationItem { + /// + /// Gets or sets the unique identifier of the node. + /// [DataMember(Name = "id")] public int NodeId { get; set; } + /// + /// Gets or sets the unique key (GUID) of the node. + /// [DataMember(Name = "key")] public Guid NodeKey { get; set; } + /// + /// Gets or sets the name of the node. + /// [DataMember(Name = "name")] public string? NodeName { get; set; } + /// + /// Gets or sets the type of the node (e.g., document, media). + /// [DataMember(Name = "type")] public string? NodeType { get; set; } + /// + /// Gets the UDI (Umbraco Document Identifier) for the node. + /// + /// + /// Returns null if the node type is unknown. + /// [DataMember(Name = "udi")] public Udi? NodeUdi => NodeType == Constants.UdiEntityType.Unknown ? null : Udi.Create(NodeType, NodeKey); + /// + /// Gets or sets a value indicating whether the node is published. + /// [DataMember(Name = "published")] public bool? NodePublished { get; set; } + /// + /// Gets or sets the unique key of the content type. + /// [DataMember(Name = "contentTypeKey")] public Guid ContentTypeKey { get; set; } + /// + /// Gets or sets the icon associated with the content type. + /// [DataMember(Name = "icon")] public string? ContentTypeIcon { get; set; } + /// + /// Gets or sets the alias of the content type. + /// [DataMember(Name = "alias")] public string? ContentTypeAlias { get; set; } + /// + /// Gets or sets the name of the content type. + /// [DataMember(Name = "contentTypeName")] public string? ContentTypeName { get; set; } + /// + /// Gets or sets the name of the relation type. + /// [DataMember(Name = "relationTypeName")] public string? RelationTypeName { get; set; } + /// + /// Gets or sets a value indicating whether the relation type is bidirectional. + /// [DataMember(Name = "relationTypeIsBidirectional")] public bool RelationTypeIsBidirectional { get; set; } + /// + /// Gets or sets a value indicating whether the relation type represents a dependency. + /// [DataMember(Name = "relationTypeIsDependency")] public bool RelationTypeIsDependency { get; set; } } diff --git a/src/Umbraco.Core/Models/RelationItemModel.cs b/src/Umbraco.Core/Models/RelationItemModel.cs index 1ca3bb9e111e..e01ffbd28bcb 100644 --- a/src/Umbraco.Core/Models/RelationItemModel.cs +++ b/src/Umbraco.Core/Models/RelationItemModel.cs @@ -1,28 +1,67 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a model for a relation item, containing node and content type information. +/// public class RelationItemModel { + /// + /// Gets or sets the unique key (GUID) of the node. + /// public Guid NodeKey { get; set; } + /// + /// Gets or sets the alias of the node. + /// public string? NodeAlias { get; set; } + /// + /// Gets or sets the name of the node. + /// public string? NodeName { get; set; } + /// + /// Gets or sets the type of the node (e.g., document, media). + /// public string? NodeType { get; set; } + /// + /// Gets or sets a value indicating whether the node is published. + /// public bool? NodePublished { get; set; } + /// + /// Gets or sets the unique key of the content type. + /// public Guid ContentTypeKey { get; set; } + /// + /// Gets or sets the icon associated with the content type. + /// public string? ContentTypeIcon { get; set; } + /// + /// Gets or sets the alias of the content type. + /// public string? ContentTypeAlias { get; set; } + /// + /// Gets or sets the name of the content type. + /// public string? ContentTypeName { get; set; } + /// + /// Gets or sets the name of the relation type. + /// public string? RelationTypeName { get; set; } + /// + /// Gets or sets a value indicating whether the relation type is bidirectional. + /// public bool RelationTypeIsBidirectional { get; set; } + /// + /// Gets or sets a value indicating whether the relation type represents a dependency. + /// public bool RelationTypeIsDependency { get; set; } } diff --git a/src/Umbraco.Core/Models/RelationType.cs b/src/Umbraco.Core/Models/RelationType.cs index 79b5a364b277..fcf18e45014e 100644 --- a/src/Umbraco.Core/Models/RelationType.cs +++ b/src/Umbraco.Core/Models/RelationType.cs @@ -1,4 +1,4 @@ -using System.Runtime.Serialization; +using System.Runtime.Serialization; using Umbraco.Cms.Core.Models.Entities; namespace Umbraco.Cms.Core.Models; @@ -17,11 +17,28 @@ public class RelationType : EntityBase, IRelationTypeWithIsDependency private string _name; private Guid? _parentObjectType; + /// + /// Initializes a new instance of the class with alias and name. + /// + /// The alias of the relation type. + /// The name of the relation type. public RelationType(string alias, string name) : this(name, alias, false, null, null, false) { } + /// + /// Initializes a new instance of the class with full configuration. + /// + /// The name of the relation type. + /// The alias of the relation type. + /// A value indicating whether the relation is bidirectional. + /// The object type GUID of the parent. + /// The object type GUID of the child. + /// A value indicating whether this relation represents a dependency. + /// The optional unique key for the relation type. + /// Thrown when or is null. + /// Thrown when or is empty or whitespace. public RelationType(string? name, string? alias, bool isBidrectional, Guid? parentObjectType, Guid? childObjectType, bool isDependency, Guid? key = null) { if (name == null) @@ -113,6 +130,12 @@ public Guid? ChildObjectType set => SetPropertyValueAndDetectChanges(value, ref _childObjectType, nameof(ChildObjectType)); } + /// + /// Gets or sets a value indicating whether the relation represents a dependency. + /// + /// + /// When true, the child entity depends on the parent entity. + /// public bool IsDependency { get => _isDependency; diff --git a/src/Umbraco.Core/Models/RelationTypeExtensions.cs b/src/Umbraco.Core/Models/RelationTypeExtensions.cs index 81d680133004..002f73b22f9f 100644 --- a/src/Umbraco.Core/Models/RelationTypeExtensions.cs +++ b/src/Umbraco.Core/Models/RelationTypeExtensions.cs @@ -6,8 +6,16 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class RelationTypeExtensions { + /// + /// Determines whether the relation type is a built-in system relation type. + /// + /// The relation type to check. + /// true if the relation type is a system relation type; otherwise, false. public static bool IsSystemRelationType(this IRelationType relationType) => relationType.Alias == Constants.Conventions.RelationTypes.RelatedDocumentAlias || relationType.Alias == Constants.Conventions.RelationTypes.RelatedMediaAlias @@ -16,6 +24,14 @@ public static bool IsSystemRelationType(this IRelationType relationType) => || relationType.Alias == Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias || relationType.Alias == Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias; + /// + /// Determines whether the relation type can be deleted. + /// + /// The relation type to check. + /// true if the relation type can be deleted; otherwise, false. + /// + /// System relation types cannot be deleted. + /// public static bool IsDeletableRelationType(this IRelationType relationType) => relationType.IsSystemRelationType() is false; } diff --git a/src/Umbraco.Core/Models/RequestPasswordResetModel.cs b/src/Umbraco.Core/Models/RequestPasswordResetModel.cs index 9b4932f88a36..261b54a42ee1 100644 --- a/src/Umbraco.Core/Models/RequestPasswordResetModel.cs +++ b/src/Umbraco.Core/Models/RequestPasswordResetModel.cs @@ -3,9 +3,15 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a model for requesting a password reset. +/// [DataContract(Name = "requestPasswordReset", Namespace = "")] public class RequestPasswordResetModel { + /// + /// Gets or sets the email address of the user requesting the password reset. + /// [Required] [DataMember(Name = "email", IsRequired = true)] public string Email { get; set; } = null!; diff --git a/src/Umbraco.Core/Models/ResolvedUserToUserGroupManipulationModel.cs b/src/Umbraco.Core/Models/ResolvedUserToUserGroupManipulationModel.cs index 33eda14f0e4c..5e24a13a146d 100644 --- a/src/Umbraco.Core/Models/ResolvedUserToUserGroupManipulationModel.cs +++ b/src/Umbraco.Core/Models/ResolvedUserToUserGroupManipulationModel.cs @@ -1,10 +1,19 @@ -using Umbraco.Cms.Core.Models.Membership; +using Umbraco.Cms.Core.Models.Membership; namespace Umbraco.Cms.Core.Models; +/// +/// Represents a resolved model for manipulating user-to-user-group assignments. +/// public class ResolvedUserToUserGroupManipulationModel { + /// + /// Gets the array of users involved in the manipulation operation. + /// public required IUser[] Users { get; init; } + /// + /// Gets the user group that the users are being added to or removed from. + /// public required IUserGroup UserGroup { get; init; } } diff --git a/src/Umbraco.Core/Models/Script.cs b/src/Umbraco.Core/Models/Script.cs index 03888bd27a42..1aaf7762ed3a 100644 --- a/src/Umbraco.Core/Models/Script.cs +++ b/src/Umbraco.Core/Models/Script.cs @@ -9,11 +9,20 @@ namespace Umbraco.Cms.Core.Models; [DataContract(IsReference = true)] public class Script : File, IScript { + /// + /// Initializes a new instance of the class with a file path. + /// + /// The path to the script file. public Script(string path) : this(path, null) { } + /// + /// Initializes a new instance of the class with a file path and content provider. + /// + /// The path to the script file. + /// A function to retrieve the file content lazily. public Script(string path, Func? getFileContent) : base(path, getFileContent) { diff --git a/src/Umbraco.Core/Models/ScriptCreateModel.cs b/src/Umbraco.Core/Models/ScriptCreateModel.cs index 7e7f2a7c3b2d..dbedf6cfa71d 100644 --- a/src/Umbraco.Core/Models/ScriptCreateModel.cs +++ b/src/Umbraco.Core/Models/ScriptCreateModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents a model for creating a new script file. +/// public class ScriptCreateModel : TextFileCreateModel { } diff --git a/src/Umbraco.Core/Models/ScriptRenameModel.cs b/src/Umbraco.Core/Models/ScriptRenameModel.cs index 896b3c8eecb9..1145cc087625 100644 --- a/src/Umbraco.Core/Models/ScriptRenameModel.cs +++ b/src/Umbraco.Core/Models/ScriptRenameModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents a model for renaming a script file. +/// public class ScriptRenameModel : TextFileRenameModel { } diff --git a/src/Umbraco.Core/Models/ScriptUpdateModel.cs b/src/Umbraco.Core/Models/ScriptUpdateModel.cs index 44dc8cdcb8ef..eed68294d920 100644 --- a/src/Umbraco.Core/Models/ScriptUpdateModel.cs +++ b/src/Umbraco.Core/Models/ScriptUpdateModel.cs @@ -1,6 +1,8 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents a model for updating an existing script file. +/// public class ScriptUpdateModel : TextFileUpdateModel { - } diff --git a/src/Umbraco.Core/Models/Segment.cs b/src/Umbraco.Core/Models/Segment.cs index 2bb02d90f2fe..99abc6aa14e4 100644 --- a/src/Umbraco.Core/Models/Segment.cs +++ b/src/Umbraco.Core/Models/Segment.cs @@ -1,11 +1,23 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a content segment used for personalization or A/B testing. +/// public class Segment { + /// + /// Gets or sets the display name of the segment. + /// public required string Name { get; set; } + /// + /// Gets or sets the alias (identifier) of the segment. + /// public required string Alias { get; set; } + /// + /// Gets or sets the cultures associated with this segment. + /// [Obsolete("This property is temporary and will be removed in a future release (planned for v20). A more permanent solution will follow.")] public IEnumerable? Cultures { get; set; } = null; } diff --git a/src/Umbraco.Core/Models/ServerEvents/ServerEvent.cs b/src/Umbraco.Core/Models/ServerEvents/ServerEvent.cs index 299fd66392c5..64ab868b5561 100644 --- a/src/Umbraco.Core/Models/ServerEvents/ServerEvent.cs +++ b/src/Umbraco.Core/Models/ServerEvents/ServerEvent.cs @@ -1,10 +1,22 @@ -namespace Umbraco.Cms.Core.Models.ServerEvents; +namespace Umbraco.Cms.Core.Models.ServerEvents; +/// +/// Represents a server-sent event that can be pushed to connected clients. +/// public class ServerEvent { + /// + /// Gets or sets the type of the event. + /// public required string EventType { get; set; } + /// + /// Gets or sets the source of the event. + /// public required string EventSource { get; set; } + /// + /// Gets or sets the unique key associated with the event. + /// public Guid Key { get; set; } } diff --git a/src/Umbraco.Core/Models/ServerEvents/SeverEventAuthorizationResult.cs b/src/Umbraco.Core/Models/ServerEvents/SeverEventAuthorizationResult.cs index 71fdd78b7e4b..d336f402fd9b 100644 --- a/src/Umbraco.Core/Models/ServerEvents/SeverEventAuthorizationResult.cs +++ b/src/Umbraco.Core/Models/ServerEvents/SeverEventAuthorizationResult.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.ServerEvents; +namespace Umbraco.Cms.Core.Models.ServerEvents; +/// +/// Represents the result of server event authorization, indicating which event sources the user can and cannot access. +/// public class SeverEventAuthorizationResult { /// diff --git a/src/Umbraco.Core/Models/ServerInformation.cs b/src/Umbraco.Core/Models/ServerInformation.cs index c916164f0dde..d3e8d6c19d10 100644 --- a/src/Umbraco.Core/Models/ServerInformation.cs +++ b/src/Umbraco.Core/Models/ServerInformation.cs @@ -3,9 +3,26 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents information about the Umbraco server instance. +/// +/// The semantic version of the Umbraco installation. +/// The time zone information for the server. +/// The current runtime mode of the server. public class ServerInformation(SemVersion semVersion, TimeZoneInfo timeZoneInfo, RuntimeMode runtimeMode) { + /// + /// Gets the semantic version of the Umbraco installation. + /// public SemVersion SemVersion { get; } = semVersion; + + /// + /// Gets the time zone information for the server. + /// public TimeZoneInfo TimeZoneInfo { get; } = timeZoneInfo; + + /// + /// Gets the current runtime mode of the server. + /// public RuntimeMode RuntimeMode { get; } = runtimeMode; } diff --git a/src/Umbraco.Core/Models/SimpleContentType.cs b/src/Umbraco.Core/Models/SimpleContentType.cs index ea57be08627c..55cbe2e68977 100644 --- a/src/Umbraco.Core/Models/SimpleContentType.cs +++ b/src/Umbraco.Core/Models/SimpleContentType.cs @@ -48,27 +48,37 @@ private SimpleContentType(IContentTypeBase contentType) IsElement = contentType.IsElement; } + /// public string Alias { get; } + /// public int Id { get; } + /// public Guid Key { get; } /// public ITemplate? DefaultTemplate { get; } + /// public ContentVariation Variations { get; } + /// public string? Icon { get; } + /// public Guid? ListView { get; } + /// public string? Name { get; } + /// public bool AllowedAsRoot { get; } + /// public bool IsElement { get; } + /// public bool SupportsPropertyVariation(string? culture, string segment, bool wildcards = false) => // non-exact validation: can accept a 'null' culture if the property type varies @@ -76,6 +86,7 @@ public bool SupportsPropertyVariation(string? culture, string segment, bool wild // wildcard validation: can accept a '*' culture or segment Variations.ValidateVariation(culture, segment, false, wildcards, false); + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -96,8 +107,14 @@ public override bool Equals(object? obj) return Equals((SimpleContentType)obj); } + /// + /// Determines whether the specified is equal to this instance. + /// + /// The other instance to compare. + /// true if both instances have the same alias and ID; otherwise, false. protected bool Equals(SimpleContentType other) => string.Equals(Alias, other.Alias) && Id == other.Id; + /// public override int GetHashCode() { unchecked diff --git a/src/Umbraco.Core/Models/SimpleValidationModel.cs b/src/Umbraco.Core/Models/SimpleValidationModel.cs index 390fe5a31cfa..b860d30a5fb0 100644 --- a/src/Umbraco.Core/Models/SimpleValidationModel.cs +++ b/src/Umbraco.Core/Models/SimpleValidationModel.cs @@ -1,14 +1,28 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a simple validation result model containing validation errors. +/// public class SimpleValidationModel { + /// + /// Initializes a new instance of the class. + /// + /// A dictionary containing the validation errors keyed by property name. + /// The overall validation message. Defaults to "The request is invalid." public SimpleValidationModel(IDictionary modelState, string message = "The request is invalid.") { Message = message; ModelState = modelState; } + /// + /// Gets the overall validation message. + /// public string Message { get; } + /// + /// Gets the dictionary containing validation errors keyed by property name. + /// public IDictionary ModelState { get; } } diff --git a/src/Umbraco.Core/Models/Stylesheet.cs b/src/Umbraco.Core/Models/Stylesheet.cs index 07f35c88e317..d2fd8e2731b3 100644 --- a/src/Umbraco.Core/Models/Stylesheet.cs +++ b/src/Umbraco.Core/Models/Stylesheet.cs @@ -15,11 +15,20 @@ public class Stylesheet : File, IStylesheet { private Lazy>? _properties; + /// + /// Initializes a new instance of the class with a file path. + /// + /// The path to the stylesheet file. public Stylesheet(string path) : this(path, null) { } + /// + /// Initializes a new instance of the class with a file path and content provider. + /// + /// The path to the stylesheet file. + /// A function to retrieve the file content lazily. public Stylesheet(string path, Func? getFileContent) : base(string.IsNullOrEmpty(path) ? path : path.EnsureEndsWith(".css"), getFileContent) => InitializeProperties(); @@ -90,6 +99,9 @@ public void RemoveProperty(string name) } } + /// + /// Initializes or reinitializes the collection of stylesheet properties from the content. + /// private void InitializeProperties() { // if the value is already created, we need to be created and update the collection according to diff --git a/src/Umbraco.Core/Models/StylesheetCreateModel.cs b/src/Umbraco.Core/Models/StylesheetCreateModel.cs index daac696958da..2a1df672a9ce 100644 --- a/src/Umbraco.Core/Models/StylesheetCreateModel.cs +++ b/src/Umbraco.Core/Models/StylesheetCreateModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents a model for creating a new stylesheet file. +/// public class StylesheetCreateModel : TextFileCreateModel { } diff --git a/src/Umbraco.Core/Models/StylesheetProperty.cs b/src/Umbraco.Core/Models/StylesheetProperty.cs index 730ff8ff3e20..a390a64b303b 100644 --- a/src/Umbraco.Core/Models/StylesheetProperty.cs +++ b/src/Umbraco.Core/Models/StylesheetProperty.cs @@ -16,6 +16,12 @@ public class StylesheetProperty : BeingDirtyBase, IValueObject, IStylesheetPrope private string _alias; private string _value; + /// + /// Initializes a new instance of the class. + /// + /// The name of the CSS rule for use in the back office. + /// The CSS selector. + /// The CSS value for the selector. public StylesheetProperty(string name, string alias, string value) { Name = name; diff --git a/src/Umbraco.Core/Models/StylesheetRenameModel.cs b/src/Umbraco.Core/Models/StylesheetRenameModel.cs index 9dde53046c7b..de6f81630285 100644 --- a/src/Umbraco.Core/Models/StylesheetRenameModel.cs +++ b/src/Umbraco.Core/Models/StylesheetRenameModel.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a model for renaming a stylesheet file. +/// public class StylesheetRenameModel : TextFileRenameModel { } diff --git a/src/Umbraco.Core/Models/StylesheetUpdateModel.cs b/src/Umbraco.Core/Models/StylesheetUpdateModel.cs index 84aead8f0fec..391f53dd8c8e 100644 --- a/src/Umbraco.Core/Models/StylesheetUpdateModel.cs +++ b/src/Umbraco.Core/Models/StylesheetUpdateModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents a model for updating an existing stylesheet file. +/// public class StylesheetUpdateModel : TextFileUpdateModel { } diff --git a/src/Umbraco.Core/Models/TagModel.cs b/src/Umbraco.Core/Models/TagModel.cs index 2646b216e388..ec95b5f7b8de 100644 --- a/src/Umbraco.Core/Models/TagModel.cs +++ b/src/Umbraco.Core/Models/TagModel.cs @@ -2,18 +2,33 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a tag data transfer model for API serialization. +/// [DataContract(Name = "tag", Namespace = "")] public class TagModel { + /// + /// Gets or sets the unique identifier of the tag. + /// [DataMember(Name = "id", IsRequired = true)] public int Id { get; set; } + /// + /// Gets or sets the text content of the tag. + /// [DataMember(Name = "text", IsRequired = true)] public string? Text { get; set; } + /// + /// Gets or sets the group that the tag belongs to. + /// [DataMember(Name = "group")] public string? Group { get; set; } + /// + /// Gets or sets the count of nodes that have this tag assigned. + /// [DataMember(Name = "nodeCount")] public int NodeCount { get; set; } } diff --git a/src/Umbraco.Core/Models/TaggableObjectTypes.cs b/src/Umbraco.Core/Models/TaggableObjectTypes.cs index 03be2273a2f4..afd22a65ba44 100644 --- a/src/Umbraco.Core/Models/TaggableObjectTypes.cs +++ b/src/Umbraco.Core/Models/TaggableObjectTypes.cs @@ -5,8 +5,23 @@ namespace Umbraco.Cms.Core.Models; /// public enum TaggableObjectTypes { + /// + /// Includes all taggable object types. + /// All, + + /// + /// Represents content entities (documents/pages). + /// Content, + + /// + /// Represents media entities (images, files, etc.). + /// Media, + + /// + /// Represents member entities (user accounts). + /// Member, } diff --git a/src/Umbraco.Core/Models/TelemetryLevel.cs b/src/Umbraco.Core/Models/TelemetryLevel.cs index cdf1d24e90d1..1d1302ea4713 100644 --- a/src/Umbraco.Core/Models/TelemetryLevel.cs +++ b/src/Umbraco.Core/Models/TelemetryLevel.cs @@ -2,10 +2,24 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Defines the level of telemetry data to be collected and sent. +/// [DataContract] public enum TelemetryLevel { + /// + /// Minimal telemetry - only essential anonymous usage data. + /// Minimal, + + /// + /// Basic telemetry - includes minimal data plus general feature usage statistics. + /// Basic, + + /// + /// Detailed telemetry - includes basic data plus detailed usage patterns and diagnostics. + /// Detailed, } diff --git a/src/Umbraco.Core/Models/TelemetryResource.cs b/src/Umbraco.Core/Models/TelemetryResource.cs index 1c6284238190..dcc053e1577b 100644 --- a/src/Umbraco.Core/Models/TelemetryResource.cs +++ b/src/Umbraco.Core/Models/TelemetryResource.cs @@ -2,9 +2,15 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a telemetry configuration resource. +/// [DataContract] public class TelemetryResource { + /// + /// Gets or sets the telemetry level for the Umbraco installation. + /// [DataMember] public TelemetryLevel TelemetryLevel { get; set; } } diff --git a/src/Umbraco.Core/Models/Template.cs b/src/Umbraco.Core/Models/Template.cs index cc92e8091ca7..f429f4fc6617 100644 --- a/src/Umbraco.Core/Models/Template.cs +++ b/src/Umbraco.Core/Models/Template.cs @@ -17,11 +17,24 @@ public class Template : File, ITemplate private Lazy? _masterTemplateId; private string? _name; + /// + /// Initializes a new instance of the class. + /// + /// The short string helper for alias cleaning. + /// The name of the template. + /// The alias of the template. public Template(IShortStringHelper shortStringHelper, string? name, string? alias) : this(shortStringHelper, name, alias, null) { } + /// + /// Initializes a new instance of the class. + /// + /// The short string helper for alias cleaning. + /// The name of the template. + /// The alias of the template. + /// A function to retrieve the file content lazily. public Template(IShortStringHelper shortStringHelper, string? name, string? alias, Func? getFileContent) : base(string.Empty, getFileContent) { @@ -31,6 +44,12 @@ public Template(IShortStringHelper shortStringHelper, string? name, string? alia _masterTemplateId = new Lazy(() => -1); } + /// + /// Gets or sets the master template identifier as a lazy-loaded value. + /// + /// + /// A containing the master template's ID, or -1 if there is no master template. + /// [DataMember] public Lazy? MasterTemplateId { @@ -38,12 +57,21 @@ public Lazy? MasterTemplateId set => SetPropertyValueAndDetectChanges(value, ref _masterTemplateId, nameof(MasterTemplateId)); } + /// + /// Gets or sets the alias of the master (parent) template. + /// + /// + /// The alias of the master template, or null if this template has no master. + /// public string? MasterTemplateAlias { get => _masterTemplateAlias; set => SetPropertyValueAndDetectChanges(value, ref _masterTemplateAlias, nameof(MasterTemplateAlias)); } + /// + /// Gets or sets the name of the template. + /// [DataMember] public new string? Name { @@ -51,6 +79,12 @@ public string? MasterTemplateAlias set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name)); } + /// + /// Gets or sets the alias of the template. + /// + /// + /// The alias is automatically cleaned using the underscore alias format. + /// [DataMember] public new string Alias { @@ -65,6 +99,10 @@ public string? MasterTemplateAlias public bool IsMasterTemplate { get; set; } // FIXME: moving forward the master template is calculated from the actual template content; figure out how to get rid of this method, or at least *only* use it from TemplateService + /// + /// Sets the master template for this template. + /// + /// The master template to set, or null to remove the master template. [Obsolete("MasterTemplate is now calculated from the content. This will be removed in Umbraco 15.")] public void SetMasterTemplate(ITemplate? masterTemplate) { @@ -80,6 +118,10 @@ public void SetMasterTemplate(ITemplate? masterTemplate) } } + /// + /// Overrides the base implementation to prevent File from cloning name and alias. + /// + /// The cloned file instance. protected override void DeepCloneNameAndAlias(File clone) { // do nothing - prevents File from doing its stuff diff --git a/src/Umbraco.Core/Models/TemplateQuery/ContentTypeModel.cs b/src/Umbraco.Core/Models/TemplateQuery/ContentTypeModel.cs index c94cd67b8a4e..5b20d2fc1b4b 100644 --- a/src/Umbraco.Core/Models/TemplateQuery/ContentTypeModel.cs +++ b/src/Umbraco.Core/Models/TemplateQuery/ContentTypeModel.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.Models.TemplateQuery; +/// +/// Represents a content type model for use in template queries. +/// public class ContentTypeModel { + /// + /// Gets or sets the alias of the content type. + /// public string? Alias { get; set; } + /// + /// Gets or sets the display name of the content type. + /// public string? Name { get; set; } } diff --git a/src/Umbraco.Core/Models/TemplateQuery/Operator.cs b/src/Umbraco.Core/Models/TemplateQuery/Operator.cs index c76202fb68a7..8b6e8ac26baa 100644 --- a/src/Umbraco.Core/Models/TemplateQuery/Operator.cs +++ b/src/Umbraco.Core/Models/TemplateQuery/Operator.cs @@ -1,13 +1,47 @@ namespace Umbraco.Cms.Core.Models.TemplateQuery; +/// +/// Represents the comparison operators available for template query conditions. +/// public enum Operator { + /// + /// Checks if the value equals the constraint. + /// Equals = 1, + + /// + /// Checks if the value does not equal the constraint. + /// NotEquals = 2, + + /// + /// Checks if the string value contains the constraint. + /// Contains = 3, + + /// + /// Checks if the string value does not contain the constraint. + /// NotContains = 4, + + /// + /// Checks if the value is less than the constraint. + /// LessThan = 5, + + /// + /// Checks if the value is less than or equal to the constraint. + /// LessThanEqualTo = 6, + + /// + /// Checks if the value is greater than the constraint. + /// GreaterThan = 7, + + /// + /// Checks if the value is greater than or equal to the constraint. + /// GreaterThanEqualTo = 8, } diff --git a/src/Umbraco.Core/Models/TemplateQuery/OperatorFactory.cs b/src/Umbraco.Core/Models/TemplateQuery/OperatorFactory.cs index fc23ebdb3d5c..831203fb5b1b 100644 --- a/src/Umbraco.Core/Models/TemplateQuery/OperatorFactory.cs +++ b/src/Umbraco.Core/Models/TemplateQuery/OperatorFactory.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Models.TemplateQuery; +/// +/// Provides factory methods for creating values from string representations. +/// public static class OperatorFactory { + /// + /// Converts a string representation of an operator to its enumeration value. + /// + /// The string representation of the operator (e.g., "=", "!=", "<", ">"). + /// The corresponding enumeration value. + /// Thrown when the string operator is null. + /// Thrown when the string operator is not recognized. public static Operator FromString(string stringOperator) { if (stringOperator == null) diff --git a/src/Umbraco.Core/Models/TemplateQuery/OperatorTerm.cs b/src/Umbraco.Core/Models/TemplateQuery/OperatorTerm.cs index d2a8c8e0dbbd..e6f2250a781e 100644 --- a/src/Umbraco.Core/Models/TemplateQuery/OperatorTerm.cs +++ b/src/Umbraco.Core/Models/TemplateQuery/OperatorTerm.cs @@ -1,7 +1,13 @@ namespace Umbraco.Cms.Core.Models.TemplateQuery; +/// +/// Represents an operator term that defines a comparison operation and the types it applies to. +/// public class OperatorTerm { + /// + /// Initializes a new instance of the class with default values. + /// public OperatorTerm() { Name = "is"; @@ -9,6 +15,12 @@ public OperatorTerm() AppliesTo = new[] { "string" }; } + /// + /// Initializes a new instance of the class with specified values. + /// + /// The display name of the operator. + /// The operator enumeration value. + /// The collection of property types this operator applies to. public OperatorTerm(string name, Operator @operator, IEnumerable appliesTo) { Name = name; @@ -16,9 +28,18 @@ public OperatorTerm(string name, Operator @operator, IEnumerable applies AppliesTo = appliesTo; } + /// + /// Gets or sets the display name of the operator. + /// public string Name { get; set; } + /// + /// Gets or sets the operator enumeration value. + /// public Operator Operator { get; set; } + /// + /// Gets or sets the collection of property types this operator applies to. + /// public IEnumerable AppliesTo { get; set; } } diff --git a/src/Umbraco.Core/Models/TemplateQuery/PropertyModel.cs b/src/Umbraco.Core/Models/TemplateQuery/PropertyModel.cs index 39ea100e7d45..463eb63281c5 100644 --- a/src/Umbraco.Core/Models/TemplateQuery/PropertyModel.cs +++ b/src/Umbraco.Core/Models/TemplateQuery/PropertyModel.cs @@ -1,10 +1,22 @@ namespace Umbraco.Cms.Core.Models.TemplateQuery; +/// +/// Represents a property that can be used in template queries for filtering or sorting. +/// public class PropertyModel { + /// + /// Gets or sets the display name of the property. + /// public string? Name { get; set; } + /// + /// Gets or sets the alias of the property. + /// public string Alias { get; set; } = string.Empty; + /// + /// Gets or sets the data type of the property (e.g., "string", "datetime", "boolean"). + /// public string? Type { get; set; } } diff --git a/src/Umbraco.Core/Models/TemplateQuery/QueryCondition.cs b/src/Umbraco.Core/Models/TemplateQuery/QueryCondition.cs index 2c64f13876ce..ffe8135c920e 100644 --- a/src/Umbraco.Core/Models/TemplateQuery/QueryCondition.cs +++ b/src/Umbraco.Core/Models/TemplateQuery/QueryCondition.cs @@ -1,10 +1,22 @@ namespace Umbraco.Cms.Core.Models.TemplateQuery; +/// +/// Represents a filter condition for a template query. +/// public class QueryCondition { + /// + /// Gets or sets the property to filter on. + /// public PropertyModel Property { get; set; } = new(); + /// + /// Gets or sets the operator term defining the comparison operation. + /// public OperatorTerm Term { get; set; } = new(); + /// + /// Gets or sets the constraint value to compare against. + /// public string ConstraintValue { get; set; } = string.Empty; } diff --git a/src/Umbraco.Core/Models/TemplateQuery/QueryConditionExtensions.cs b/src/Umbraco.Core/Models/TemplateQuery/QueryConditionExtensions.cs index 0722422aaef8..b932c8e637ce 100644 --- a/src/Umbraco.Core/Models/TemplateQuery/QueryConditionExtensions.cs +++ b/src/Umbraco.Core/Models/TemplateQuery/QueryConditionExtensions.cs @@ -4,11 +4,21 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for building query condition expressions. +/// public static class QueryConditionExtensions { private static Lazy StringContainsMethodInfo => new(() => typeof(string).GetMethod("Contains", new[] { typeof(string) })!); + /// + /// Builds a lambda expression predicate from a query condition. + /// + /// The type of the entity being queried. + /// The query condition to convert. + /// The alias to use for the parameter in the expression. + /// A lambda expression that can be used to filter entities. public static Expression> BuildCondition(this QueryCondition condition, string parameterAlias) { object constraintValue; diff --git a/src/Umbraco.Core/Models/TemplateQuery/QueryModel.cs b/src/Umbraco.Core/Models/TemplateQuery/QueryModel.cs index 06f5c82d1911..bac3fcdacabb 100644 --- a/src/Umbraco.Core/Models/TemplateQuery/QueryModel.cs +++ b/src/Umbraco.Core/Models/TemplateQuery/QueryModel.cs @@ -1,14 +1,32 @@ namespace Umbraco.Cms.Core.Models.TemplateQuery; +/// +/// Represents a query model for building template queries with filters and sorting. +/// public class QueryModel { + /// + /// Gets or sets the content type to filter by. + /// public ContentTypeModel? ContentType { get; set; } + /// + /// Gets or sets the source node for the query. + /// public SourceModel? Source { get; set; } + /// + /// Gets or sets the collection of filter conditions. + /// public IEnumerable? Filters { get; set; } + /// + /// Gets or sets the sort expression for ordering results. + /// public SortExpression? Sort { get; set; } + /// + /// Gets or sets the maximum number of items to return. + /// public int Take { get; set; } } diff --git a/src/Umbraco.Core/Models/TemplateQuery/SortExpression.cs b/src/Umbraco.Core/Models/TemplateQuery/SortExpression.cs index b5accd7ccda9..4fcac89c5f72 100644 --- a/src/Umbraco.Core/Models/TemplateQuery/SortExpression.cs +++ b/src/Umbraco.Core/Models/TemplateQuery/SortExpression.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.Models.TemplateQuery; +/// +/// Represents a sort expression for ordering query results. +/// public class SortExpression { + /// + /// Gets or sets the property to sort by. + /// public PropertyModel? Property { get; set; } + /// + /// Gets or sets the sort direction (e.g., "ascending" or "descending"). + /// public string? Direction { get; set; } } diff --git a/src/Umbraco.Core/Models/TemplateQuery/SourceModel.cs b/src/Umbraco.Core/Models/TemplateQuery/SourceModel.cs index a36ae38a9e70..fa7472568f39 100644 --- a/src/Umbraco.Core/Models/TemplateQuery/SourceModel.cs +++ b/src/Umbraco.Core/Models/TemplateQuery/SourceModel.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.Models.TemplateQuery; +/// +/// Represents the source node for a template query. +/// public class SourceModel { + /// + /// Gets or sets the unique identifier of the source node. + /// public int Id { get; set; } + /// + /// Gets or sets the name of the source node. + /// public string? Name { get; set; } } diff --git a/src/Umbraco.Core/Models/TemporaryFileUpload/CreateTemporaryFileModel.cs b/src/Umbraco.Core/Models/TemporaryFileUpload/CreateTemporaryFileModel.cs index cae26224a551..385cccb7a04a 100644 --- a/src/Umbraco.Core/Models/TemporaryFileUpload/CreateTemporaryFileModel.cs +++ b/src/Umbraco.Core/Models/TemporaryFileUpload/CreateTemporaryFileModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models.TemporaryFile; +namespace Umbraco.Cms.Core.Models.TemporaryFile; +/// +/// Represents the model for creating a new temporary file. +/// public class CreateTemporaryFileModel : TemporaryFileModelBase { } diff --git a/src/Umbraco.Core/Models/TemporaryFileUpload/TemporaryFileModel.cs b/src/Umbraco.Core/Models/TemporaryFileUpload/TemporaryFileModel.cs index 5315c1ce5846..e8e74fdef68e 100644 --- a/src/Umbraco.Core/Models/TemporaryFileUpload/TemporaryFileModel.cs +++ b/src/Umbraco.Core/Models/TemporaryFileUpload/TemporaryFileModel.cs @@ -1,6 +1,12 @@ namespace Umbraco.Cms.Core.Models.TemporaryFile; +/// +/// Represents a temporary file with its availability expiration time. +/// public class TemporaryFileModel : TemporaryFileModelBase { + /// + /// Gets or sets the date and time until which the temporary file is available. + /// public required DateTime AvailableUntil { get; set; } } diff --git a/src/Umbraco.Core/Models/TemporaryFileUpload/TemporaryFileModelBase.cs b/src/Umbraco.Core/Models/TemporaryFileUpload/TemporaryFileModelBase.cs index f33866d09817..63eb607d8cf9 100644 --- a/src/Umbraco.Core/Models/TemporaryFileUpload/TemporaryFileModelBase.cs +++ b/src/Umbraco.Core/Models/TemporaryFileUpload/TemporaryFileModelBase.cs @@ -1,10 +1,22 @@ namespace Umbraco.Cms.Core.Models.TemporaryFile; +/// +/// Represents the base model for a temporary file. +/// public abstract class TemporaryFileModelBase { + /// + /// Gets or sets the name of the file. + /// public required string FileName { get; set; } + /// + /// Gets or sets the unique key identifying the temporary file. + /// public Guid Key { get; set; } + /// + /// Gets or sets the function to open a read stream for the file content. + /// public Func OpenReadStream { get; set; } = () => Stream.Null; } diff --git a/src/Umbraco.Core/Models/TextFileCreateModel.cs b/src/Umbraco.Core/Models/TextFileCreateModel.cs index 0b434cb70383..48b37d9886a1 100644 --- a/src/Umbraco.Core/Models/TextFileCreateModel.cs +++ b/src/Umbraco.Core/Models/TextFileCreateModel.cs @@ -1,10 +1,28 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents the base model for creating a text file. +/// public abstract class TextFileCreateModel { + /// + /// Gets or sets the name of the file to create. + /// public required string Name { get; set; } + /// + /// Gets or sets the parent path where the file will be created. + /// + /// + /// The parent directory path, or null to create at the root level. + /// public string? ParentPath { get; set; } + /// + /// Gets or sets the initial content of the file. + /// + /// + /// The file content, or null for an empty file. + /// public string? Content { get; set; } } diff --git a/src/Umbraco.Core/Models/TextFileRenameModel.cs b/src/Umbraco.Core/Models/TextFileRenameModel.cs index f60d77bb73ec..6bf22900d62b 100644 --- a/src/Umbraco.Core/Models/TextFileRenameModel.cs +++ b/src/Umbraco.Core/Models/TextFileRenameModel.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents the base model for renaming a text file. +/// public abstract class TextFileRenameModel { /// diff --git a/src/Umbraco.Core/Models/TextFileUpdateModel.cs b/src/Umbraco.Core/Models/TextFileUpdateModel.cs index 20cb85339fce..ec57975d9135 100644 --- a/src/Umbraco.Core/Models/TextFileUpdateModel.cs +++ b/src/Umbraco.Core/Models/TextFileUpdateModel.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents the base model for updating a text file's content. +/// public abstract class TextFileUpdateModel { /// diff --git a/src/Umbraco.Core/Models/TwoFactorLogin.cs b/src/Umbraco.Core/Models/TwoFactorLogin.cs index 551482e3a25a..ca5636ed2909 100644 --- a/src/Umbraco.Core/Models/TwoFactorLogin.cs +++ b/src/Umbraco.Core/Models/TwoFactorLogin.cs @@ -2,13 +2,28 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a two-factor authentication login configuration for a user or member. +/// public class TwoFactorLogin : EntityBase, ITwoFactorLogin { + /// + /// Gets or sets a value indicating whether the two-factor authentication has been confirmed/activated. + /// public bool Confirmed { get; set; } + /// + /// Gets or sets the name of the two-factor authentication provider. + /// public string ProviderName { get; set; } = null!; + /// + /// Gets or sets the secret key used for two-factor authentication. + /// public string Secret { get; set; } = null!; + /// + /// Gets or sets the unique key of the user or member associated with this two-factor login. + /// public Guid UserOrMemberKey { get; set; } } diff --git a/src/Umbraco.Core/Models/UmbracoUserExtensions.cs b/src/Umbraco.Core/Models/UmbracoUserExtensions.cs index d708704fac45..894d48401a07 100644 --- a/src/Umbraco.Core/Models/UmbracoUserExtensions.cs +++ b/src/Umbraco.Core/Models/UmbracoUserExtensions.cs @@ -9,11 +9,27 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for the interface. +/// public static class UmbracoUserExtensions { + /// + /// Gets the permissions for a user on a specific content path. + /// + /// The user to get permissions for. + /// The content path to check permissions on. + /// The user service. + /// An enumerable of permission strings. public static IEnumerable GetPermissions(this IUser user, string path, IUserService userService) => userService.GetPermissionsForPath(user, path).GetAllPermissions(); + /// + /// Determines whether the user has access to the specified section (application). + /// + /// The user to check. + /// The section/application alias to check access for. + /// true if the user has access to the section; otherwise, false. public static bool HasSectionAccess(this IUser user, string app) { IEnumerable apps = user.AllowedSections; @@ -69,6 +85,13 @@ public static CultureInfo GetUserCulture(this IUser user, ILocalizedTextService return GetUserCulture(user.Language, textService, globalSettings); } + /// + /// Gets the culture info for a specified language code. + /// + /// The user's language code. + /// The localized text service. + /// The global settings. + /// The for the specified language, or the default UI language if not found. public static CultureInfo GetUserCulture(string? userLanguage, ILocalizedTextService textService, GlobalSettings globalSettings) { try diff --git a/src/Umbraco.Core/Models/UsageInformation.cs b/src/Umbraco.Core/Models/UsageInformation.cs index 3de3a1201aa7..03624f784782 100644 --- a/src/Umbraco.Core/Models/UsageInformation.cs +++ b/src/Umbraco.Core/Models/UsageInformation.cs @@ -2,18 +2,32 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents usage information data for telemetry or reporting purposes. +/// [DataContract] public class UsageInformation { + /// + /// Initializes a new instance of the class. + /// + /// The name identifying the type of usage information. + /// The usage data payload. public UsageInformation(string name, object data) { Name = name; Data = data; } + /// + /// Gets the name identifying the type of usage information. + /// [DataMember(Name = "name")] public string Name { get; } + /// + /// Gets the usage data payload. + /// [DataMember(Name = "data")] public object Data { get; } } diff --git a/src/Umbraco.Core/Models/UserCreateModel.cs b/src/Umbraco.Core/Models/UserCreateModel.cs index f21561657fcb..d7fc9b8adf6c 100644 --- a/src/Umbraco.Core/Models/UserCreateModel.cs +++ b/src/Umbraco.Core/Models/UserCreateModel.cs @@ -1,18 +1,42 @@ -using Umbraco.Cms.Core.Models.Membership; +using Umbraco.Cms.Core.Models.Membership; namespace Umbraco.Cms.Core.Models; +/// +/// Represents the model used for creating a new user. +/// public class UserCreateModel { + /// + /// Gets or sets the optional unique identifier for the user. + /// + /// + /// The user's GUID, or null to auto-generate one. + /// public Guid? Id { get; set; } + /// + /// Gets or sets the email address of the user. + /// public string Email { get; set; } = string.Empty; + /// + /// Gets or sets the username for the user. + /// public string UserName { get; set; } = string.Empty; + /// + /// Gets or sets the display name of the user. + /// public string Name { get; set; } = string.Empty; + /// + /// Gets or sets the kind/type of user being created. + /// public UserKind Kind { get; set; } + /// + /// Gets or sets the collection of user group keys the user should be assigned to. + /// public ISet UserGroupKeys { get; set; } = new HashSet(); } diff --git a/src/Umbraco.Core/Models/UserExtensions.cs b/src/Umbraco.Core/Models/UserExtensions.cs index f1f4064847a6..ffbd1d89a983 100644 --- a/src/Umbraco.Core/Models/UserExtensions.cs +++ b/src/Umbraco.Core/Models/UserExtensions.cs @@ -10,6 +10,10 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Provides extension methods for the interface related to +/// content/media access, avatar URLs, and start node calculations. +/// public static class UserExtensions { /// @@ -56,6 +60,15 @@ public static string[] GetUserAvatarUrls(this IUser user, IAppCache cache, Media }.WhereNotNull().ToArray(); } + /// + /// Determines whether the user has path access to the specified content item. + /// + /// The user to check. + /// The content item to check access for. + /// The entity service. + /// The application caches. + /// true if the user has access to the content path; otherwise, false. + /// Thrown when is null. public static bool HasPathAccess(this IUser user, IContent content, IEntityService entityService, AppCaches appCaches) { if (content == null) @@ -69,30 +82,51 @@ public static bool HasPathAccess(this IUser user, IContent content, IEntityServi Constants.System.RecycleBinContent); } + /// + /// Determines whether the user has access to the content root. + /// internal static bool HasContentRootAccess(this IUser user, IEntityService entityService, AppCaches appCaches) => ContentPermissions.HasPathAccess( Constants.System.RootString, user.CalculateContentStartNodeIds(entityService, appCaches), Constants.System.RecycleBinContent); + /// + /// Determines whether the user has access to the content recycle bin. + /// internal static bool HasContentBinAccess(this IUser user, IEntityService entityService, AppCaches appCaches) => ContentPermissions.HasPathAccess( Constants.System.RecycleBinContentString, user.CalculateContentStartNodeIds(entityService, appCaches), Constants.System.RecycleBinContent); + /// + /// Determines whether the user has access to the media root. + /// internal static bool HasMediaRootAccess(this IUser user, IEntityService entityService, AppCaches appCaches) => ContentPermissions.HasPathAccess( Constants.System.RootString, user.CalculateMediaStartNodeIds(entityService, appCaches), Constants.System.RecycleBinMedia); + /// + /// Determines whether the user has access to the media recycle bin. + /// internal static bool HasMediaBinAccess(this IUser user, IEntityService entityService, AppCaches appCaches) => ContentPermissions.HasPathAccess( Constants.System.RecycleBinMediaString, user.CalculateMediaStartNodeIds(entityService, appCaches), Constants.System.RecycleBinMedia); + /// + /// Determines whether the user has path access to the specified media item. + /// + /// The user to check. + /// The media item to check access for. + /// The entity service. + /// The application caches. + /// true if the user has access to the media path; otherwise, false. + /// Thrown when is null. public static bool HasPathAccess(this IUser user, IMedia? media, IEntityService entityService, AppCaches appCaches) { if (media == null) @@ -103,6 +137,15 @@ public static bool HasPathAccess(this IUser user, IMedia? media, IEntityService return ContentPermissions.HasPathAccess(media.Path, user.CalculateMediaStartNodeIds(entityService, appCaches), Constants.System.RecycleBinMedia); } + /// + /// Determines whether the user has content path access to the specified entity. + /// + /// The user to check. + /// The entity to check access for. + /// The entity service. + /// The application caches. + /// true if the user has access to the content path; otherwise, false. + /// Thrown when is null. public static bool HasContentPathAccess(this IUser user, IUmbracoEntity entity, IEntityService entityService, AppCaches appCaches) { if (entity == null) @@ -116,6 +159,15 @@ public static bool HasContentPathAccess(this IUser user, IUmbracoEntity entity, Constants.System.RecycleBinContent); } + /// + /// Determines whether the user has media path access to the specified entity. + /// + /// The user to check. + /// The entity to check access for. + /// The entity service. + /// The application caches. + /// true if the user has access to the media path; otherwise, false. + /// Thrown when is null. public static bool HasMediaPathAccess(this IUser user, IUmbracoEntity entity, IEntityService entityService, AppCaches appCaches) { if (entity == null) @@ -152,6 +204,13 @@ public static int[] CalculateAllowedLanguageIds(this IUser user, ILocalizationSe : user.Groups.SelectMany(x => x.AllowedLanguages).Distinct().ToArray(); } + /// + /// Calculates the content start node IDs for the user, combining user and group start nodes. + /// + /// The user to calculate start nodes for. + /// The entity service. + /// The application caches. + /// An array of content start node IDs, or null if no start nodes are defined. public static int[]? CalculateContentStartNodeIds(this IUser user, IEntityService entityService, AppCaches appCaches) { var cacheKey = user.UserCacheKey(CacheKeys.UserAllContentStartNodesPrefix); @@ -211,6 +270,13 @@ public static int[] CalculateAllowedLanguageIds(this IUser user, ILocalizationSe return result; } + /// + /// Gets the media start node paths for the user. + /// + /// The user to get paths for. + /// The entity service. + /// The application caches. + /// An array of media start node paths, or null if no start nodes are defined. public static string[]? GetMediaStartNodePaths(this IUser user, IEntityService entityService, AppCaches appCaches) { var cacheKey = user.UserCacheKey(CacheKeys.UserMediaStartNodePathsPrefix); @@ -229,6 +295,13 @@ public static int[] CalculateAllowedLanguageIds(this IUser user, ILocalizationSe return result; } + /// + /// Gets the content start node paths for the user. + /// + /// The user to get paths for. + /// The entity service. + /// The application caches. + /// An array of content start node paths, or null if no start nodes are defined. public static string[]? GetContentStartNodePaths(this IUser user, IEntityService entityService, AppCaches appCaches) { var cacheKey = user.UserCacheKey(CacheKeys.UserContentStartNodePathsPrefix); @@ -248,6 +321,14 @@ public static int[] CalculateAllowedLanguageIds(this IUser user, ILocalizationSe return result; } + /// + /// Combines group and user start nodes, excluding nodes in the recycle bin. + /// + /// The Umbraco object type (Document or Media). + /// The start nodes from user groups. + /// The start nodes from the user. + /// The entity service. + /// An array of combined start node IDs. internal static int[] CombineStartNodes(UmbracoObjectTypes objectType, int[] groupSn, int[] userSn, IEntityService entityService) { // assume groupSn and userSn each don't contain duplicates @@ -316,15 +397,27 @@ internal static int[] CombineStartNodes(UmbracoObjectTypes objectType, int[] gro return lsn.ToArray(); } + /// + /// Gets the isolated user cache from the application caches. + /// private static IAppPolicyCache GetUserCache(AppCaches appCaches) => appCaches.IsolatedCaches.GetOrCreate(); + /// + /// Generates a cache key for the user. + /// private static string UserCacheKey(this IUser user, string cacheKey) => $"{cacheKey}{user.Key}"; + /// + /// Determines whether a path starts with another path (as a parent). + /// private static bool StartsWithPath(string test, string path) => test.StartsWith(path) && test.Length > path.Length && test[path.Length] == ','; + /// + /// Gets the recycle bin path for the specified object type. + /// private static string GetBinPath(UmbracoObjectTypes objectType) { var binPath = Constants.System.RootString + ","; diff --git a/src/Umbraco.Core/Models/UserExternalLoginProviderModel.cs b/src/Umbraco.Core/Models/UserExternalLoginProviderModel.cs index 538012245d3f..a49d2b0261cf 100644 --- a/src/Umbraco.Core/Models/UserExternalLoginProviderModel.cs +++ b/src/Umbraco.Core/Models/UserExternalLoginProviderModel.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents information about an external login provider and its association with a user. +/// public class UserExternalLoginProviderModel { + /// + /// Initializes a new instance of the class. + /// + /// The authentication scheme name of the provider. + /// Indicates whether the provider is linked to the user. + /// Indicates whether manual linking is enabled for this provider. + /// The provider-specific key for the user, if linked. public UserExternalLoginProviderModel(string providerSchemeName, bool isLinkedOnUser, bool hasManualLinkingEnabled, string? providerKey) { ProviderSchemeName = providerSchemeName; @@ -10,11 +20,29 @@ public UserExternalLoginProviderModel(string providerSchemeName, bool isLinkedOn ProviderKey = providerKey; } + /// + /// Gets the authentication scheme name of the external login provider. + /// public string ProviderSchemeName { get; } + /// + /// Gets or sets the provider-specific key identifying the user with this provider. + /// + /// + /// The provider key, or null if the user is not linked to this provider. + /// public string? ProviderKey { get; set; } + /// + /// Gets a value indicating whether this external login provider is linked to the user. + /// public bool IsLinkedOnUser { get; } + /// + /// Gets a value indicating whether manual linking is enabled for this provider. + /// + /// + /// When enabled, users can manually link/unlink their account with this provider. + /// public bool HasManualLinkingEnabled { get; } } diff --git a/src/Umbraco.Core/Models/UserForgotPasswordMessage.cs b/src/Umbraco.Core/Models/UserForgotPasswordMessage.cs index ad25fd1b7284..e90899872ad0 100644 --- a/src/Umbraco.Core/Models/UserForgotPasswordMessage.cs +++ b/src/Umbraco.Core/Models/UserForgotPasswordMessage.cs @@ -2,9 +2,18 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents the message data for a forgot password notification to a user. +/// public class UserForgotPasswordMessage { + /// + /// Gets or sets the URI for the password reset page. + /// public required Uri ForgotPasswordUri { get; set; } + /// + /// Gets or sets the user who will receive the forgot password message. + /// public required IUser Recipient { get; set; } } diff --git a/src/Umbraco.Core/Models/UserInvitationMessage.cs b/src/Umbraco.Core/Models/UserInvitationMessage.cs index e833bbc1d783..c10f5c1d54a9 100644 --- a/src/Umbraco.Core/Models/UserInvitationMessage.cs +++ b/src/Umbraco.Core/Models/UserInvitationMessage.cs @@ -1,14 +1,29 @@ -using Umbraco.Cms.Core.Models.Membership; +using Umbraco.Cms.Core.Models.Membership; namespace Umbraco.Cms.Core.Models; +/// +/// Represents the message data for a user invitation notification. +/// public class UserInvitationMessage { + /// + /// Gets or sets the custom message to include in the invitation. + /// public required string Message { get; set; } + /// + /// Gets or sets the URI for the invitation acceptance page. + /// public required Uri InviteUri { get; set; } + /// + /// Gets or sets the user who will receive the invitation. + /// public required IUser Recipient { get; set; } + /// + /// Gets or sets the user who is sending the invitation. + /// public required IUser Sender { get; set; } } diff --git a/src/Umbraco.Core/Models/UserInviteModel.cs b/src/Umbraco.Core/Models/UserInviteModel.cs index 744adbe89312..72f094f6ea28 100644 --- a/src/Umbraco.Core/Models/UserInviteModel.cs +++ b/src/Umbraco.Core/Models/UserInviteModel.cs @@ -1,6 +1,15 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents the model used for inviting a new user to the system. +/// +/// +/// Extends with an optional message to include in the invitation. +/// public class UserInviteModel : UserCreateModel { + /// + /// Gets or sets an optional custom message to include in the invitation email. + /// public string? Message { get; set; } } diff --git a/src/Umbraco.Core/Models/UserResendInviteModel.cs b/src/Umbraco.Core/Models/UserResendInviteModel.cs index 9dd78cd30457..e05c09ff9507 100644 --- a/src/Umbraco.Core/Models/UserResendInviteModel.cs +++ b/src/Umbraco.Core/Models/UserResendInviteModel.cs @@ -1,7 +1,17 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents the model used for resending an invitation to a user. +/// public class UserResendInviteModel { + /// + /// Gets or sets an optional custom message to include in the resent invitation email. + /// public string? Message { get; set; } + + /// + /// Gets or sets the unique key of the user whose invitation should be resent. + /// public Guid InvitedUserKey { get; set; } } diff --git a/src/Umbraco.Core/Models/UserTwoFactorProviderModel.cs b/src/Umbraco.Core/Models/UserTwoFactorProviderModel.cs index acdaed7dd9ae..4c6e4220417d 100644 --- a/src/Umbraco.Core/Models/UserTwoFactorProviderModel.cs +++ b/src/Umbraco.Core/Models/UserTwoFactorProviderModel.cs @@ -2,18 +2,32 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents information about a two-factor authentication provider and its status for a user. +/// [DataContract] public class UserTwoFactorProviderModel { + /// + /// Initializes a new instance of the class. + /// + /// The name of the two-factor authentication provider. + /// Indicates whether this provider is enabled for the user. public UserTwoFactorProviderModel(string providerName, bool isEnabledOnUser) { ProviderName = providerName; IsEnabledOnUser = isEnabledOnUser; } + /// + /// Gets the name of the two-factor authentication provider. + /// [DataMember(Name = "providerName")] public string ProviderName { get; } + /// + /// Gets a value indicating whether this two-factor provider is enabled for the user. + /// [DataMember(Name = "isEnabledOnUser")] public bool IsEnabledOnUser { get; } } diff --git a/src/Umbraco.Core/Models/UserUpdateModel.cs b/src/Umbraco.Core/Models/UserUpdateModel.cs index 684cbafda891..b2d5633c08f9 100644 --- a/src/Umbraco.Core/Models/UserUpdateModel.cs +++ b/src/Umbraco.Core/Models/UserUpdateModel.cs @@ -1,24 +1,63 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents the model used for updating an existing user. +/// public class UserUpdateModel { + /// + /// Gets or sets the unique key of the existing user to update. + /// public required Guid ExistingUserKey { get; set; } + /// + /// Gets or sets the email address of the user. + /// public string Email { get; set; } = string.Empty; + /// + /// Gets or sets the username of the user. + /// public string UserName { get; set; } = string.Empty; + /// + /// Gets or sets the display name of the user. + /// public string Name { get; set; } = string.Empty; + /// + /// Gets or sets the ISO code of the user's preferred language. + /// public string LanguageIsoCode { get; set; } = string.Empty; + /// + /// Gets or sets the collection of content start node keys for the user. + /// + /// + /// These define the content tree sections the user has access to. + /// public ISet ContentStartNodeKeys { get; set; } = new HashSet(); + /// + /// Gets or sets a value indicating whether the user has access to the content root. + /// public bool HasContentRootAccess { get; set; } + /// + /// Gets or sets the collection of media start node keys for the user. + /// + /// + /// These define the media tree sections the user has access to. + /// public ISet MediaStartNodeKeys { get; set; } = new HashSet(); + /// + /// Gets or sets a value indicating whether the user has access to the media root. + /// public bool HasMediaRootAccess { get; set; } + /// + /// Gets or sets the collection of user group keys the user belongs to. + /// public ISet UserGroupKeys { get; set; } = new HashSet(); } diff --git a/src/Umbraco.Core/Models/UsersToUserGroupManipulationModel.cs b/src/Umbraco.Core/Models/UsersToUserGroupManipulationModel.cs index 375d6fcdb17a..5ebe6fc77366 100644 --- a/src/Umbraco.Core/Models/UsersToUserGroupManipulationModel.cs +++ b/src/Umbraco.Core/Models/UsersToUserGroupManipulationModel.cs @@ -1,11 +1,25 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a model for adding or removing users from a user group. +/// public class UsersToUserGroupManipulationModel { + /// + /// Gets the unique key of the user group to manipulate. + /// public Guid UserGroupKey { get; init; } + /// + /// Gets the array of user keys to add to or remove from the user group. + /// public Guid[] UserKeys { get; init; } + /// + /// Initializes a new instance of the class. + /// + /// The unique key of the user group. + /// The array of user keys to manipulate. public UsersToUserGroupManipulationModel(Guid userGroupKey, Guid[] userKeys) { UserGroupKey = userGroupKey; diff --git a/src/Umbraco.Core/Models/Validation/PropertyValidationContext.cs b/src/Umbraco.Core/Models/Validation/PropertyValidationContext.cs index 9dd1afe0c1b5..9235d7efcc79 100644 --- a/src/Umbraco.Core/Models/Validation/PropertyValidationContext.cs +++ b/src/Umbraco.Core/Models/Validation/PropertyValidationContext.cs @@ -1,20 +1,45 @@ -namespace Umbraco.Cms.Core.Models.Validation; +namespace Umbraco.Cms.Core.Models.Validation; +/// +/// Represents the context for property validation, including culture and segment information. +/// public sealed class PropertyValidationContext { + /// + /// Gets the culture being validated, or null for invariant validation. + /// public required string? Culture { get; init; } + /// + /// Gets the segment being validated, or null for neutral segment validation. + /// public required string? Segment { get; init; } + /// + /// Gets the collection of cultures being validated. + /// public required IEnumerable CulturesBeingValidated { get; init; } + /// + /// Gets the collection of segments being validated. + /// public required IEnumerable SegmentsBeingValidated { get; init; } + /// + /// Creates an empty property validation context with no culture or segment. + /// + /// An empty property validation context. public static PropertyValidationContext Empty() => new() { Culture = null, Segment = null, CulturesBeingValidated = [], SegmentsBeingValidated = [] }; + /// + /// Creates a property validation context for a specific culture and segment. + /// + /// The culture to validate. + /// The segment to validate. + /// A property validation context for the specified culture and segment. public static PropertyValidationContext CultureAndSegment(string? culture, string? segment) => new() { Culture = culture, Segment = segment, CulturesBeingValidated = [], SegmentsBeingValidated = [] diff --git a/src/Umbraco.Core/Models/Verify2FACodeModel.cs b/src/Umbraco.Core/Models/Verify2FACodeModel.cs index 3d50638f2745..d9648e9cde08 100644 --- a/src/Umbraco.Core/Models/Verify2FACodeModel.cs +++ b/src/Umbraco.Core/Models/Verify2FACodeModel.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; namespace Umbraco.Cms.Core.Models; @@ -8,9 +8,15 @@ namespace Umbraco.Cms.Core.Models; /// public class Verify2FACodeModel { + /// + /// Gets or sets the verification code entered by the user. + /// [Required] public required string Code { get; set; } + /// + /// Gets or sets the name of the two-factor authentication provider. + /// [Required] public required string Provider { get; set; } diff --git a/src/Umbraco.Core/Models/Webhook.cs b/src/Umbraco.Core/Models/Webhook.cs index 0528b3a6ef4f..fea973e1b0c4 100644 --- a/src/Umbraco.Core/Models/Webhook.cs +++ b/src/Umbraco.Core/Models/Webhook.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Models; +/// +/// Represents a webhook configuration that triggers HTTP requests on specified events. +/// public class Webhook : EntityBase, IWebhook { // Custom comparers for enumerable @@ -32,6 +35,14 @@ private static readonly DelegateEqualityComparer> private bool _enabled; private IDictionary _headers; + /// + /// Initializes a new instance of the class. + /// + /// The URL to send webhook requests to. + /// Indicates whether the webhook is enabled. Defaults to false. + /// The content type keys that trigger this webhook. + /// The event aliases that trigger this webhook. + /// Custom HTTP headers to include in webhook requests. public Webhook(string url, bool? enabled = null, Guid[]? entityKeys = null, string[]? events = null, IDictionary? headers = null) { _url = url; @@ -41,42 +52,66 @@ public Webhook(string url, bool? enabled = null, Guid[]? entityKeys = null, stri _enabled = enabled ?? false; } + /// + /// Gets or sets the display name of the webhook. + /// public string? Name { get => _name; set => SetPropertyValueAndDetectChanges(value, ref _name!, nameof(Name)); } + /// + /// Gets or sets the description of the webhook. + /// public string? Description { get => _description; set => SetPropertyValueAndDetectChanges(value, ref _description!, nameof(Description)); } + /// + /// Gets or sets the URL to send webhook requests to. + /// public string Url { get => _url; set => SetPropertyValueAndDetectChanges(value, ref _url!, nameof(Url)); } + /// + /// Gets or sets the event aliases that trigger this webhook. + /// public string[] Events { get => _events; set => SetPropertyValueAndDetectChanges(value, ref _events!, nameof(Events), EventsComparer); } + /// + /// Gets or sets the content type keys that filter which content triggers this webhook. + /// + /// + /// If empty, the webhook triggers for all content types. + /// public Guid[] ContentTypeKeys { get => _contentTypeKeys; set => SetPropertyValueAndDetectChanges(value, ref _contentTypeKeys!, nameof(ContentTypeKeys), ContentTypeKeysComparer); } + /// + /// Gets or sets a value indicating whether the webhook is enabled. + /// public bool Enabled { get => _enabled; set => SetPropertyValueAndDetectChanges(value, ref _enabled, nameof(Enabled)); } + /// + /// Gets or sets the custom HTTP headers to include in webhook requests. + /// public IDictionary Headers { get => _headers; diff --git a/src/Umbraco.Core/Models/WebhookLog.cs b/src/Umbraco.Core/Models/WebhookLog.cs index 5340b0f73888..fbb33d38ffed 100644 --- a/src/Umbraco.Core/Models/WebhookLog.cs +++ b/src/Umbraco.Core/Models/WebhookLog.cs @@ -1,32 +1,77 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents a log entry for a webhook request execution. +/// public class WebhookLog { + /// + /// Gets or sets the unique identifier of the log entry. + /// public int Id { get; set; } + /// + /// Gets or sets the unique key of the webhook that was executed. + /// public Guid WebhookKey { get; set; } + /// + /// Gets or sets the unique key of this log entry. + /// public Guid Key { get; set; } + /// + /// Gets or sets the URL that the webhook request was sent to. + /// public string Url { get; set; } = string.Empty; + /// + /// Gets or sets the HTTP status code returned from the webhook request. + /// public string StatusCode { get; set; } = string.Empty; + /// + /// Gets or sets the date and time when the webhook request was executed. + /// public DateTime Date { get; set; } + /// + /// Gets or sets the alias of the event that triggered the webhook. + /// public string EventAlias { get; set; } = string.Empty; + /// + /// Gets or sets the number of retry attempts for this webhook request. + /// public int RetryCount { get; set; } + /// + /// Gets or sets the HTTP headers that were sent with the request. + /// public string RequestHeaders { get; set; } = string.Empty; + /// + /// Gets or sets the body content that was sent with the request. + /// public string? RequestBody { get; set; } = string.Empty; + /// + /// Gets or sets the HTTP headers returned in the response. + /// public string ResponseHeaders { get; set; } = string.Empty; + /// + /// Gets or sets the body content returned in the response. + /// public string ResponseBody { get; set; } = string.Empty; + /// + /// Gets or sets a value indicating whether an exception occurred during the request. + /// public bool ExceptionOccured { get; set; } + /// + /// Gets or sets a value indicating whether the response had a success status code (2xx). + /// public bool IsSuccessStatusCode { get; set; } } diff --git a/src/Umbraco.Core/Models/WebhookRequest.cs b/src/Umbraco.Core/Models/WebhookRequest.cs index b7f2d5828438..86eee9e10982 100644 --- a/src/Umbraco.Core/Models/WebhookRequest.cs +++ b/src/Umbraco.Core/Models/WebhookRequest.cs @@ -1,14 +1,32 @@ -namespace Umbraco.Cms.Core.Models; +namespace Umbraco.Cms.Core.Models; +/// +/// Represents a pending webhook request that needs to be sent. +/// public class WebhookRequest { + /// + /// Gets or sets the unique identifier of the request. + /// public int Id { get; set; } + /// + /// Gets or sets the unique key of the webhook this request belongs to. + /// public Guid WebhookKey { get; set; } + /// + /// Gets or sets the alias of the event that triggered this webhook request. + /// public string EventAlias { get; set; } = string.Empty; + /// + /// Gets or sets the serialized request payload to send. + /// public string? RequestObject { get; set; } + /// + /// Gets or sets the number of retry attempts made for this request. + /// public int RetryCount { get; set; } } diff --git a/src/Umbraco.Core/Net/IIpResolver.cs b/src/Umbraco.Core/Net/IIpResolver.cs index edc9c6428c86..b59812d01d91 100644 --- a/src/Umbraco.Core/Net/IIpResolver.cs +++ b/src/Umbraco.Core/Net/IIpResolver.cs @@ -1,6 +1,13 @@ namespace Umbraco.Cms.Core.Net; +/// +/// Provides functionality to resolve the IP address of the current request. +/// public interface IIpResolver { + /// + /// Gets the IP address of the current HTTP request. + /// + /// The IP address as a string. string GetCurrentRequestIpAddress(); } diff --git a/src/Umbraco.Core/Net/ISessionIdResolver.cs b/src/Umbraco.Core/Net/ISessionIdResolver.cs index 4ec6248b3958..db77dddfc801 100644 --- a/src/Umbraco.Core/Net/ISessionIdResolver.cs +++ b/src/Umbraco.Core/Net/ISessionIdResolver.cs @@ -1,6 +1,12 @@ namespace Umbraco.Cms.Core.Net; +/// +/// Provides functionality to resolve the session identifier for the current request. +/// public interface ISessionIdResolver { + /// + /// Gets the session identifier for the current request, if available. + /// string? SessionId { get; } } diff --git a/src/Umbraco.Core/Net/IUserAgentProvider.cs b/src/Umbraco.Core/Net/IUserAgentProvider.cs index 6916ee8d374b..9d77c5529b40 100644 --- a/src/Umbraco.Core/Net/IUserAgentProvider.cs +++ b/src/Umbraco.Core/Net/IUserAgentProvider.cs @@ -1,6 +1,13 @@ namespace Umbraco.Cms.Core.Net; +/// +/// Provides functionality to retrieve the user agent string from the current request. +/// public interface IUserAgentProvider { + /// + /// Gets the user agent string from the current HTTP request. + /// + /// The user agent string, or null if not available. string? GetUserAgent(); } diff --git a/src/Umbraco.Core/Net/NullSessionIdResolver.cs b/src/Umbraco.Core/Net/NullSessionIdResolver.cs index c76c6c86322e..60f2473b97a1 100644 --- a/src/Umbraco.Core/Net/NullSessionIdResolver.cs +++ b/src/Umbraco.Core/Net/NullSessionIdResolver.cs @@ -1,6 +1,13 @@ namespace Umbraco.Cms.Core.Net; +/// +/// A null implementation of that always returns null. +/// +/// +/// This implementation is used when session support is not available or not configured. +/// public class NullSessionIdResolver : ISessionIdResolver { + /// public string? SessionId => null; } diff --git a/src/Umbraco.Core/Notifications/ApplicationCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/ApplicationCacheRefresherNotification.cs index cd0b1326f463..e7244b74b1c0 100644 --- a/src/Umbraco.Core/Notifications/ApplicationCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/ApplicationCacheRefresherNotification.cs @@ -1,9 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when application-wide cache needs to be refreshed. +/// +/// +/// This notification is used to synchronize application cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class ApplicationCacheRefresherNotification : CacheRefresherNotification { + /// + /// Initializes a new instance of the class. + /// + /// The payload containing information about what to refresh. + /// The type of cache refresh operation. public ApplicationCacheRefresherNotification(object messageObject, MessageType messageType) : base( messageObject, diff --git a/src/Umbraco.Core/Notifications/AssignedMemberRolesNotification.cs b/src/Umbraco.Core/Notifications/AssignedMemberRolesNotification.cs index 96d0391b95ce..a20558ee4a1a 100644 --- a/src/Umbraco.Core/Notifications/AssignedMemberRolesNotification.cs +++ b/src/Umbraco.Core/Notifications/AssignedMemberRolesNotification.cs @@ -1,18 +1,21 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMemberService when the AssignRoles and ReplaceRoles methods are called in the API. +/// Notification that is published after roles have been assigned to members. /// +/// +/// This notification is published by the when AssignRoles or ReplaceRoles methods complete. +/// public class AssignedMemberRolesNotification : MemberRolesNotification { /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class. /// - /// - /// Collection of Ids of the members the roles are being assigned to. - /// - /// - /// Collection of role names being assigned. - /// + /// The IDs of the members the roles are being assigned to. + /// The names of the roles being assigned. public AssignedMemberRolesNotification(int[] memberIds, string[] roles) : base(memberIds, roles) { diff --git a/src/Umbraco.Core/Notifications/AssignedUserGroupPermissionsNotification.cs b/src/Umbraco.Core/Notifications/AssignedUserGroupPermissionsNotification.cs index 347f1934bc3f..08bdcf5c424e 100644 --- a/src/Umbraco.Core/Notifications/AssignedUserGroupPermissionsNotification.cs +++ b/src/Umbraco.Core/Notifications/AssignedUserGroupPermissionsNotification.cs @@ -1,14 +1,32 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models.Membership; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when user group permissions have been assigned to entities. +/// +/// +/// This notification is published after permissions have been assigned, allowing handlers +/// to react to permission changes for auditing or cache invalidation purposes. +/// public class AssignedUserGroupPermissionsNotification : EnumerableObjectNotification { + /// + /// Initializes a new instance of the class. + /// + /// The entity permissions that were assigned. + /// The event messages collection. public AssignedUserGroupPermissionsNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the entity permissions that were assigned. + /// public IEnumerable EntityPermissions => Target; } diff --git a/src/Umbraco.Core/Notifications/CacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/CacheRefresherNotification.cs index 637c05dfb099..08fbc804ffad 100644 --- a/src/Umbraco.Core/Notifications/CacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/CacheRefresherNotification.cs @@ -1,19 +1,38 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; /// -/// Base class for cache refresher notifications +/// Abstract base class for cache refresher notifications. /// +/// +/// Cache refresher notifications are used to synchronize cache invalidation across +/// multiple servers in a load-balanced environment. +/// public abstract class CacheRefresherNotification : INotification { + /// + /// Initializes a new instance of the class. + /// + /// The payload containing information about what to refresh. + /// The type of cache refresh operation. + /// Thrown when is null. public CacheRefresherNotification(object messageObject, MessageType messageType) { MessageObject = messageObject ?? throw new ArgumentNullException(nameof(messageObject)); MessageType = messageType; } + /// + /// Gets the payload containing information about what to refresh. + /// public object MessageObject { get; } + /// + /// Gets the type of cache refresh operation. + /// public MessageType MessageType { get; } } diff --git a/src/Umbraco.Core/Notifications/CancelableEnumerableObjectNotification.cs b/src/Umbraco.Core/Notifications/CancelableEnumerableObjectNotification.cs index 1f51e68409fe..15743d45546d 100644 --- a/src/Umbraco.Core/Notifications/CancelableEnumerableObjectNotification.cs +++ b/src/Umbraco.Core/Notifications/CancelableEnumerableObjectNotification.cs @@ -5,13 +5,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for cancelable notifications that carry a collection of target objects. +/// +/// The type of items in the collection. +/// +/// This class combines the functionality of with +/// as the target type, allowing handlers to both access the collection +/// of items and cancel the operation if needed. +/// public abstract class CancelableEnumerableObjectNotification : CancelableObjectNotification> { + /// + /// Initializes a new instance of the class with a single target item. + /// + /// The single target item. + /// The event messages collection. protected CancelableEnumerableObjectNotification(T target, EventMessages messages) : base(new[] { target }, messages) { } + /// + /// Initializes a new instance of the class with multiple target items. + /// + /// The collection of target items. + /// The event messages collection. protected CancelableEnumerableObjectNotification(IEnumerable target, EventMessages messages) : base( target, diff --git a/src/Umbraco.Core/Notifications/CancelableNotification.cs b/src/Umbraco.Core/Notifications/CancelableNotification.cs index 438bc1ee99d3..0c12faa80802 100644 --- a/src/Umbraco.Core/Notifications/CancelableNotification.cs +++ b/src/Umbraco.Core/Notifications/CancelableNotification.cs @@ -1,15 +1,37 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; namespace Umbraco.Cms.Core.Notifications; +/// +/// Base class for notifications that can be canceled by a notification handler. +/// +/// +/// Notification handlers can set to true or call +/// to abort the operation that triggered the notification. +/// public class CancelableNotification : StatefulNotification, ICancelableNotification { + /// + /// Initializes a new instance of the class. + /// + /// The event messages collection for adding cancellation messages. public CancelableNotification(EventMessages messages) => Messages = messages; + /// + /// Gets the event messages collection associated with this notification. + /// public EventMessages Messages { get; } + /// public bool Cancel { get; set; } + /// + /// Cancels the operation and adds a cancellation message to the event messages collection. + /// + /// The message explaining why the operation was canceled. public void CancelOperation(EventMessage cancellationMessage) { Cancel = true; diff --git a/src/Umbraco.Core/Notifications/CancelableObjectNotification.cs b/src/Umbraco.Core/Notifications/CancelableObjectNotification.cs index be15626eb035..22e4c367f2db 100644 --- a/src/Umbraco.Core/Notifications/CancelableObjectNotification.cs +++ b/src/Umbraco.Core/Notifications/CancelableObjectNotification.cs @@ -5,16 +5,35 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for cancelable notifications that carry a target object. +/// +/// The type of the target object associated with this notification. +/// +/// This class combines the functionality of and +/// , allowing handlers to both access the target object +/// and cancel the operation if needed. +/// public abstract class CancelableObjectNotification : ObjectNotification, ICancelableNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The target object associated with this notification. + /// The event messages collection. protected CancelableObjectNotification(T target, EventMessages messages) : base(target, messages) { } + /// public bool Cancel { get; set; } + /// + /// Cancels the operation and adds a cancellation message to the event messages collection. + /// + /// The message explaining why the operation was canceled. public void CancelOperation(EventMessage cancelationMessage) { Cancel = true; diff --git a/src/Umbraco.Core/Notifications/ContentCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/ContentCacheRefresherNotification.cs index b9a6b0c83f36..f48178eea126 100644 --- a/src/Umbraco.Core/Notifications/ContentCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentCacheRefresherNotification.cs @@ -1,21 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; /// -/// A notification that is used to trigger the Content Cache Refresher. +/// Notification that triggers the content cache refresher. /// +/// +/// This notification is used to synchronize content cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class ContentCacheRefresherNotification : CacheRefresherNotification { /// - /// Initializes a new instance of the + /// Initializes a new instance of the class. /// - /// - /// The refresher payload. - /// - /// - /// Type of the cache refresher message, - /// + /// The payload containing information about the content to refresh. + /// The type of cache refresh operation. public ContentCacheRefresherNotification(object messageObject, MessageType messageType) : base( messageObject, diff --git a/src/Umbraco.Core/Notifications/ContentCopiedNotification.cs b/src/Umbraco.Core/Notifications/ContentCopiedNotification.cs index 21500caf39f7..cbef90b7f2e7 100644 --- a/src/Umbraco.Core/Notifications/ContentCopiedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentCopiedNotification.cs @@ -5,35 +5,38 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the Copy method is called in the API. -/// The notification is published after the content object has been copied. +/// Notification that is published after content has been copied. /// +/// +/// This notification is published by the after the content object has been copied. +/// It is not cancelable since the copy operation has already completed. +/// public sealed class ContentCopiedNotification : CopiedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The original content item that was copied. + /// The copy of the content item. + /// The ID of the new parent. + /// The key of the new parent. + /// A value indicating whether the copy is related to the original. + /// The event messages collection. public ContentCopiedNotification(IContent original, IContent copy, int parentId, Guid? parentKey, bool relateToOriginal, EventMessages messages) : base(original, copy, parentId, parentKey, relateToOriginal, messages) { } /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class. /// - /// - /// Gets the original object. - /// - /// - /// Gets the object being copied. - /// - /// - /// Gets the ID of the parent of the being copied. - /// - /// - /// Boolean indicating whether the copy was related to the orginal. - /// - /// - /// Initializes a new instance of the . - /// + /// The original content item that was copied. + /// The copy of the content item. + /// The ID of the new parent. + /// A value indicating whether the copy is related to the original. + /// The event messages collection. [Obsolete("Please use constructor that takes a parent key as well, scheduled for removal in v15")] public ContentCopiedNotification(IContent original, IContent copy, int parentId, bool relateToOriginal, EventMessages messages) : this(original, copy, parentId, null, relateToOriginal, messages) diff --git a/src/Umbraco.Core/Notifications/ContentCopyingNotification.cs b/src/Umbraco.Core/Notifications/ContentCopyingNotification.cs index a5106554ca2e..58ca033df054 100644 --- a/src/Umbraco.Core/Notifications/ContentCopyingNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentCopyingNotification.cs @@ -5,32 +5,37 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the Copy method is called in the API. -/// The notification is published after a copy object has been created and had its parentId updated and its state has been set to unpublished. +/// Notification that is published before content is copied. /// +/// +/// This notification is cancelable, allowing handlers to prevent the copy operation. +/// The notification is published by the after a copy object +/// has been created and its parentId updated and state set to unpublished, but before it is persisted. +/// public sealed class ContentCopyingNotification : CopyingNotification { + /// + /// Initializes a new instance of the class. + /// + /// The original content item being copied. + /// The copy of the content item. + /// The ID of the new parent. + /// The key of the new parent. + /// The event messages collection. public ContentCopyingNotification(IContent original, IContent copy, int parentId, Guid? parentKey, EventMessages messages) : base(original, copy, parentId, parentKey, messages) { } /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class. /// - /// - /// Gets the original object. - /// - /// - /// Gets the object being copied. - /// - /// - /// Gets the ID of the parent of the being copied. - /// - /// - /// Initializes a new instance of the . - /// + /// The original content item being copied. + /// The copy of the content item. + /// The ID of the new parent. + /// The event messages collection. [Obsolete("Please use constructor that takes a parent key as well, scheduled for removal in v15")] public ContentCopyingNotification(IContent original, IContent copy, int parentId, EventMessages messages) : this(original, copy, parentId, null, messages) diff --git a/src/Umbraco.Core/Notifications/ContentDeletedBlueprintNotification.cs b/src/Umbraco.Core/Notifications/ContentDeletedBlueprintNotification.cs index 3d9a19177f91..9101dd585bf8 100644 --- a/src/Umbraco.Core/Notifications/ContentDeletedBlueprintNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentDeletedBlueprintNotification.cs @@ -5,24 +5,38 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the DeletedBlueprint method is called in the API. +/// A notification that is used to trigger the IContentService when the DeletedBlueprint method is called in the API. /// public sealed class ContentDeletedBlueprintNotification : EnumerableObjectNotification { + /// + /// Initializes a new instance of the class + /// with a single blueprint. + /// + /// The content blueprint that was deleted. + /// The event messages collection. public ContentDeletedBlueprintNotification(IContent target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple blueprints. + /// + /// The content blueprints that were deleted. + /// The event messages collection. public ContentDeletedBlueprintNotification(IEnumerable target, EventMessages messages) : base( target, messages) { } + /// - /// The collection of deleted blueprint IContent. + /// The collection of deleted blueprint IContent. /// public IEnumerable DeletedBlueprints => Target; } diff --git a/src/Umbraco.Core/Notifications/ContentDeletedNotification.cs b/src/Umbraco.Core/Notifications/ContentDeletedNotification.cs index 5bb88386177f..c3e4e0fc0c5e 100644 --- a/src/Umbraco.Core/Notifications/ContentDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentDeletedNotification.cs @@ -5,11 +5,21 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the Delete and EmptyRecycleBin methods are called in the API. +/// Notification that is published after content has been deleted. /// +/// +/// This notification is published by the when Delete or EmptyRecycleBin methods complete. +/// It is not cancelable since the delete operation has already completed. +/// public sealed class ContentDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class with a single content item. + /// + /// The content item that was deleted. + /// The event messages collection. public ContentDeletedNotification(IContent target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentDeletingNotification.cs b/src/Umbraco.Core/Notifications/ContentDeletingNotification.cs index aa929e48d1fa..85c0b0767050 100644 --- a/src/Umbraco.Core/Notifications/ContentDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentDeletingNotification.cs @@ -5,16 +5,31 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the DeleteContentOfType, Delete and EmptyRecycleBin methods are called in the API. +/// Notification that is published before content is deleted. /// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation. +/// The notification is published by the when DeleteContentOfType, Delete, or EmptyRecycleBin methods are called. +/// public sealed class ContentDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class with a single content item. + /// + /// The content item being deleted. + /// The event messages collection. public ContentDeletingNotification(IContent target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple content items. + /// + /// The collection of content items being deleted. + /// The event messages collection. public ContentDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentEmptiedRecycleBinNotification.cs b/src/Umbraco.Core/Notifications/ContentEmptiedRecycleBinNotification.cs index 6398d5d9c349..402b4f2f27bd 100644 --- a/src/Umbraco.Core/Notifications/ContentEmptiedRecycleBinNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentEmptiedRecycleBinNotification.cs @@ -5,20 +5,21 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the EmptyRecycleBin method is called in the API, after the RecycleBin has been deleted. +/// Notification that is published after the content recycle bin has been emptied. /// +/// +/// This notification is published by the after the recycle bin has been emptied. +/// It is not cancelable since the operation has already completed. +/// public sealed class ContentEmptiedRecycleBinNotification : EmptiedRecycleBinNotification { /// - /// Initializes a new instance of the + /// Initializes a new instance of the class. /// - /// - /// The collection of deleted IContent object. - /// - /// - /// Initializes a new instance of the . - /// + /// The collection of content items that were permanently deleted. + /// The event messages collection. public ContentEmptiedRecycleBinNotification(IEnumerable deletedEntities, EventMessages messages) : base( deletedEntities, messages) diff --git a/src/Umbraco.Core/Notifications/ContentEmptyingRecycleBinNotification.cs b/src/Umbraco.Core/Notifications/ContentEmptyingRecycleBinNotification.cs index 370b027c27d2..f9be0a37947a 100644 --- a/src/Umbraco.Core/Notifications/ContentEmptyingRecycleBinNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentEmptyingRecycleBinNotification.cs @@ -5,20 +5,21 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the EmptyRecycleBin method is called in the API. +/// Notification that is published before the content recycle bin is emptied. /// +/// +/// This notification is cancelable, allowing handlers to prevent the empty recycle bin operation. +/// The notification is published by the when EmptyRecycleBin is called. +/// public sealed class ContentEmptyingRecycleBinNotification : EmptyingRecycleBinNotification { /// - /// Initializes a new instance of the + /// Initializes a new instance of the class. /// - /// - /// The collection of IContent objects being deleted. - /// - /// - /// Initializes a new instance of the . - /// + /// The collection of content items being permanently deleted. + /// The event messages collection. public ContentEmptyingRecycleBinNotification(IEnumerable? deletedEntities, EventMessages messages) : base( deletedEntities, messages) diff --git a/src/Umbraco.Core/Notifications/ContentMovedNotification.cs b/src/Umbraco.Core/Notifications/ContentMovedNotification.cs index 01690155c30c..eb1dd90cae08 100644 --- a/src/Umbraco.Core/Notifications/ContentMovedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentMovedNotification.cs @@ -7,17 +7,35 @@ namespace Umbraco.Cms.Core.Notifications; /// -/// A notification that is used to trigger the IContentService when the Move method is called in the API. -/// The notification is published and called after the content object has been moved. -/// NOTE: If the target parent is the Recycle bin, this notification is never published. Try the instead. +/// Notification that is published after content has been moved. /// +/// +/// +/// This notification is published by the after content has been moved. +/// It is not cancelable since the move operation has already completed. +/// +/// +/// NOTE: If the target parent is the recycle bin, this notification is never published. +/// Use instead. +/// +/// public sealed class ContentMovedNotification : MovedNotification { + /// + /// Initializes a new instance of the class with a single content item. + /// + /// The move information for the content item that was moved. + /// The event messages collection. public ContentMovedNotification(MoveEventInfo target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple content items. + /// + /// The collection of move information for content items that were moved. + /// The event messages collection. public ContentMovedNotification(IEnumerable> target, EventMessages messages) : base( target, diff --git a/src/Umbraco.Core/Notifications/ContentMovedToRecycleBinNotification.cs b/src/Umbraco.Core/Notifications/ContentMovedToRecycleBinNotification.cs index 3c71d7bbed2f..138b2b3a3a44 100644 --- a/src/Umbraco.Core/Notifications/ContentMovedToRecycleBinNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentMovedToRecycleBinNotification.cs @@ -5,12 +5,21 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the MoveToRecycleBin method is called in the API. -/// Is published after the content has been moved to the Recycle Bin. +/// Notification that is published after content has been moved to the recycle bin. /// +/// +/// This notification is published by the after content has been moved to the recycle bin. +/// It is not cancelable since the operation has already completed. +/// public sealed class ContentMovedToRecycleBinNotification : MovedToRecycleBinNotification { + /// + /// Initializes a new instance of the class with a single content item. + /// + /// The move to recycle bin information for the content item that was moved. + /// The event messages collection. public ContentMovedToRecycleBinNotification(MoveToRecycleBinEventInfo target, EventMessages messages) : base( target, @@ -18,6 +27,11 @@ public ContentMovedToRecycleBinNotification(MoveToRecycleBinEventInfo { } + /// + /// Initializes a new instance of the class with multiple content items. + /// + /// The collection of move to recycle bin information for content items that were moved. + /// The event messages collection. public ContentMovedToRecycleBinNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentMovingNotification.cs b/src/Umbraco.Core/Notifications/ContentMovingNotification.cs index 9a84e258533d..7f6fadefc920 100644 --- a/src/Umbraco.Core/Notifications/ContentMovingNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentMovingNotification.cs @@ -7,17 +7,35 @@ namespace Umbraco.Cms.Core.Notifications; /// -/// A notification that is used to trigger the IContentService when the Move method is called in the API. -/// Called while content is moving, but before it has been moved. Cancel the operation to prevent the movement. -/// NOTE: If the target parent is the Recycle bin, this notification is never published. Try the instead. +/// Notification that is published before content is moved. /// +/// +/// +/// This notification is cancelable, allowing handlers to prevent the move operation. +/// The notification is published by the before content is moved. +/// +/// +/// NOTE: If the target parent is the recycle bin, this notification is never published. +/// Use instead. +/// +/// public sealed class ContentMovingNotification : MovingNotification { + /// + /// Initializes a new instance of the class with a single content item. + /// + /// The move information for the content item being moved. + /// The event messages collection. public ContentMovingNotification(MoveEventInfo target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple content items. + /// + /// The collection of move information for content items being moved. + /// The event messages collection. public ContentMovingNotification(IEnumerable> target, EventMessages messages) : base( target, diff --git a/src/Umbraco.Core/Notifications/ContentMovingToRecycleBinNotification.cs b/src/Umbraco.Core/Notifications/ContentMovingToRecycleBinNotification.cs index 398b570b6be3..12e74eb5c723 100644 --- a/src/Umbraco.Core/Notifications/ContentMovingToRecycleBinNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentMovingToRecycleBinNotification.cs @@ -5,11 +5,21 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the MoveToRecycleBin method is called in the API. +/// Notification that is published before content is moved to the recycle bin. /// +/// +/// This notification is cancelable, allowing handlers to prevent the move to recycle bin operation. +/// The notification is published by the when MoveToRecycleBin is called. +/// public sealed class ContentMovingToRecycleBinNotification : MovingToRecycleBinNotification { + /// + /// Initializes a new instance of the class with a single content item. + /// + /// The move to recycle bin information for the content item being moved. + /// The event messages collection. public ContentMovingToRecycleBinNotification(MoveToRecycleBinEventInfo target, EventMessages messages) : base( target, @@ -17,6 +27,11 @@ public ContentMovingToRecycleBinNotification(MoveToRecycleBinEventInfo { } + /// + /// Initializes a new instance of the class with multiple content items. + /// + /// The collection of move to recycle bin information for content items being moved. + /// The event messages collection. public ContentMovingToRecycleBinNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentNotificationExtensions.cs b/src/Umbraco.Core/Notifications/ContentNotificationExtensions.cs index a7449f24cc0b..2b7d966c25a8 100644 --- a/src/Umbraco.Core/Notifications/ContentNotificationExtensions.cs +++ b/src/Umbraco.Core/Notifications/ContentNotificationExtensions.cs @@ -5,6 +5,10 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Provides extension methods for content-related notifications to help determine +/// culture-specific save and publish states. +/// public static class ContentNotificationExtensions { /// @@ -57,6 +61,12 @@ public static bool HasUnpublishedCulture(this ContentPublishedNotification notif public static bool HasUnpublishedCulture(this ContentUnpublishedNotification notification, IContent content, string culture) => HasUnpublishedCulture(content, culture); + /// + /// Determines whether a culture is being published for the specified content. + /// + /// The content item to check. + /// The culture code to check. + /// true if the culture is being published; otherwise, false. public static bool IsPublishingCulture(IContent content, string culture) => (content.PublishCultureInfos?.TryGetValue(culture, out ContentCultureInfos cultureInfo) ?? false) && cultureInfo.IsDirty(); @@ -64,6 +74,12 @@ public static bool IsPublishingCulture(IContent content, string culture) private static bool IsUnpublishingCulture(IContent content, string culture) => content.IsPropertyDirty(ContentBase.ChangeTrackingPrefix.UnpublishedCulture + culture); + /// + /// Determines whether a culture has been unpublished for the specified content. + /// + /// The content item to check. + /// The culture code to check. + /// true if the culture has been unpublished; otherwise, false. public static bool HasUnpublishedCulture(IContent content, string culture) => content.WasPropertyDirty(ContentBase.ChangeTrackingPrefix.UnpublishedCulture + culture); } diff --git a/src/Umbraco.Core/Notifications/ContentPublishedNotification.cs b/src/Umbraco.Core/Notifications/ContentPublishedNotification.cs index f242ef20a95a..7787c782836f 100644 --- a/src/Umbraco.Core/Notifications/ContentPublishedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentPublishedNotification.cs @@ -7,28 +7,50 @@ namespace Umbraco.Cms.Core.Notifications; /// -/// A notification that is used to trigger the IContentService when the Publish method is called in the API and after data has been published. -/// Called after content has been published. +/// Notification that is published after content has been published. /// +/// +/// This notification is published by the after content has been made publicly available. +/// It is not cancelable since the publish operation has already completed. +/// public sealed class ContentPublishedNotification : EnumerableObjectNotification { + /// + /// Initializes a new instance of the class with a single content item. + /// + /// The content item that was published. + /// The event messages collection. public ContentPublishedNotification(IContent target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple content items. + /// + /// The collection of content items that were published. + /// The event messages collection. public ContentPublishedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple content items and descendant flag. + /// + /// The collection of content items that were published. + /// The event messages collection. + /// A value indicating whether descendants were included in the publish operation. public ContentPublishedNotification(IEnumerable target, EventMessages messages, bool includeDescendants) : base(target, messages) => IncludeDescendants = includeDescendants; /// - /// Gets a enumeration of which are being published. + /// Gets the collection of items that were published. /// public IEnumerable PublishedEntities => Target; + /// + /// Gets a value indicating whether descendants were included in the publish operation. + /// public bool IncludeDescendants { get; } } diff --git a/src/Umbraco.Core/Notifications/ContentPublishingNotification.cs b/src/Umbraco.Core/Notifications/ContentPublishingNotification.cs index ddaf019168b6..9c62637a10f1 100644 --- a/src/Umbraco.Core/Notifications/ContentPublishingNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentPublishingNotification.cs @@ -7,23 +7,36 @@ namespace Umbraco.Cms.Core.Notifications; /// -/// A notification that is used to trigger the IContentService when the Publishing method is called in the API. -/// Called while publishing content but before content has been published. Cancel the operation to prevent the publish. +/// Notification that is published before content is published. /// +/// +/// This notification is cancelable, allowing handlers to prevent the publish operation. +/// The notification is published by the before content is made publicly available. +/// public sealed class ContentPublishingNotification : CancelableEnumerableObjectNotification { + /// + /// Initializes a new instance of the class with a single content item. + /// + /// The content item being published. + /// The event messages collection. public ContentPublishingNotification(IContent target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple content items. + /// + /// The collection of content items being published. + /// The event messages collection. public ContentPublishingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } /// - /// Gets a enumeration of which are being published. + /// Gets the collection of items being published. /// public IEnumerable PublishedEntities => Target; } diff --git a/src/Umbraco.Core/Notifications/ContentRefreshNotification.cs b/src/Umbraco.Core/Notifications/ContentRefreshNotification.cs index f2d18fbba15e..95f696f24994 100644 --- a/src/Umbraco.Core/Notifications/ContentRefreshNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentRefreshNotification.cs @@ -1,13 +1,29 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using System.ComponentModel; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when content needs to be refreshed in the cache. +/// +/// +/// This notification is used internally for cache synchronization purposes. +/// For normal content operations, use or +/// instead. +/// [Obsolete("This is only used for the internal cache and will change, use saved notifications instead")] [EditorBrowsable(EditorBrowsableState.Never)] public class ContentRefreshNotification : EntityRefreshNotification { + /// + /// Initializes a new instance of the class. + /// + /// The content item to refresh. + /// The event messages collection. public ContentRefreshNotification(IContent target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentRolledBackNotification.cs b/src/Umbraco.Core/Notifications/ContentRolledBackNotification.cs index db2cf1d1328c..6cd49055b122 100644 --- a/src/Umbraco.Core/Notifications/ContentRolledBackNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentRolledBackNotification.cs @@ -5,11 +5,21 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the Rollback method is called in the API, after the content has been rolled back. +/// Notification that is published after content has been rolled back to a previous version. /// +/// +/// This notification is published by the after the content has been reverted. +/// It is not cancelable since the rollback operation has already completed. +/// public sealed class ContentRolledBackNotification : RolledBackNotification { + /// + /// Initializes a new instance of the class. + /// + /// The content item that was rolled back. + /// The event messages collection. public ContentRolledBackNotification(IContent target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentRollingBackNotification.cs b/src/Umbraco.Core/Notifications/ContentRollingBackNotification.cs index 650de660db68..1065c50f55f9 100644 --- a/src/Umbraco.Core/Notifications/ContentRollingBackNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentRollingBackNotification.cs @@ -5,11 +5,21 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the Rollback method is called in the API. +/// Notification that is published before content is rolled back to a previous version. /// +/// +/// This notification is cancelable, allowing handlers to prevent the rollback operation. +/// The notification is published by the before the content is reverted. +/// public sealed class ContentRollingBackNotification : RollingBackNotification { + /// + /// Initializes a new instance of the class. + /// + /// The content item being rolled back. + /// The event messages collection. public ContentRollingBackNotification(IContent target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentSavedBlueprintNotification.cs b/src/Umbraco.Core/Notifications/ContentSavedBlueprintNotification.cs index 897065a53227..6ee34ee61ce5 100644 --- a/src/Umbraco.Core/Notifications/ContentSavedBlueprintNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentSavedBlueprintNotification.cs @@ -7,15 +7,27 @@ namespace Umbraco.Cms.Core.Notifications; /// -/// A notification that is used to trigger the IContentService when the SavedBlueprint method is called in the API. +/// A notification that is used to trigger the IContentService when the SavedBlueprint method is called in the API. /// public sealed class ContentSavedBlueprintNotification : ObjectNotification { + /// + /// Initializes a new instance of the class. + /// + /// The content blueprint that was saved. + /// The event messages collection. public ContentSavedBlueprintNotification(IContent target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with information about the original content. + /// + /// The content blueprint that was saved. + /// The original content from which the blueprint was created, if any. + /// The event messages collection. public ContentSavedBlueprintNotification(IContent target, IContent? createdFromContent, EventMessages messages) : base(target, messages) { @@ -23,13 +35,12 @@ public ContentSavedBlueprintNotification(IContent target, IContent? createdFromC } /// - /// Getting the saved blueprint object. + /// Getting the saved blueprint object. /// public IContent SavedBlueprint => Target; /// - /// Getting the saved blueprint object. + /// Gets the original content from which the blueprint was created, if any. /// public IContent? CreatedFromContent { get; } - } diff --git a/src/Umbraco.Core/Notifications/ContentSavedNotification.cs b/src/Umbraco.Core/Notifications/ContentSavedNotification.cs index 886ee44f673e..485dad6798e3 100644 --- a/src/Umbraco.Core/Notifications/ContentSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentSavedNotification.cs @@ -5,21 +5,31 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the Save method is called in the API and after the data has been persisted. +/// Notification that is published after content has been saved. /// +/// +/// This notification is published by the after content has been persisted. +/// It is not cancelable since the save operation has already completed. +/// public sealed class ContentSavedNotification : SavedNotification { /// - /// Initializes a new instance of the + /// Initializes a new instance of the class with a single content item. /// + /// The content item that was saved. + /// The event messages collection. public ContentSavedNotification(IContent target, EventMessages messages) : base(target, messages) { } + /// - /// Gets a enumeration of . + /// Initializes a new instance of the class with multiple content items. /// + /// The collection of content items that were saved. + /// The event messages collection. public ContentSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentSavingNotification.cs b/src/Umbraco.Core/Notifications/ContentSavingNotification.cs index 675c2537ec89..17e517348b11 100644 --- a/src/Umbraco.Core/Notifications/ContentSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentSavingNotification.cs @@ -5,21 +5,31 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the Save method is called in the API. +/// Notification that is published before content is saved. /// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation. +/// The notification is published by the before content is persisted. +/// public sealed class ContentSavingNotification : SavingNotification { /// - /// Initializes a new instance of the + /// Initializes a new instance of the class with a single content item. /// + /// The content item being saved. + /// The event messages collection. public ContentSavingNotification(IContent target, EventMessages messages) : base(target, messages) { } + /// - /// Gets a enumeration of . + /// Initializes a new instance of the class with multiple content items. /// + /// The collection of content items being saved. + /// The event messages collection. public ContentSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentScaffoldedNotification.cs b/src/Umbraco.Core/Notifications/ContentScaffoldedNotification.cs index 47eda5468df2..6fe51eed5535 100644 --- a/src/Umbraco.Core/Notifications/ContentScaffoldedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentScaffoldedNotification.cs @@ -7,10 +7,17 @@ namespace Umbraco.Cms.Core.Notifications; /// -/// Notification that is send out when a Content item has been scaffolded from an original item and basic cleaning has been performed +/// Notification that is sent out when a Content item has been scaffolded from an original item and basic cleaning has been performed. /// public sealed class ContentScaffoldedNotification : ScaffoldedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The original content being copied from. + /// The scaffold (copy) being created. + /// The ID of the parent under which the scaffold will be created. + /// The event messages collection. public ContentScaffoldedNotification(IContent original, IContent scaffold, int parentId, EventMessages messages) : base(original, scaffold, parentId, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentSendingToPublishNotification.cs b/src/Umbraco.Core/Notifications/ContentSendingToPublishNotification.cs index 3fca73952191..f8325fcf5255 100644 --- a/src/Umbraco.Core/Notifications/ContentSendingToPublishNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentSendingToPublishNotification.cs @@ -5,17 +5,28 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the SendToPublication method is called in the API. +/// A notification that is used to trigger the IContentService when the SendToPublication method is called in the API. /// +/// +/// This notification is cancelable, allowing handlers to prevent the send to publish operation +/// by setting to true. +/// public sealed class ContentSendingToPublishNotification : CancelableObjectNotification { + /// + /// Initializes a new instance of the class. + /// + /// The content being sent to publish. + /// The event messages collection. public ContentSendingToPublishNotification(IContent target, EventMessages messages) : base(target, messages) { } + /// - /// Getting the IContent object being sent to publish. + /// Getting the IContent object being sent to publish. /// public IContent Entity => Target; } diff --git a/src/Umbraco.Core/Notifications/ContentSentToPublishNotification.cs b/src/Umbraco.Core/Notifications/ContentSentToPublishNotification.cs index 22131d06e1c9..c5b816f7d250 100644 --- a/src/Umbraco.Core/Notifications/ContentSentToPublishNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentSentToPublishNotification.cs @@ -5,17 +5,24 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the SendToPublication method is called in the API, after the entity has been sent to publication. +/// A notification that is used to trigger the IContentService when the SendToPublication method is called in the API, after the entity has been sent to publication. /// public sealed class ContentSentToPublishNotification : ObjectNotification { + /// + /// Initializes a new instance of the class. + /// + /// The content that was sent to publish. + /// The event messages collection. public ContentSentToPublishNotification(IContent target, EventMessages messages) : base(target, messages) { } + /// - /// Getting the IContent object being sent to publish. + /// Getting the IContent object being sent to publish. /// public IContent Entity => Target; } diff --git a/src/Umbraco.Core/Notifications/ContentSortedNotification.cs b/src/Umbraco.Core/Notifications/ContentSortedNotification.cs index 3473f816fbfe..3fd9e4bb8a36 100644 --- a/src/Umbraco.Core/Notifications/ContentSortedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentSortedNotification.cs @@ -7,10 +7,15 @@ namespace Umbraco.Cms.Core.Notifications; /// -/// Called after content has been sorted. +/// Called after content has been sorted. /// public sealed class ContentSortedNotification : SortedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The content items that were sorted. + /// The event messages collection. public ContentSortedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentSortingNotification.cs b/src/Umbraco.Core/Notifications/ContentSortingNotification.cs index 4570b6848900..3e9d524557af 100644 --- a/src/Umbraco.Core/Notifications/ContentSortingNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentSortingNotification.cs @@ -7,10 +7,19 @@ namespace Umbraco.Cms.Core.Notifications; /// -/// Called while content is sorting, but before content has been sorted. Cancel the operation to cancel the sorting. +/// Called while content is sorting, but before content has been sorted. Cancel the operation to cancel the sorting. /// +/// +/// This notification is cancelable, allowing handlers to prevent the sort operation +/// by setting to true. +/// public sealed class ContentSortingNotification : SortingNotification { + /// + /// Initializes a new instance of the class. + /// + /// The content items being sorted. + /// The event messages collection. public ContentSortingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentTreeChangeNotification.cs b/src/Umbraco.Core/Notifications/ContentTreeChangeNotification.cs index 61659bd7dc2e..88c4aa53ea9a 100644 --- a/src/Umbraco.Core/Notifications/ContentTreeChangeNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentTreeChangeNotification.cs @@ -1,22 +1,51 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services.Changes; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when changes occur in the content tree structure. +/// +/// +/// This notification is published when content items are added, removed, moved, or have their +/// structure modified in the content tree. It is used for cache invalidation and tree synchronization. +/// public class ContentTreeChangeNotification : TreeChangeNotification { + /// + /// Initializes a new instance of the class + /// with a single tree change. + /// + /// The tree change that occurred. + /// The event messages collection. public ContentTreeChangeNotification(TreeChange target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple tree changes. + /// + /// The collection of tree changes that occurred. + /// The event messages collection. public ContentTreeChangeNotification(IEnumerable> target, EventMessages messages) : base( target, messages) { } + /// + /// Initializes a new instance of the class + /// for multiple content items with the same change type. + /// + /// The content items that changed. + /// The type of changes that occurred. + /// The event messages collection. public ContentTreeChangeNotification( IEnumerable target, TreeChangeTypes changeTypes, @@ -25,6 +54,13 @@ public ContentTreeChangeNotification( { } + /// + /// Initializes a new instance of the class + /// for a single content item. + /// + /// The content item that changed. + /// The type of changes that occurred. + /// The event messages collection. public ContentTreeChangeNotification( IContent target, TreeChangeTypes changeTypes, @@ -33,6 +69,15 @@ public ContentTreeChangeNotification( { } + /// + /// Initializes a new instance of the class + /// for a single content item with culture-specific publishing information. + /// + /// The content item that changed. + /// The type of changes that occurred. + /// The cultures that were published, if any. + /// The cultures that were unpublished, if any. + /// The event messages collection. public ContentTreeChangeNotification( IContent target, TreeChangeTypes changeTypes, diff --git a/src/Umbraco.Core/Notifications/ContentTypeCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/ContentTypeCacheRefresherNotification.cs index d4ced3496d58..65adaca43d09 100644 --- a/src/Umbraco.Core/Notifications/ContentTypeCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentTypeCacheRefresherNotification.cs @@ -1,9 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when content type cache needs to be refreshed. +/// +/// +/// This notification is used to synchronize content type cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class ContentTypeCacheRefresherNotification : CacheRefresherNotification { + /// + /// Initializes a new instance of the class. + /// + /// The payload containing information about the content type to refresh. + /// The type of cache refresh operation. public ContentTypeCacheRefresherNotification(object messageObject, MessageType messageType) : base( messageObject, diff --git a/src/Umbraco.Core/Notifications/ContentTypeChangeNotification.cs b/src/Umbraco.Core/Notifications/ContentTypeChangeNotification.cs index 606a6fb34e32..7603f1fae51b 100644 --- a/src/Umbraco.Core/Notifications/ContentTypeChangeNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentTypeChangeNotification.cs @@ -1,12 +1,29 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services.Changes; namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications related to content type changes. +/// +/// The type of content type composition. +/// +/// This notification is published when content types are modified, allowing handlers +/// to react to schema changes for cache invalidation or other purposes. +/// public abstract class ContentTypeChangeNotification : EnumerableObjectNotification> where T : class, IContentTypeComposition { + /// + /// Initializes a new instance of the class + /// with a single content type change. + /// + /// The content type change that occurred. + /// The event messages collection. protected ContentTypeChangeNotification(ContentTypeChange target, EventMessages messages) : base( target, @@ -14,11 +31,20 @@ protected ContentTypeChangeNotification(ContentTypeChange target, EventMessag { } + /// + /// Initializes a new instance of the class + /// with multiple content type changes. + /// + /// The collection of content type changes that occurred. + /// The event messages collection. protected ContentTypeChangeNotification(IEnumerable> target, EventMessages messages) : base( target, messages) { } + /// + /// Gets the content type changes that occurred. + /// public IEnumerable> Changes => Target; } diff --git a/src/Umbraco.Core/Notifications/ContentTypeChangedNotification.cs b/src/Umbraco.Core/Notifications/ContentTypeChangedNotification.cs index f9655e32cd4d..80994c705bac 100644 --- a/src/Umbraco.Core/Notifications/ContentTypeChangedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentTypeChangedNotification.cs @@ -1,14 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services.Changes; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is published when a ContentType is saved or deleted, after the transaction has completed. -/// This is mainly used for caching purposes, and generally not recommended. Use and instead. +/// A notification that is published when a ContentType is saved or deleted, after the transaction has completed. +/// This is mainly used for caching purposes, and generally not recommended. Use and instead. /// public class ContentTypeChangedNotification : ContentTypeChangeNotification { + /// + /// Initializes a new instance of the class + /// with a single content type change. + /// + /// The content type change that occurred. + /// The event messages collection. public ContentTypeChangedNotification(ContentTypeChange target, EventMessages messages) : base( target, @@ -16,6 +26,12 @@ public ContentTypeChangedNotification(ContentTypeChange target, Ev { } + /// + /// Initializes a new instance of the class + /// with multiple content type changes. + /// + /// The content type changes that occurred. + /// The event messages collection. public ContentTypeChangedNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentTypeDeletedNotification.cs b/src/Umbraco.Core/Notifications/ContentTypeDeletedNotification.cs index cdf322537c26..ff512d0488e1 100644 --- a/src/Umbraco.Core/Notifications/ContentTypeDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentTypeDeletedNotification.cs @@ -1,17 +1,35 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the ContentTypeService when the Delete method is called in the API, after the entities have been deleted. +/// Notification that is published after a content type has been deleted. /// +/// +/// This notification is published by the after the content type has been removed. +/// It is not cancelable since the delete operation has already completed. +/// public class ContentTypeDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class with a single content type. + /// + /// The content type that was deleted. + /// The event messages collection. public ContentTypeDeletedNotification(IContentType target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple content types. + /// + /// The collection of content types that were deleted. + /// The event messages collection. public ContentTypeDeletedNotification(IEnumerable target, EventMessages messages) : base( target, diff --git a/src/Umbraco.Core/Notifications/ContentTypeDeletingNotification.cs b/src/Umbraco.Core/Notifications/ContentTypeDeletingNotification.cs index 17c6b081342a..fd8af5fe3d69 100644 --- a/src/Umbraco.Core/Notifications/ContentTypeDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentTypeDeletingNotification.cs @@ -1,17 +1,35 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the ContentTypeService when the Delete method is called in the API. +/// Notification that is published before a content type is deleted. /// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation. +/// The notification is published by the before the content type is removed. +/// public class ContentTypeDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class with a single content type. + /// + /// The content type being deleted. + /// The event messages collection. public ContentTypeDeletingNotification(IContentType target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple content types. + /// + /// The collection of content types being deleted. + /// The event messages collection. public ContentTypeDeletingNotification(IEnumerable target, EventMessages messages) : base( target, diff --git a/src/Umbraco.Core/Notifications/ContentTypeMovedNotification.cs b/src/Umbraco.Core/Notifications/ContentTypeMovedNotification.cs index a90a2ffbd3ca..8f82371de993 100644 --- a/src/Umbraco.Core/Notifications/ContentTypeMovedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentTypeMovedNotification.cs @@ -1,12 +1,22 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the ContentTypeService when the Move method is called in the API, after the entities have been moved. +/// A notification that is used to trigger the ContentTypeService when the Move method is called in the API, after the entities have been moved. /// public class ContentTypeMovedNotification : MovedNotification { + /// + /// Initializes a new instance of the class + /// with a single move operation. + /// + /// The move event information for the content type that was moved. + /// The event messages collection. public ContentTypeMovedNotification(MoveEventInfo target, EventMessages messages) : base( target, @@ -14,6 +24,12 @@ public ContentTypeMovedNotification(MoveEventInfo target, EventMes { } + /// + /// Initializes a new instance of the class + /// with multiple move operations. + /// + /// The move event information for the content types that were moved. + /// The event messages collection. public ContentTypeMovedNotification(IEnumerable> target, EventMessages messages) : base( target, messages) diff --git a/src/Umbraco.Core/Notifications/ContentTypeMovingNotification.cs b/src/Umbraco.Core/Notifications/ContentTypeMovingNotification.cs index df72a4debf72..0f5b90738814 100644 --- a/src/Umbraco.Core/Notifications/ContentTypeMovingNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentTypeMovingNotification.cs @@ -1,12 +1,26 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the ContentTypeService when the Move method is called in the API. +/// A notification that is used to trigger the ContentTypeService when the Move method is called in the API. /// +/// +/// This notification is cancelable, allowing handlers to prevent the move operation +/// by setting to true. +/// public class ContentTypeMovingNotification : MovingNotification { + /// + /// Initializes a new instance of the class + /// with a single move operation. + /// + /// The move event information for the content type being moved. + /// The event messages collection. public ContentTypeMovingNotification(MoveEventInfo target, EventMessages messages) : base( target, @@ -14,6 +28,12 @@ public ContentTypeMovingNotification(MoveEventInfo target, EventMe { } + /// + /// Initializes a new instance of the class + /// with multiple move operations. + /// + /// The move event information for the content types being moved. + /// The event messages collection. public ContentTypeMovingNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentTypeRefreshNotification.cs b/src/Umbraco.Core/Notifications/ContentTypeRefreshNotification.cs index 108e72aecc00..174841af323f 100644 --- a/src/Umbraco.Core/Notifications/ContentTypeRefreshNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentTypeRefreshNotification.cs @@ -1,12 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services.Changes; namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications related to content type cache refresh operations. +/// +/// The type of content type composition. +/// +/// This notification is used internally for cache synchronization when content types are modified. +/// public abstract class ContentTypeRefreshNotification : ContentTypeChangeNotification where T : class, IContentTypeComposition { + /// + /// Initializes a new instance of the class + /// with a single content type change. + /// + /// The content type change that occurred. + /// The event messages collection. protected ContentTypeRefreshNotification(ContentTypeChange target, EventMessages messages) : base( target, @@ -14,6 +30,12 @@ protected ContentTypeRefreshNotification(ContentTypeChange target, EventMessa { } + /// + /// Initializes a new instance of the class + /// with multiple content type changes. + /// + /// The collection of content type changes that occurred. + /// The event messages collection. protected ContentTypeRefreshNotification(IEnumerable> target, EventMessages messages) : base( target, messages) diff --git a/src/Umbraco.Core/Notifications/ContentTypeRefreshedNotification.cs b/src/Umbraco.Core/Notifications/ContentTypeRefreshedNotification.cs index b49eef287656..92ca454438e6 100644 --- a/src/Umbraco.Core/Notifications/ContentTypeRefreshedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentTypeRefreshedNotification.cs @@ -1,3 +1,6 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using System.ComponentModel; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; @@ -5,15 +8,34 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when content types have been refreshed in the cache. +/// +/// +/// This notification is used internally for cache synchronization purposes. +/// For normal content type operations, use instead. +/// [Obsolete("This is only used for the internal cache and will change, use saved notifications instead")] [EditorBrowsable(EditorBrowsableState.Never)] public class ContentTypeRefreshedNotification : ContentTypeRefreshNotification { + /// + /// Initializes a new instance of the class + /// with a single content type change. + /// + /// The content type change that occurred. + /// The event messages collection. public ContentTypeRefreshedNotification(ContentTypeChange target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple content type changes. + /// + /// The collection of content type changes that occurred. + /// The event messages collection. public ContentTypeRefreshedNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentTypeSavedNotification.cs b/src/Umbraco.Core/Notifications/ContentTypeSavedNotification.cs index 11b6d43a9e86..a7241e6d37a0 100644 --- a/src/Umbraco.Core/Notifications/ContentTypeSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentTypeSavedNotification.cs @@ -1,17 +1,35 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the ContentTypeService when the Save method is called in the API, after the entities have been saved. +/// Notification that is published after a content type has been saved. /// +/// +/// This notification is published by the after the content type has been persisted. +/// It is not cancelable since the save operation has already completed. +/// public class ContentTypeSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class with a single content type. + /// + /// The content type that was saved. + /// The event messages collection. public ContentTypeSavedNotification(IContentType target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple content types. + /// + /// The collection of content types that were saved. + /// The event messages collection. public ContentTypeSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentTypeSavingNotification.cs b/src/Umbraco.Core/Notifications/ContentTypeSavingNotification.cs index c08821b55622..a81634ef3c55 100644 --- a/src/Umbraco.Core/Notifications/ContentTypeSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentTypeSavingNotification.cs @@ -1,17 +1,35 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the ContentTypeService when the Save method is called in the API. +/// Notification that is published before a content type is saved. /// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation. +/// The notification is published by the before the content type is persisted. +/// public class ContentTypeSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class with a single content type. + /// + /// The content type being saved. + /// The event messages collection. public ContentTypeSavingNotification(IContentType target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple content types. + /// + /// The collection of content types being saved. + /// The event messages collection. public ContentTypeSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ContentUnpublishedNotification.cs b/src/Umbraco.Core/Notifications/ContentUnpublishedNotification.cs index 959f8aaf02a9..6816c36eece9 100644 --- a/src/Umbraco.Core/Notifications/ContentUnpublishedNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentUnpublishedNotification.cs @@ -5,22 +5,38 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the UnPublish method is called in the API and after data has been unpublished. +/// Notification that is published after content has been unpublished. /// +/// +/// This notification is published by the after content has been removed from the public site. +/// It is not cancelable since the unpublish operation has already completed. +/// public sealed class ContentUnpublishedNotification : EnumerableObjectNotification { + /// + /// Initializes a new instance of the class with a single content item. + /// + /// The content item that was unpublished. + /// The event messages collection. public ContentUnpublishedNotification(IContent target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple content items. + /// + /// The collection of content items that were unpublished. + /// The event messages collection. public ContentUnpublishedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// - /// Gets a enumeration of which are being unpublished. + /// Gets the collection of items that were unpublished. /// public IEnumerable UnpublishedEntities => Target; } diff --git a/src/Umbraco.Core/Notifications/ContentUnpublishingNotification.cs b/src/Umbraco.Core/Notifications/ContentUnpublishingNotification.cs index da3a5b25b6f9..ca80bcf36ef6 100644 --- a/src/Umbraco.Core/Notifications/ContentUnpublishingNotification.cs +++ b/src/Umbraco.Core/Notifications/ContentUnpublishingNotification.cs @@ -5,22 +5,38 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IContentService when the UnPublishing method is called in the API. +/// Notification that is published before content is unpublished. /// +/// +/// This notification is cancelable, allowing handlers to prevent the unpublish operation. +/// The notification is published by the before content is removed from the public site. +/// public sealed class ContentUnpublishingNotification : CancelableEnumerableObjectNotification { + /// + /// Initializes a new instance of the class with a single content item. + /// + /// The content item being unpublished. + /// The event messages collection. public ContentUnpublishingNotification(IContent target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple content items. + /// + /// The collection of content items being unpublished. + /// The event messages collection. public ContentUnpublishingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// - /// Gets a enumeration of which are being unpublished. + /// Gets the collection of items being unpublished. /// public IEnumerable UnpublishedEntities => Target; } diff --git a/src/Umbraco.Core/Notifications/CopiedNotification.cs b/src/Umbraco.Core/Notifications/CopiedNotification.cs index ddb1274e106b..a958beb89caa 100644 --- a/src/Umbraco.Core/Notifications/CopiedNotification.cs +++ b/src/Umbraco.Core/Notifications/CopiedNotification.cs @@ -5,9 +5,26 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published after an entity has been copied. +/// +/// The type of entity that was copied. +/// +/// This notification is published after the copy has been persisted to the database. +/// It is not cancelable since the copy operation has already completed. +/// public abstract class CopiedNotification : ObjectNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The original entity that was copied. + /// The copy of the entity. + /// The ID of the new parent. + /// The key of the new parent. + /// A value indicating whether the copy is related to the original. + /// The event messages collection. protected CopiedNotification(T original, T copy, int parentId, Guid? parentKey, bool relateToOriginal, EventMessages messages) : base(original, messages) { @@ -17,20 +34,43 @@ protected CopiedNotification(T original, T copy, int parentId, Guid? parentKey, RelateToOriginal = relateToOriginal; } + /// + /// Initializes a new instance of the class. + /// + /// The original entity that was copied. + /// The copy of the entity. + /// The ID of the new parent. + /// A value indicating whether the copy is related to the original. + /// The event messages collection. [Obsolete("Please use constructor that takes a parent key, scheduled for removal in V15")] protected CopiedNotification(T original, T copy, int parentId, bool relateToOriginal, EventMessages messages) : this(original, copy, parentId, null, relateToOriginal, messages) { } + /// + /// Gets the original entity that was copied. + /// public T Original => Target; + /// + /// Gets the copy of the entity. + /// public T Copy { get; } + /// + /// Gets the ID of the new parent. + /// [Obsolete("Please use parent key instead, scheduled for removal in V15")] public int ParentId { get; } + /// + /// Gets the key of the new parent. + /// public Guid? ParentKey { get; } + /// + /// Gets a value indicating whether the copy is related to the original. + /// public bool RelateToOriginal { get; } } diff --git a/src/Umbraco.Core/Notifications/CopyingNotification.cs b/src/Umbraco.Core/Notifications/CopyingNotification.cs index 2320d13f2895..2904fe338dd9 100644 --- a/src/Umbraco.Core/Notifications/CopyingNotification.cs +++ b/src/Umbraco.Core/Notifications/CopyingNotification.cs @@ -5,9 +5,25 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published before an entity is copied. +/// +/// The type of entity being copied. +/// +/// This notification is cancelable, allowing handlers to prevent the copy operation. +/// The notification is published before the copy is persisted to the database. +/// public abstract class CopyingNotification : CancelableObjectNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The original entity being copied. + /// The copy of the entity. + /// The ID of the new parent. + /// The key of the new parent. + /// The event messages collection. protected CopyingNotification(T original, T copy, int parentId, Guid? parentKey, EventMessages messages) : base(original, messages) { @@ -16,18 +32,37 @@ protected CopyingNotification(T original, T copy, int parentId, Guid? parentKey, ParentKey = parentKey; } + /// + /// Initializes a new instance of the class. + /// + /// The original entity being copied. + /// The copy of the entity. + /// The ID of the new parent. + /// The event messages collection. [Obsolete("Please use constructor that takes a parent key, scheduled for removal in V15")] protected CopyingNotification(T original, T copy, int parentId, EventMessages messages) : this(original, copy, parentId, null, messages) { } + /// + /// Gets the original entity being copied. + /// public T Original => Target; + /// + /// Gets the copy of the entity. + /// public T Copy { get; } + /// + /// Gets the ID of the new parent. + /// [Obsolete("Please use parent key instead, scheduled for removal in V15")] public int ParentId { get; } + /// + /// Gets the key of the new parent. + /// public Guid? ParentKey { get; } } diff --git a/src/Umbraco.Core/Notifications/CreatedNotification.cs b/src/Umbraco.Core/Notifications/CreatedNotification.cs index 8667e4bdcc68..70d33294bcde 100644 --- a/src/Umbraco.Core/Notifications/CreatedNotification.cs +++ b/src/Umbraco.Core/Notifications/CreatedNotification.cs @@ -5,13 +5,29 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published after an entity has been created. +/// +/// The type of entity that was created. +/// +/// This notification is published after the entity has been persisted to the database. +/// It is not cancelable since the creation has already completed. +/// public abstract class CreatedNotification : ObjectNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The entity that was created. + /// The event messages collection. protected CreatedNotification(T target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the entity that was created. + /// public T CreatedEntity => Target; } diff --git a/src/Umbraco.Core/Notifications/CreatingNotification.cs b/src/Umbraco.Core/Notifications/CreatingNotification.cs index f76a3d883990..2b7537304d30 100644 --- a/src/Umbraco.Core/Notifications/CreatingNotification.cs +++ b/src/Umbraco.Core/Notifications/CreatingNotification.cs @@ -5,13 +5,29 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published before an entity is created. +/// +/// The type of entity being created. +/// +/// This notification is cancelable, allowing handlers to prevent the creation. +/// The notification is published before the entity is persisted to the database. +/// public abstract class CreatingNotification : CancelableObjectNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The entity being created. + /// The event messages collection. protected CreatingNotification(T target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the entity being created. + /// public T CreatedEntity => Target; } diff --git a/src/Umbraco.Core/Notifications/DataTypeCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/DataTypeCacheRefresherNotification.cs index 5f8b34fb221b..9aabb5009577 100644 --- a/src/Umbraco.Core/Notifications/DataTypeCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/DataTypeCacheRefresherNotification.cs @@ -1,9 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that triggers the data type cache refresher. +/// +/// +/// This notification is used to synchronize data type cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class DataTypeCacheRefresherNotification : CacheRefresherNotification { + /// + /// Initializes a new instance of the class. + /// + /// The payload containing information about the data type to refresh. + /// The type of cache refresh operation. public DataTypeCacheRefresherNotification(object messageObject, MessageType messageType) : base(messageObject, messageType) { diff --git a/src/Umbraco.Core/Notifications/DataTypeDeletedNotification.cs b/src/Umbraco.Core/Notifications/DataTypeDeletedNotification.cs index 8b7f3486acb2..80730a4dab73 100644 --- a/src/Umbraco.Core/Notifications/DataTypeDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/DataTypeDeletedNotification.cs @@ -1,12 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the DataTypeService when the Delete method is called in the API, after the IDataType objects have been deleted. +/// Notification that is published after a data type has been deleted. /// +/// +/// This notification is published by the after the data type has been removed. +/// It is not cancelable since the delete operation has already completed. +/// public class DataTypeDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class with a single data type. + /// + /// The data type that was deleted. + /// The event messages collection. public DataTypeDeletedNotification(IDataType target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DataTypeDeletingNotification.cs b/src/Umbraco.Core/Notifications/DataTypeDeletingNotification.cs index d97632152b35..4272e77d700f 100644 --- a/src/Umbraco.Core/Notifications/DataTypeDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/DataTypeDeletingNotification.cs @@ -1,12 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the DataTypeService when the Delete method is called in the API. +/// Notification that is published before a data type is deleted. /// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation. +/// The notification is published by the before the data type is removed. +/// public class DataTypeDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class with a single data type. + /// + /// The data type being deleted. + /// The event messages collection. public DataTypeDeletingNotification(IDataType target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DataTypeMovedNotification.cs b/src/Umbraco.Core/Notifications/DataTypeMovedNotification.cs index 50d98213a22c..e70bcd2daf0d 100644 --- a/src/Umbraco.Core/Notifications/DataTypeMovedNotification.cs +++ b/src/Umbraco.Core/Notifications/DataTypeMovedNotification.cs @@ -1,12 +1,21 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the DataTypeService when the Move method is called in the API, after the IDataType has been moved. +/// A notification that is used to trigger the DataTypeService when the Move method is called in the API, after the IDataType has been moved. /// public class DataTypeMovedNotification : MovedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The move event information for the data type that was moved. + /// The event messages collection. public DataTypeMovedNotification(MoveEventInfo target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DataTypeMovingNotification.cs b/src/Umbraco.Core/Notifications/DataTypeMovingNotification.cs index 6f1247966cd5..2ef867015259 100644 --- a/src/Umbraco.Core/Notifications/DataTypeMovingNotification.cs +++ b/src/Umbraco.Core/Notifications/DataTypeMovingNotification.cs @@ -1,12 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the DataTypeService when the Move method is called in the API. +/// A notification that is used to trigger the DataTypeService when the Move method is called in the API. /// +/// +/// This notification is cancelable, allowing handlers to prevent the move operation +/// by setting to true. +/// public class DataTypeMovingNotification : MovingNotification { + /// + /// Initializes a new instance of the class. + /// + /// The move event information for the data type being moved. + /// The event messages collection. public DataTypeMovingNotification(MoveEventInfo target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DataTypeSavedNotification.cs b/src/Umbraco.Core/Notifications/DataTypeSavedNotification.cs index 58ad7c124ca6..0e2a4f77de01 100644 --- a/src/Umbraco.Core/Notifications/DataTypeSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/DataTypeSavedNotification.cs @@ -1,17 +1,35 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the DataTypeService when the Save method is called in the API, and after data has been persisted. +/// Notification that is published after a data type has been saved. /// +/// +/// This notification is published by the after the data type has been persisted. +/// It is not cancelable since the save operation has already completed. +/// public class DataTypeSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class with a single data type. + /// + /// The data type that was saved. + /// The event messages collection. public DataTypeSavedNotification(IDataType target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple data types. + /// + /// The collection of data types that were saved. + /// The event messages collection. public DataTypeSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DataTypeSavingNotification.cs b/src/Umbraco.Core/Notifications/DataTypeSavingNotification.cs index cb910638ee35..2d5d52015784 100644 --- a/src/Umbraco.Core/Notifications/DataTypeSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/DataTypeSavingNotification.cs @@ -1,17 +1,35 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the DataTypeService when the Save method is called in the API. +/// Notification that is published before a data type is saved. /// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation. +/// The notification is published by the before the data type is persisted. +/// public class DataTypeSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class with a single data type. + /// + /// The data type being saved. + /// The event messages collection. public DataTypeSavingNotification(IDataType target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple data types. + /// + /// The collection of data types being saved. + /// The event messages collection. public DataTypeSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DeletedNotification.cs b/src/Umbraco.Core/Notifications/DeletedNotification.cs index 69af0581af0b..de746a4a99be 100644 --- a/src/Umbraco.Core/Notifications/DeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/DeletedNotification.cs @@ -5,17 +5,38 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published after entities have been deleted. +/// +/// The type of entities that were deleted. +/// +/// This notification is published after the entities have been removed from the database. +/// It is not cancelable since the delete operation has already completed. +/// public abstract class DeletedNotification : EnumerableObjectNotification { + /// + /// Initializes a new instance of the class with a single entity. + /// + /// The entity that was deleted. + /// The event messages collection. protected DeletedNotification(T target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple entities. + /// + /// The collection of entities that were deleted. + /// The event messages collection. protected DeletedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the collection of entities that were deleted. + /// public IEnumerable DeletedEntities => Target; } diff --git a/src/Umbraco.Core/Notifications/DeletedVersionsNotification.cs b/src/Umbraco.Core/Notifications/DeletedVersionsNotification.cs index 03b8e150b7dd..a4f58039d835 100644 --- a/src/Umbraco.Core/Notifications/DeletedVersionsNotification.cs +++ b/src/Umbraco.Core/Notifications/DeletedVersionsNotification.cs @@ -5,9 +5,25 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published after versions have been deleted. +/// +/// The type of entity whose versions were deleted. +/// +/// This notification is published after versions have been successfully deleted, +/// allowing handlers to react to the deletion for auditing or cache invalidation purposes. +/// public abstract class DeletedVersionsNotification : DeletedVersionsNotificationBase where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The ID of the entity whose versions were deleted. + /// The event messages collection. + /// The specific version that was deleted, or default if based on other criteria. + /// Whether all versions prior to the specified version were deleted. + /// The date before which versions were deleted. protected DeletedVersionsNotification(int id, EventMessages messages, int specificVersion = default, bool deletePriorVersions = false, DateTime dateToRetain = default) : base(id, messages, specificVersion, deletePriorVersions, dateToRetain) { diff --git a/src/Umbraco.Core/Notifications/DeletedVersionsNotificationBase.cs b/src/Umbraco.Core/Notifications/DeletedVersionsNotificationBase.cs index a68593de8053..7aaa35e86c7d 100644 --- a/src/Umbraco.Core/Notifications/DeletedVersionsNotificationBase.cs +++ b/src/Umbraco.Core/Notifications/DeletedVersionsNotificationBase.cs @@ -5,9 +5,26 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications related to deleting content or media versions. +/// +/// The type of entity whose versions are being deleted. +/// +/// This notification provides information about which versions are being deleted, +/// including support for deleting specific versions, prior versions, or versions +/// before a certain date. +/// public abstract class DeletedVersionsNotificationBase : StatefulNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The ID of the entity whose versions are being deleted. + /// The event messages collection. + /// The specific version to delete, or default to delete based on other criteria. + /// Whether to delete all versions prior to the specified version. + /// The date before which versions should be deleted. protected DeletedVersionsNotificationBase( int id, EventMessages messages, @@ -22,13 +39,28 @@ protected DeletedVersionsNotificationBase( DateToRetain = dateToRetain; } + /// + /// Gets the ID of the entity whose versions are being deleted. + /// public int Id { get; } + /// + /// Gets the event messages collection. + /// public EventMessages Messages { get; } + /// + /// Gets the specific version to delete, or default if not targeting a specific version. + /// public int SpecificVersion { get; } + /// + /// Gets a value indicating whether to delete all versions prior to the specified version. + /// public bool DeletePriorVersions { get; } + /// + /// Gets the date before which versions should be deleted. + /// public DateTime DateToRetain { get; } } diff --git a/src/Umbraco.Core/Notifications/DeletingNotification.cs b/src/Umbraco.Core/Notifications/DeletingNotification.cs index ab630468dd7d..6eec866331c0 100644 --- a/src/Umbraco.Core/Notifications/DeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/DeletingNotification.cs @@ -5,17 +5,38 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published before entities are deleted. +/// +/// The type of entities being deleted. +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation. +/// The notification is published before the entities are removed from the database. +/// public abstract class DeletingNotification : CancelableEnumerableObjectNotification { + /// + /// Initializes a new instance of the class with a single entity. + /// + /// The entity being deleted. + /// The event messages collection. protected DeletingNotification(T target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple entities. + /// + /// The collection of entities being deleted. + /// The event messages collection. protected DeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the collection of entities being deleted. + /// public IEnumerable DeletedEntities => Target; } diff --git a/src/Umbraco.Core/Notifications/DeletingVersionsNotification.cs b/src/Umbraco.Core/Notifications/DeletingVersionsNotification.cs index 6b708da28b35..4ec18c070cd2 100644 --- a/src/Umbraco.Core/Notifications/DeletingVersionsNotification.cs +++ b/src/Umbraco.Core/Notifications/DeletingVersionsNotification.cs @@ -5,13 +5,30 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for cancelable notifications published before versions are deleted. +/// +/// The type of entity whose versions are being deleted. +/// +/// This notification is published before versions are deleted, allowing handlers to cancel +/// the operation by setting to true. +/// public abstract class DeletingVersionsNotification : DeletedVersionsNotificationBase, ICancelableNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The ID of the entity whose versions are being deleted. + /// The event messages collection. + /// The specific version to delete, or default to delete based on other criteria. + /// Whether to delete all versions prior to the specified version. + /// The date before which versions should be deleted. protected DeletingVersionsNotification(int id, EventMessages messages, int specificVersion = default, bool deletePriorVersions = false, DateTime dateToRetain = default) : base(id, messages, specificVersion, deletePriorVersions, dateToRetain) { } + /// public bool Cancel { get; set; } } diff --git a/src/Umbraco.Core/Notifications/DictionaryCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/DictionaryCacheRefresherNotification.cs index 170e8e21be86..7becc4426bab 100644 --- a/src/Umbraco.Core/Notifications/DictionaryCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/DictionaryCacheRefresherNotification.cs @@ -1,9 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when dictionary cache needs to be refreshed. +/// +/// +/// This notification is used to synchronize dictionary cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class DictionaryCacheRefresherNotification : CacheRefresherNotification { + /// + /// Initializes a new instance of the class. + /// + /// The payload containing information about the dictionary items to refresh. + /// The type of cache refresh operation. public DictionaryCacheRefresherNotification(object messageObject, MessageType messageType) : base(messageObject, messageType) { diff --git a/src/Umbraco.Core/Notifications/DictionaryItemDeletingNotification.cs b/src/Umbraco.Core/Notifications/DictionaryItemDeletingNotification.cs index ed7d40eb470e..537f0370a322 100644 --- a/src/Umbraco.Core/Notifications/DictionaryItemDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/DictionaryItemDeletingNotification.cs @@ -5,24 +5,33 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the ILocalizationService when the Delete (IDictionaryItem overload) method is called in the API. +/// A notification that is used to trigger the ILocalizationService when the Delete (IDictionaryItem overload) method is called in the API. /// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation +/// by setting to true. +/// public class DictionaryItemDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single dictionary item. + /// + /// The dictionary item being deleted. + /// The event messages collection. public DictionaryItemDeletingNotification(IDictionaryItem target, EventMessages messages) : base(target, messages) { } + /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class + /// with multiple dictionary items. /// - /// - /// Gets the collection of deleted IDictionaryItem objects. - /// - /// - /// Initializes a new instance of the . - /// + /// The dictionary items being deleted. + /// The event messages collection. public DictionaryItemDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DictionaryItemMovedNotification.cs b/src/Umbraco.Core/Notifications/DictionaryItemMovedNotification.cs index f58e39bb4cff..632b5e70ad89 100644 --- a/src/Umbraco.Core/Notifications/DictionaryItemMovedNotification.cs +++ b/src/Umbraco.Core/Notifications/DictionaryItemMovedNotification.cs @@ -1,15 +1,37 @@ -using Umbraco.Cms.Core.Events; +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after dictionary items have been moved. +/// +/// +/// This notification is published after dictionary items have been successfully moved +/// to a new parent in the dictionary tree. +/// public class DictionaryItemMovedNotification : MovedNotification { + /// + /// Initializes a new instance of the class + /// with a single move operation. + /// + /// Information about the dictionary item that was moved. + /// The event messages collection. public DictionaryItemMovedNotification(MoveEventInfo target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple move operations. + /// + /// Information about the dictionary items that were moved. + /// The event messages collection. public DictionaryItemMovedNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DictionaryItemMovingNotification.cs b/src/Umbraco.Core/Notifications/DictionaryItemMovingNotification.cs index 35586104aae7..5e0afb63be83 100644 --- a/src/Umbraco.Core/Notifications/DictionaryItemMovingNotification.cs +++ b/src/Umbraco.Core/Notifications/DictionaryItemMovingNotification.cs @@ -1,15 +1,37 @@ -using Umbraco.Cms.Core.Events; +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before dictionary items are moved. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the move operation +/// by setting to true. +/// public class DictionaryItemMovingNotification : MovingNotification { + /// + /// Initializes a new instance of the class + /// with a single move operation. + /// + /// Information about the dictionary item being moved. + /// The event messages collection. public DictionaryItemMovingNotification(MoveEventInfo target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple move operations. + /// + /// Information about the dictionary items being moved. + /// The event messages collection. public DictionaryItemMovingNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DictionaryItemSavedNotification.cs b/src/Umbraco.Core/Notifications/DictionaryItemSavedNotification.cs index da4e6687ca46..9e2d125372c8 100644 --- a/src/Umbraco.Core/Notifications/DictionaryItemSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/DictionaryItemSavedNotification.cs @@ -5,24 +5,29 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the ILocalizationService when the Save (IDictionaryItem overload) method is called in the API and the data has been persisted. +/// A notification that is used to trigger the ILocalizationService when the Save (IDictionaryItem overload) method is called in the API and the data has been persisted. /// public class DictionaryItemSavedNotification : SavedNotification { - public DictionaryItemSavedNotification(IDictionaryItem target, EventMessages messages) + /// + /// Initializes a new instance of the class + /// with a single dictionary item. + /// + /// The dictionary item that was saved. + /// The event messages collection. + public DictionaryItemSavedNotification(IDictionaryItem target, EventMessages messages) : base(target, messages) { } + /// - /// Initializes a new instance of the + /// Initializes a new instance of the class + /// with multiple dictionary items. /// - /// - /// Gets the saved collection of IDictionary objects. - /// - /// - /// Initializes a new instance of the . - /// + /// The dictionary items that were saved. + /// The event messages collection. public DictionaryItemSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DictionaryItemSavingNotification.cs b/src/Umbraco.Core/Notifications/DictionaryItemSavingNotification.cs index 4766cdddc127..27d2b7647ea8 100644 --- a/src/Umbraco.Core/Notifications/DictionaryItemSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/DictionaryItemSavingNotification.cs @@ -5,25 +5,33 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the ILocalizationService when the Save (IDictionaryItem overload) method is called in the API. +/// A notification that is used to trigger the ILocalizationService when the Save (IDictionaryItem overload) method is called in the API. /// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation +/// by setting to true. +/// public class DictionaryItemSavingNotification : SavingNotification { /// - /// Initializes a new instance of the + /// Initializes a new instance of the class + /// with a single dictionary item. /// - /// - /// Gets the collection of IDictionaryItem objects being saved. - /// - /// - /// Initializes a new instance of the . - /// + /// The dictionary item being saved. + /// The event messages collection. public DictionaryItemSavingNotification(IDictionaryItem target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple dictionary items. + /// + /// The dictionary items being saved. + /// The event messages collection. public DictionaryItemSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DomainCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/DomainCacheRefresherNotification.cs index 86114b500375..b998fa81d4da 100644 --- a/src/Umbraco.Core/Notifications/DomainCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/DomainCacheRefresherNotification.cs @@ -1,9 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when domain cache needs to be refreshed. +/// +/// +/// This notification is used to synchronize domain cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class DomainCacheRefresherNotification : CacheRefresherNotification { + /// + /// Initializes a new instance of the class. + /// + /// The payload containing information about the domains to refresh. + /// The type of cache refresh operation. public DomainCacheRefresherNotification(object messageObject, MessageType messageType) : base(messageObject, messageType) { diff --git a/src/Umbraco.Core/Notifications/DomainDeletedNotification.cs b/src/Umbraco.Core/Notifications/DomainDeletedNotification.cs index dfab6f9c5896..41e7c7fd079e 100644 --- a/src/Umbraco.Core/Notifications/DomainDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/DomainDeletedNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after domains have been deleted. +/// +/// +/// This notification is published after domains have been successfully deleted, +/// allowing handlers to react for auditing or cache invalidation purposes. +/// public class DomainDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class + /// with a single domain. + /// + /// The domain that was deleted. + /// The event messages collection. public DomainDeletedNotification(IDomain target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple domains. + /// + /// The domains that were deleted. + /// The event messages collection. public DomainDeletedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DomainDeletingNotification.cs b/src/Umbraco.Core/Notifications/DomainDeletingNotification.cs index afeb3fa67c99..eabf833426be 100644 --- a/src/Umbraco.Core/Notifications/DomainDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/DomainDeletingNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before domains are deleted. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation +/// by setting to true. +/// public class DomainDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single domain. + /// + /// The domain being deleted. + /// The event messages collection. public DomainDeletingNotification(IDomain target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple domains. + /// + /// The domains being deleted. + /// The event messages collection. public DomainDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DomainSavedNotification.cs b/src/Umbraco.Core/Notifications/DomainSavedNotification.cs index 75c93e15b702..10d0f231564d 100644 --- a/src/Umbraco.Core/Notifications/DomainSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/DomainSavedNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after domains have been saved. +/// +/// +/// This notification is published after domains have been successfully saved, +/// allowing handlers to react for auditing or cache invalidation purposes. +/// public class DomainSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class + /// with a single domain. + /// + /// The domain that was saved. + /// The event messages collection. public DomainSavedNotification(IDomain target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple domains. + /// + /// The domains that were saved. + /// The event messages collection. public DomainSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/DomainSavingNotification.cs b/src/Umbraco.Core/Notifications/DomainSavingNotification.cs index 673ed92c7205..98a95dc91372 100644 --- a/src/Umbraco.Core/Notifications/DomainSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/DomainSavingNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before domains are saved. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation +/// by setting to true. +/// public class DomainSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class + /// with a single domain. + /// + /// The domain being saved. + /// The event messages collection. public DomainSavingNotification(IDomain target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple domains. + /// + /// The domains being saved. + /// The event messages collection. public DomainSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/EmptiedRecycleBinNotification.cs b/src/Umbraco.Core/Notifications/EmptiedRecycleBinNotification.cs index 8e648ac14d94..1adbb605f949 100644 --- a/src/Umbraco.Core/Notifications/EmptiedRecycleBinNotification.cs +++ b/src/Umbraco.Core/Notifications/EmptiedRecycleBinNotification.cs @@ -5,16 +5,35 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published after the recycle bin has been emptied. +/// +/// The type of entities that were in the recycle bin. +/// +/// This notification is published after the entities have been permanently deleted. +/// It is not cancelable since the empty operation has already completed. +/// public abstract class EmptiedRecycleBinNotification : StatefulNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The collection of entities that were permanently deleted. + /// The event messages collection. protected EmptiedRecycleBinNotification(IEnumerable deletedEntities, EventMessages messages) { DeletedEntities = deletedEntities; Messages = messages; } + /// + /// Gets the collection of entities that were permanently deleted from the recycle bin. + /// public IEnumerable DeletedEntities { get; } + /// + /// Gets the event messages collection associated with this notification. + /// public EventMessages Messages { get; } } diff --git a/src/Umbraco.Core/Notifications/EmptyingRecycleBinNotification.cs b/src/Umbraco.Core/Notifications/EmptyingRecycleBinNotification.cs index 570181941506..c380beba7746 100644 --- a/src/Umbraco.Core/Notifications/EmptyingRecycleBinNotification.cs +++ b/src/Umbraco.Core/Notifications/EmptyingRecycleBinNotification.cs @@ -5,18 +5,38 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published before the recycle bin is emptied. +/// +/// The type of entities in the recycle bin being deleted. +/// +/// This notification is cancelable, allowing handlers to prevent the empty recycle bin operation. +/// The notification is published before the entities are permanently deleted. +/// public abstract class EmptyingRecycleBinNotification : StatefulNotification, ICancelableNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The collection of entities being permanently deleted. + /// The event messages collection. protected EmptyingRecycleBinNotification(IEnumerable? deletedEntities, EventMessages messages) { DeletedEntities = deletedEntities; Messages = messages; } + /// + /// Gets the collection of entities being permanently deleted from the recycle bin. + /// public IEnumerable? DeletedEntities { get; } + /// + /// Gets the event messages collection associated with this notification. + /// public EventMessages Messages { get; } + /// public bool Cancel { get; set; } } diff --git a/src/Umbraco.Core/Notifications/EntityContainerDeletedNotification.cs b/src/Umbraco.Core/Notifications/EntityContainerDeletedNotification.cs index 5074aa3893c7..8f4219ab1a2b 100644 --- a/src/Umbraco.Core/Notifications/EntityContainerDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/EntityContainerDeletedNotification.cs @@ -1,10 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after entity containers (folders) have been deleted. +/// +/// +/// Entity containers are used to organize content types, media types, and data types +/// into folders. This notification is published after a container has been deleted. +/// public class EntityContainerDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The entity container that was deleted. + /// The event messages collection. public EntityContainerDeletedNotification(EntityContainer target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/EntityContainerDeletingNotification.cs b/src/Umbraco.Core/Notifications/EntityContainerDeletingNotification.cs index 4d22d7715a8b..fb2a13ddf794 100644 --- a/src/Umbraco.Core/Notifications/EntityContainerDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/EntityContainerDeletingNotification.cs @@ -1,10 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before entity containers (folders) are deleted. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation +/// by setting to true. +/// public class EntityContainerDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class. + /// + /// The entity container being deleted. + /// The event messages collection. public EntityContainerDeletingNotification(EntityContainer target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/EntityContainerRenamedNotification.cs b/src/Umbraco.Core/Notifications/EntityContainerRenamedNotification.cs index 11e7100b9167..52e0ebe00a87 100644 --- a/src/Umbraco.Core/Notifications/EntityContainerRenamedNotification.cs +++ b/src/Umbraco.Core/Notifications/EntityContainerRenamedNotification.cs @@ -1,10 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after entity containers (folders) have been renamed. +/// +/// +/// Entity containers are used to organize content types, media types, and data types +/// into folders. This notification is published after a container has been renamed. +/// public class EntityContainerRenamedNotification : RenamedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The entity container that was renamed. + /// The event messages collection. public EntityContainerRenamedNotification(EntityContainer target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/EntityContainerRenamingNotification.cs b/src/Umbraco.Core/Notifications/EntityContainerRenamingNotification.cs index 9e1b795d9f12..0c81fd6fb8e8 100644 --- a/src/Umbraco.Core/Notifications/EntityContainerRenamingNotification.cs +++ b/src/Umbraco.Core/Notifications/EntityContainerRenamingNotification.cs @@ -1,10 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before entity containers (folders) are renamed. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the rename operation +/// by setting to true. +/// public class EntityContainerRenamingNotification : RenamingNotification { + /// + /// Initializes a new instance of the class. + /// + /// The entity container being renamed. + /// The event messages collection. public EntityContainerRenamingNotification(EntityContainer target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/EntityContainerSavedNotification.cs b/src/Umbraco.Core/Notifications/EntityContainerSavedNotification.cs index 4fa344683473..106112b59172 100644 --- a/src/Umbraco.Core/Notifications/EntityContainerSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/EntityContainerSavedNotification.cs @@ -1,10 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after entity containers (folders) have been saved. +/// +/// +/// Entity containers are used to organize content types, media types, and data types +/// into folders. This notification is published after a container has been saved. +/// public class EntityContainerSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The entity container that was saved. + /// The event messages collection. public EntityContainerSavedNotification(EntityContainer target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/EntityContainerSavingNotification.cs b/src/Umbraco.Core/Notifications/EntityContainerSavingNotification.cs index 6c5455e76287..729cdff3a4f8 100644 --- a/src/Umbraco.Core/Notifications/EntityContainerSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/EntityContainerSavingNotification.cs @@ -1,10 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before entity containers (folders) are saved. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation +/// by setting to true. +/// public class EntityContainerSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class. + /// + /// The entity container being saved. + /// The event messages collection. public EntityContainerSavingNotification(EntityContainer target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/EntityRefreshNotification.cs b/src/Umbraco.Core/Notifications/EntityRefreshNotification.cs index 4a5aaa4216c9..7f0f7481b200 100644 --- a/src/Umbraco.Core/Notifications/EntityRefreshNotification.cs +++ b/src/Umbraco.Core/Notifications/EntityRefreshNotification.cs @@ -1,15 +1,33 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when an entity needs to be refreshed in the cache. +/// +/// The type of content base entity being refreshed. +/// +/// This notification is used internally for cache synchronization purposes. +/// public class EntityRefreshNotification : ObjectNotification where T : class, IContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The entity to refresh. + /// The event messages collection. public EntityRefreshNotification(T target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the entity that needs to be refreshed. + /// public T Entity => Target; } diff --git a/src/Umbraco.Core/Notifications/EnumerableObjectNotification.cs b/src/Umbraco.Core/Notifications/EnumerableObjectNotification.cs index 3989e34b4b97..266b409c5e63 100644 --- a/src/Umbraco.Core/Notifications/EnumerableObjectNotification.cs +++ b/src/Umbraco.Core/Notifications/EnumerableObjectNotification.cs @@ -5,13 +5,31 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications that carry a collection of target objects. +/// +/// The type of items in the collection. +/// +/// This class extends with as the target type, +/// providing convenient constructors for both single items and collections. +/// public abstract class EnumerableObjectNotification : ObjectNotification> { + /// + /// Initializes a new instance of the class with a single target item. + /// + /// The single target item. + /// The event messages collection. protected EnumerableObjectNotification(T target, EventMessages messages) : base(new[] { target }, messages) { } + /// + /// Initializes a new instance of the class with multiple target items. + /// + /// The collection of target items. + /// The event messages collection. protected EnumerableObjectNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ExportedMemberNotification.cs b/src/Umbraco.Core/Notifications/ExportedMemberNotification.cs index 29c843945ca9..f61390487832 100644 --- a/src/Umbraco.Core/Notifications/ExportedMemberNotification.cs +++ b/src/Umbraco.Core/Notifications/ExportedMemberNotification.cs @@ -1,17 +1,38 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Membership; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when a member has been exported. +/// +/// +/// This notification is published after member data has been exported, typically for GDPR +/// compliance purposes. Handlers can use this to add additional data to the export. +/// public class ExportedMemberNotification : INotification { + /// + /// Initializes a new instance of the class. + /// + /// The member that was exported. + /// The export model containing the member's data. public ExportedMemberNotification(IMember member, MemberExportModel exported) { Member = member; Exported = exported; } + /// + /// Gets the member that was exported. + /// public IMember Member { get; } + /// + /// Gets the export model containing the member's data. + /// public MemberExportModel Exported { get; } } diff --git a/src/Umbraco.Core/Notifications/HealthCheckCompletedNotification.cs b/src/Umbraco.Core/Notifications/HealthCheckCompletedNotification.cs index 67df86deb169..ab48bfcfdb6f 100644 --- a/src/Umbraco.Core/Notifications/HealthCheckCompletedNotification.cs +++ b/src/Umbraco.Core/Notifications/HealthCheckCompletedNotification.cs @@ -1,13 +1,30 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.HealthChecks; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when health checks have been completed. +/// +/// +/// This notification is published after the health check runner has executed all configured +/// health checks, allowing handlers to process or act on the results. +/// public class HealthCheckCompletedNotification : INotification { + /// + /// Initializes a new instance of the class. + /// + /// The results of the completed health checks. public HealthCheckCompletedNotification(HealthCheckResults healthCheckResults) { HealthCheckResults = healthCheckResults; } + /// + /// Gets the results of the completed health checks. + /// public HealthCheckResults HealthCheckResults { get; } } diff --git a/src/Umbraco.Core/Notifications/ICancelableNotification.cs b/src/Umbraco.Core/Notifications/ICancelableNotification.cs index e4d1b61309e1..e73871e28333 100644 --- a/src/Umbraco.Core/Notifications/ICancelableNotification.cs +++ b/src/Umbraco.Core/Notifications/ICancelableNotification.cs @@ -3,7 +3,20 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Represents a notification that can be canceled by a notification handler. +/// +/// +/// When a notification handler sets to true, +/// the operation that triggered the notification will be aborted. +/// public interface ICancelableNotification : INotification { + /// + /// Gets or sets a value indicating whether the operation should be canceled. + /// + /// + /// true if the operation should be canceled; otherwise, false. + /// bool Cancel { get; set; } } diff --git a/src/Umbraco.Core/Notifications/IStatefulNotification.cs b/src/Umbraco.Core/Notifications/IStatefulNotification.cs index 65603f5bfa76..9eae1bafa8e1 100644 --- a/src/Umbraco.Core/Notifications/IStatefulNotification.cs +++ b/src/Umbraco.Core/Notifications/IStatefulNotification.cs @@ -1,6 +1,22 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Represents a notification that can carry state between "ing" (before) and "ed" (after) notifications. +/// +/// +/// This interface allows notification handlers to store custom state data that persists +/// between the starting notification (e.g., ContentSaving) and the ending notification (e.g., ContentSaved). +/// public interface IStatefulNotification : INotification { + /// + /// Gets or sets a dictionary for storing custom state data. + /// + /// + /// Use this property to pass data between a starting ("ing") and an ending ("ed") notification handler. + /// IDictionary State { get; set; } } diff --git a/src/Umbraco.Core/Notifications/ImportedPackageNotification.cs b/src/Umbraco.Core/Notifications/ImportedPackageNotification.cs index 62114722c1cc..e4e0bc5239a5 100644 --- a/src/Umbraco.Core/Notifications/ImportedPackageNotification.cs +++ b/src/Umbraco.Core/Notifications/ImportedPackageNotification.cs @@ -1,11 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Packaging; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after a package has been imported. +/// +/// +/// This notification is published after a package has been successfully imported, +/// providing access to the installation summary with details about what was installed. +/// public class ImportedPackageNotification : StatefulNotification { + /// + /// Initializes a new instance of the class. + /// + /// The summary of the package installation. public ImportedPackageNotification(InstallationSummary installationSummary) => InstallationSummary = installationSummary; + /// + /// Gets the summary of the package installation. + /// public InstallationSummary InstallationSummary { get; } } diff --git a/src/Umbraco.Core/Notifications/ImportingPackageNotification.cs b/src/Umbraco.Core/Notifications/ImportingPackageNotification.cs index 67a02f254c88..944ee8d8f814 100644 --- a/src/Umbraco.Core/Notifications/ImportingPackageNotification.cs +++ b/src/Umbraco.Core/Notifications/ImportingPackageNotification.cs @@ -1,10 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before a package is imported. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the package import +/// by setting to true. +/// public class ImportingPackageNotification : StatefulNotification, ICancelableNotification { + /// + /// Initializes a new instance of the class. + /// + /// The name of the package being imported. public ImportingPackageNotification(string packageName) => PackageName = packageName; + /// + /// Gets the name of the package being imported. + /// public string PackageName { get; } + /// public bool Cancel { get; set; } } diff --git a/src/Umbraco.Core/Notifications/LanguageCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/LanguageCacheRefresherNotification.cs index 8e62c68b1d39..4a4fb89acaf7 100644 --- a/src/Umbraco.Core/Notifications/LanguageCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/LanguageCacheRefresherNotification.cs @@ -1,9 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when language cache needs to be refreshed. +/// +/// +/// This notification is used to synchronize language cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class LanguageCacheRefresherNotification : CacheRefresherNotification { + /// + /// Initializes a new instance of the class. + /// + /// The payload containing information about the languages to refresh. + /// The type of cache refresh operation. public LanguageCacheRefresherNotification(object messageObject, MessageType messageType) : base(messageObject, messageType) { diff --git a/src/Umbraco.Core/Notifications/LanguageDeletedNotification.cs b/src/Umbraco.Core/Notifications/LanguageDeletedNotification.cs index 61884e1e1677..50cf7d6426cb 100644 --- a/src/Umbraco.Core/Notifications/LanguageDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/LanguageDeletedNotification.cs @@ -5,11 +5,17 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the ILocalizationService when the Delete (ILanguage overload) method is called in the API, after the languages have been deleted. +/// A notification that is used to trigger the ILocalizationService when the Delete (ILanguage overload) method is called in the API, after the languages have been deleted. /// public class LanguageDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The language that was deleted. + /// The event messages collection. public LanguageDeletedNotification(ILanguage target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/LanguageDeletingNotification.cs b/src/Umbraco.Core/Notifications/LanguageDeletingNotification.cs index 7f011beb819d..201a5ba4fc0d 100644 --- a/src/Umbraco.Core/Notifications/LanguageDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/LanguageDeletingNotification.cs @@ -10,11 +10,23 @@ namespace Umbraco.Cms.Core.Notifications; /// public class LanguageDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single language. + /// + /// The language being deleted. + /// The event messages collection. public LanguageDeletingNotification(ILanguage target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple languages. + /// + /// The languages being deleted. + /// The event messages collection. public LanguageDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/LanguageSavedNotification.cs b/src/Umbraco.Core/Notifications/LanguageSavedNotification.cs index 15d99a404c2c..0c5342e1686f 100644 --- a/src/Umbraco.Core/Notifications/LanguageSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/LanguageSavedNotification.cs @@ -10,11 +10,23 @@ namespace Umbraco.Cms.Core.Notifications; /// public class LanguageSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class + /// with a single language. + /// + /// The language that was saved. + /// The event messages collection. public LanguageSavedNotification(ILanguage target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple languages. + /// + /// The languages that were saved. + /// The event messages collection. public LanguageSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/LanguageSavingNotification.cs b/src/Umbraco.Core/Notifications/LanguageSavingNotification.cs index 74370355c6ea..23eec3cd91be 100644 --- a/src/Umbraco.Core/Notifications/LanguageSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/LanguageSavingNotification.cs @@ -10,11 +10,23 @@ namespace Umbraco.Cms.Core.Notifications; /// public class LanguageSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class + /// with a single language. + /// + /// The language being saved. + /// The event messages collection. public LanguageSavingNotification(ILanguage target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple languages. + /// + /// The languages being saved. + /// The event messages collection. public LanguageSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/MediaCacheRefresherNotification.cs index fe5c21f9b664..90b6516b81e4 100644 --- a/src/Umbraco.Core/Notifications/MediaCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaCacheRefresherNotification.cs @@ -1,20 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the Media Cache Refresher. +/// Notification that triggers the media cache refresher. /// +/// +/// This notification is used to synchronize media cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class MediaCacheRefresherNotification : CacheRefresherNotification { /// - /// Initializes a new instance of the + /// Initializes a new instance of the class. /// - /// - /// The refresher payload. - /// - /// - /// Type of the cache refresher message, - /// + /// The payload containing information about the media to refresh. + /// The type of cache refresh operation. public MediaCacheRefresherNotification(object messageObject, MessageType messageType) : base(messageObject, messageType) { diff --git a/src/Umbraco.Core/Notifications/MediaDeletedNotification.cs b/src/Umbraco.Core/Notifications/MediaDeletedNotification.cs index 1ee19432c941..f3bd5d1c23f5 100644 --- a/src/Umbraco.Core/Notifications/MediaDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaDeletedNotification.cs @@ -5,11 +5,21 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMediaService when the Delete and EmptyRecycleBin methods are called in the API, after the media has been deleted. +/// Notification that is published after media has been deleted. /// +/// +/// This notification is published by the when Delete or EmptyRecycleBin methods complete. +/// It is not cancelable since the delete operation has already completed. +/// public sealed class MediaDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class with a single media item. + /// + /// The media item that was deleted. + /// The event messages collection. public MediaDeletedNotification(IMedia target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaDeletingNotification.cs b/src/Umbraco.Core/Notifications/MediaDeletingNotification.cs index 5de8242d9801..927f3fa4a3f8 100644 --- a/src/Umbraco.Core/Notifications/MediaDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaDeletingNotification.cs @@ -5,24 +5,31 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMediaService when the DeleteMediaOfType, Delete and EmptyRecycleBin methods are called in the API. +/// Notification that is published before media is deleted. /// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation. +/// The notification is published by the when DeleteMediaOfType, Delete, or EmptyRecycleBin methods are called. +/// public sealed class MediaDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class with a single media item. + /// + /// The media item being deleted. + /// The event messages collection. public MediaDeletingNotification(IMedia target, EventMessages messages) : base(target, messages) { } + /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class with multiple media items. /// - /// - /// Gets the collection of objects being deleted. - /// - /// - /// Initializes a new instance of the . - /// + /// The collection of media items being deleted. + /// The event messages collection. public MediaDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaEmptiedRecycleBinNotification.cs b/src/Umbraco.Core/Notifications/MediaEmptiedRecycleBinNotification.cs index 3aea97d608b2..7534b9eb968b 100644 --- a/src/Umbraco.Core/Notifications/MediaEmptiedRecycleBinNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaEmptiedRecycleBinNotification.cs @@ -6,8 +6,20 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after the media recycle bin has been emptied. +/// +/// +/// This notification is published after all media items in the recycle bin have been +/// permanently deleted. +/// public sealed class MediaEmptiedRecycleBinNotification : EmptiedRecycleBinNotification { + /// + /// Initializes a new instance of the class. + /// + /// The media items that were permanently deleted. + /// The event messages collection. public MediaEmptiedRecycleBinNotification(IEnumerable deletedEntities, EventMessages messages) : base(deletedEntities, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaEmptyingRecycleBinNotification.cs b/src/Umbraco.Core/Notifications/MediaEmptyingRecycleBinNotification.cs index 432d48084796..97bca5ebdfb8 100644 --- a/src/Umbraco.Core/Notifications/MediaEmptyingRecycleBinNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaEmptyingRecycleBinNotification.cs @@ -6,8 +6,20 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before the media recycle bin is emptied. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the recycle bin +/// from being emptied by setting to true. +/// public sealed class MediaEmptyingRecycleBinNotification : EmptyingRecycleBinNotification { + /// + /// Initializes a new instance of the class. + /// + /// The media items that will be permanently deleted. + /// The event messages collection. public MediaEmptyingRecycleBinNotification(IEnumerable deletedEntities, EventMessages messages) : base(deletedEntities, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaMovedNotification.cs b/src/Umbraco.Core/Notifications/MediaMovedNotification.cs index 3ef46323edae..f219ed9dbba4 100644 --- a/src/Umbraco.Core/Notifications/MediaMovedNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaMovedNotification.cs @@ -5,17 +5,37 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMediaService when the Move method is called in the API. The event is fired after the media object has been moved. -/// NOTE: If the target parent is the Recycle bin, this notification is never published. Try the instead. +/// Notification that is published after media has been moved. /// +/// +/// +/// This notification is published by the after media has been moved. +/// It is not cancelable since the move operation has already completed. +/// +/// +/// NOTE: If the target parent is the recycle bin, this notification is never published. +/// Use instead. +/// +/// public sealed class MediaMovedNotification : MovedNotification { + /// + /// Initializes a new instance of the class with a single media item. + /// + /// The move information for the media item that was moved. + /// The event messages collection. public MediaMovedNotification(MoveEventInfo target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple media items. + /// + /// The collection of move information for media items that were moved. + /// The event messages collection. public MediaMovedNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaMovedToRecycleBinNotification.cs b/src/Umbraco.Core/Notifications/MediaMovedToRecycleBinNotification.cs index c9e7a19b4424..06a469e5a054 100644 --- a/src/Umbraco.Core/Notifications/MediaMovedToRecycleBinNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaMovedToRecycleBinNotification.cs @@ -7,15 +7,29 @@ namespace Umbraco.Cms.Core.Notifications; /// -/// A notification that is used to trigger the IMediaService when the MoveToRecycleBin method is called in the API, after the media object has been moved to the RecycleBin. +/// Notification that is published after media has been moved to the recycle bin. /// +/// +/// This notification is published by the after media has been moved to the recycle bin. +/// It is not cancelable since the operation has already completed. +/// public sealed class MediaMovedToRecycleBinNotification : MovedToRecycleBinNotification { + /// + /// Initializes a new instance of the class with a single media item. + /// + /// The move to recycle bin information for the media item that was moved. + /// The event messages collection. public MediaMovedToRecycleBinNotification(MoveToRecycleBinEventInfo target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple media items. + /// + /// The collection of move to recycle bin information for media items that were moved. + /// The event messages collection. public MediaMovedToRecycleBinNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaMovingNotification.cs b/src/Umbraco.Core/Notifications/MediaMovingNotification.cs index a4c906b26566..9421b53487ce 100644 --- a/src/Umbraco.Core/Notifications/MediaMovingNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaMovingNotification.cs @@ -5,17 +5,37 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMediaService when the Move method is called in the API. -/// NOTE: If the target parent is the Recycle bin, this notification is never published. Try the instead. +/// Notification that is published before media is moved. /// +/// +/// +/// This notification is cancelable, allowing handlers to prevent the move operation. +/// The notification is published by the before media is moved. +/// +/// +/// NOTE: If the target parent is the recycle bin, this notification is never published. +/// Use instead. +/// +/// public sealed class MediaMovingNotification : MovingNotification { + /// + /// Initializes a new instance of the class with a single media item. + /// + /// The move information for the media item being moved. + /// The event messages collection. public MediaMovingNotification(MoveEventInfo target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple media items. + /// + /// The collection of move information for media items being moved. + /// The event messages collection. public MediaMovingNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaMovingToRecycleBinNotification.cs b/src/Umbraco.Core/Notifications/MediaMovingToRecycleBinNotification.cs index 2baad45ef367..76d40e7af7b7 100644 --- a/src/Umbraco.Core/Notifications/MediaMovingToRecycleBinNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaMovingToRecycleBinNotification.cs @@ -5,16 +5,31 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMediaService when the MoveToRecycleBin method is called in the API. +/// Notification that is published before media is moved to the recycle bin. /// +/// +/// This notification is cancelable, allowing handlers to prevent the move to recycle bin operation. +/// The notification is published by the when MoveToRecycleBin is called. +/// public sealed class MediaMovingToRecycleBinNotification : MovingToRecycleBinNotification { + /// + /// Initializes a new instance of the class with a single media item. + /// + /// The move to recycle bin information for the media item being moved. + /// The event messages collection. public MediaMovingToRecycleBinNotification(MoveToRecycleBinEventInfo target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple media items. + /// + /// The collection of move to recycle bin information for media items being moved. + /// The event messages collection. public MediaMovingToRecycleBinNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaRefreshNotification.cs b/src/Umbraco.Core/Notifications/MediaRefreshNotification.cs index bd4cb3efdaf3..157a3f45148f 100644 --- a/src/Umbraco.Core/Notifications/MediaRefreshNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaRefreshNotification.cs @@ -1,13 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using System.ComponentModel; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when media needs to be refreshed in the cache. +/// +/// +/// This notification is used internally for cache synchronization purposes. +/// For normal media operations, use instead. +/// [Obsolete("This is only used for the internal cache and will change, use tree change notifications instead")] [EditorBrowsable(EditorBrowsableState.Never)] public class MediaRefreshNotification : EntityRefreshNotification { + /// + /// Initializes a new instance of the class. + /// + /// The media item to refresh. + /// The event messages collection. public MediaRefreshNotification(IMedia target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaSavedNotification.cs b/src/Umbraco.Core/Notifications/MediaSavedNotification.cs index 1f804ae5df0e..66598f78c588 100644 --- a/src/Umbraco.Core/Notifications/MediaSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaSavedNotification.cs @@ -5,24 +5,31 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMediaService when the Save method is called in the API and after the data has been persisted. +/// Notification that is published after media has been saved. /// +/// +/// This notification is published by the after media has been persisted. +/// It is not cancelable since the save operation has already completed. +/// public sealed class MediaSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class with a single media item. + /// + /// The media item that was saved. + /// The event messages collection. public MediaSavedNotification(IMedia target, EventMessages messages) : base(target, messages) { } + /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class with multiple media items. /// - /// - /// Gets the saved collection of objects. - /// - /// - /// Initializes a new instance of the . - /// + /// The collection of media items that were saved. + /// The event messages collection. public MediaSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaSavingNotification.cs b/src/Umbraco.Core/Notifications/MediaSavingNotification.cs index c520266832e2..819365c6461a 100644 --- a/src/Umbraco.Core/Notifications/MediaSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaSavingNotification.cs @@ -5,24 +5,31 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMediaService when the Save method is called in the API. +/// Notification that is published before media is saved. /// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation. +/// The notification is published by the before media is persisted. +/// public sealed class MediaSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class with a single media item. + /// + /// The media item being saved. + /// The event messages collection. public MediaSavingNotification(IMedia target, EventMessages messages) : base(target, messages) { } + /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class with multiple media items. /// - /// - /// Gets the collection of objects being saved. - /// - /// - /// Initializes a new instance of the . - /// + /// The collection of media items being saved. + /// The event messages collection. public MediaSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaTreeChangeNotification.cs b/src/Umbraco.Core/Notifications/MediaTreeChangeNotification.cs index cd896cd1fc55..171ac0321f1c 100644 --- a/src/Umbraco.Core/Notifications/MediaTreeChangeNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaTreeChangeNotification.cs @@ -1,21 +1,50 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services.Changes; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when changes occur in the media tree structure. +/// +/// +/// This notification is published when media items are added, removed, moved, or have their +/// structure modified in the media tree. It is used for cache invalidation and tree synchronization. +/// public class MediaTreeChangeNotification : TreeChangeNotification { + /// + /// Initializes a new instance of the class + /// with a single tree change. + /// + /// The tree change that occurred. + /// The event messages collection. public MediaTreeChangeNotification(TreeChange target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple tree changes. + /// + /// The collection of tree changes that occurred. + /// The event messages collection. public MediaTreeChangeNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// for multiple media items with the same change type. + /// + /// The media items that changed. + /// The type of changes that occurred. + /// The event messages collection. public MediaTreeChangeNotification( IEnumerable target, TreeChangeTypes changeTypes, @@ -24,6 +53,13 @@ public MediaTreeChangeNotification( { } + /// + /// Initializes a new instance of the class + /// for a single media item. + /// + /// The media item that changed. + /// The type of changes that occurred. + /// The event messages collection. public MediaTreeChangeNotification(IMedia target, TreeChangeTypes changeTypes, EventMessages messages) : base(new TreeChange(target, changeTypes), messages) { diff --git a/src/Umbraco.Core/Notifications/MediaTypeChangedNotification.cs b/src/Umbraco.Core/Notifications/MediaTypeChangedNotification.cs index 5410d84bfb4f..46be686b1e8a 100644 --- a/src/Umbraco.Core/Notifications/MediaTypeChangedNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaTypeChangedNotification.cs @@ -8,11 +8,23 @@ namespace Umbraco.Cms.Core.Notifications; /// public class MediaTypeChangedNotification : ContentTypeChangeNotification { + /// + /// Initializes a new instance of the class + /// with a single content type change. + /// + /// The content type change information for the media type. + /// The event messages collection. public MediaTypeChangedNotification(ContentTypeChange target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple content type changes. + /// + /// The content type change information for the media types. + /// The event messages collection. public MediaTypeChangedNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaTypeDeletedNotification.cs b/src/Umbraco.Core/Notifications/MediaTypeDeletedNotification.cs index c100867ffd4b..06fac3d3cbc8 100644 --- a/src/Umbraco.Core/Notifications/MediaTypeDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaTypeDeletedNotification.cs @@ -7,6 +7,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class MediaTypeDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class + /// with a single media type. + /// + /// The media type that was deleted. + /// The event messages collection. public MediaTypeDeletedNotification(IMediaType target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaTypeDeletingNotification.cs b/src/Umbraco.Core/Notifications/MediaTypeDeletingNotification.cs index 2ee54d30839a..2160351aa634 100644 --- a/src/Umbraco.Core/Notifications/MediaTypeDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaTypeDeletingNotification.cs @@ -7,6 +7,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class MediaTypeDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single media type. + /// + /// The media type being deleted. + /// The event messages collection. public MediaTypeDeletingNotification(IMediaType target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaTypeMovedNotification.cs b/src/Umbraco.Core/Notifications/MediaTypeMovedNotification.cs index c005602dd877..c7d4e90cd54d 100644 --- a/src/Umbraco.Core/Notifications/MediaTypeMovedNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaTypeMovedNotification.cs @@ -7,6 +7,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class MediaTypeMovedNotification : MovedNotification { + /// + /// Initializes a new instance of the class + /// with a single media type move operation. + /// + /// The move event information for the media type that was moved. + /// The event messages collection. public MediaTypeMovedNotification(MoveEventInfo target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaTypeMovingNotification.cs b/src/Umbraco.Core/Notifications/MediaTypeMovingNotification.cs index 5cdad939ecf8..ead88b6d47f7 100644 --- a/src/Umbraco.Core/Notifications/MediaTypeMovingNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaTypeMovingNotification.cs @@ -7,6 +7,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class MediaTypeMovingNotification : MovingNotification { + /// + /// Initializes a new instance of the class + /// with a single media type move operation. + /// + /// The move event information for the media type being moved. + /// The event messages collection. public MediaTypeMovingNotification(MoveEventInfo target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaTypeRefreshedNotification.cs b/src/Umbraco.Core/Notifications/MediaTypeRefreshedNotification.cs index 5b6814fdb152..42fa6f19cd7c 100644 --- a/src/Umbraco.Core/Notifications/MediaTypeRefreshedNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaTypeRefreshedNotification.cs @@ -1,3 +1,6 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using System.ComponentModel; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; @@ -5,15 +8,34 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when media types have been refreshed in the cache. +/// +/// +/// This notification is used internally for cache synchronization purposes. +/// For normal media type operations, use tree change notifications instead. +/// [Obsolete("This is only used for the internal cache and will change, use tree change notifications instead")] [EditorBrowsable(EditorBrowsableState.Never)] public class MediaTypeRefreshedNotification : ContentTypeRefreshNotification { + /// + /// Initializes a new instance of the class + /// with a single media type change. + /// + /// The media type change that occurred. + /// The event messages collection. public MediaTypeRefreshedNotification(ContentTypeChange target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple media type changes. + /// + /// The collection of media type changes that occurred. + /// The event messages collection. public MediaTypeRefreshedNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaTypeSavedNotification.cs b/src/Umbraco.Core/Notifications/MediaTypeSavedNotification.cs index 092814e89e9c..3b40cebb515f 100644 --- a/src/Umbraco.Core/Notifications/MediaTypeSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaTypeSavedNotification.cs @@ -1,25 +1,35 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMediaTypeService when the Save method is called in the API, after the entities has been saved. +/// Notification that is published after a media type has been saved. /// +/// +/// This notification is published by the after the media type has been persisted. +/// It is not cancelable since the save operation has already completed. +/// public class MediaTypeSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class with a single media type. + /// + /// The media type that was saved. + /// The event messages collection. public MediaTypeSavedNotification(IMediaType target, EventMessages messages) : base(target, messages) { } + /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class with multiple media types. /// - /// - /// Gets the collection of saved objects. - /// - /// - /// Initializes a new instance of the . - /// + /// The collection of media types that were saved. + /// The event messages collection. public MediaTypeSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MediaTypeSavingNotification.cs b/src/Umbraco.Core/Notifications/MediaTypeSavingNotification.cs index 66ab97df25f1..09b5eb87eaf3 100644 --- a/src/Umbraco.Core/Notifications/MediaTypeSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/MediaTypeSavingNotification.cs @@ -1,25 +1,35 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMediaTypeService when the Save method is called in the API. +/// Notification that is published before a media type is saved. /// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation. +/// The notification is published by the before the media type is persisted. +/// public class MediaTypeSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class with a single media type. + /// + /// The media type being saved. + /// The event messages collection. public MediaTypeSavingNotification(IMediaType target, EventMessages messages) : base(target, messages) { } + /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class with multiple media types. /// - /// - /// Gets the collection of objects being saved. - /// - /// - /// Initializes a new instance of the . - /// + /// The collection of media types being saved. + /// The event messages collection. public MediaTypeSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/MemberCacheRefresherNotification.cs index a765bcb1dbc4..b39ef62c7b2f 100644 --- a/src/Umbraco.Core/Notifications/MemberCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberCacheRefresherNotification.cs @@ -1,20 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the Member Cache Refresher. +/// Notification that triggers the member cache refresher. /// +/// +/// This notification is used to synchronize member cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class MemberCacheRefresherNotification : CacheRefresherNotification { /// - /// Initializes a new instance of the + /// Initializes a new instance of the class. /// - /// - /// The refresher payload. - /// - /// - /// Type of the cache refresher message, - /// + /// The payload containing information about the member to refresh. + /// The type of cache refresh operation. public MemberCacheRefresherNotification(object messageObject, MessageType messageType) : base(messageObject, messageType) { diff --git a/src/Umbraco.Core/Notifications/MemberDeletedNotification.cs b/src/Umbraco.Core/Notifications/MemberDeletedNotification.cs index ba3c84ba40a8..c8384fd52858 100644 --- a/src/Umbraco.Core/Notifications/MemberDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberDeletedNotification.cs @@ -5,20 +5,21 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMemberService when the Delete and DeleteMembersOfType methods are called in the API, after the members have been deleted. +/// Notification that is published after a member has been deleted. /// +/// +/// This notification is published by the when Delete or DeleteMembersOfType methods complete. +/// It is not cancelable since the delete operation has already completed. +/// public sealed class MemberDeletedNotification : DeletedNotification { /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class with a single member. /// - /// - /// Gets the collection of deleted objects. - /// - /// - /// Initializes a new instance of the . - /// + /// The member that was deleted. + /// The event messages collection. public MemberDeletedNotification(IMember target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberDeletingNotification.cs b/src/Umbraco.Core/Notifications/MemberDeletingNotification.cs index c06912f1b22d..939553010686 100644 --- a/src/Umbraco.Core/Notifications/MemberDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberDeletingNotification.cs @@ -5,24 +5,31 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMemberService when the Delete and DeleteMembersOfType methods are called in the API. +/// Notification that is published before a member is deleted. /// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation. +/// The notification is published by the when Delete or DeleteMembersOfType methods are called. +/// public sealed class MemberDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class with a single member. + /// + /// The member being deleted. + /// The event messages collection. public MemberDeletingNotification(IMember target, EventMessages messages) : base(target, messages) { } + /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class with multiple members. /// - /// - /// Gets the collection of objects being deleted. - /// - /// - /// Initializes a new instance of the . - /// + /// The collection of members being deleted. + /// The event messages collection. public MemberDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberGroupCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/MemberGroupCacheRefresherNotification.cs index 333a8fbb5542..12017a531989 100644 --- a/src/Umbraco.Core/Notifications/MemberGroupCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberGroupCacheRefresherNotification.cs @@ -1,9 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when member group cache needs to be refreshed. +/// +/// +/// This notification is used to synchronize member group cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class MemberGroupCacheRefresherNotification : CacheRefresherNotification { + /// + /// Initializes a new instance of the class. + /// + /// The payload containing information about the member groups to refresh. + /// The type of cache refresh operation. public MemberGroupCacheRefresherNotification(object messageObject, MessageType messageType) : base(messageObject, messageType) { diff --git a/src/Umbraco.Core/Notifications/MemberGroupDeletedNotification.cs b/src/Umbraco.Core/Notifications/MemberGroupDeletedNotification.cs index 528dc37254ee..251bdf4a54ef 100644 --- a/src/Umbraco.Core/Notifications/MemberGroupDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberGroupDeletedNotification.cs @@ -1,10 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after member groups have been deleted. +/// +/// +/// This notification is published after member groups have been successfully deleted, +/// allowing handlers to react for auditing or cache invalidation purposes. +/// public class MemberGroupDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The member group that was deleted. + /// The event messages collection. public MemberGroupDeletedNotification(IMemberGroup target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberGroupDeletingNotification.cs b/src/Umbraco.Core/Notifications/MemberGroupDeletingNotification.cs index f0ed3dc49ca2..0362fad27db6 100644 --- a/src/Umbraco.Core/Notifications/MemberGroupDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberGroupDeletingNotification.cs @@ -1,15 +1,37 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before member groups are deleted. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation +/// by setting to true. +/// public class MemberGroupDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single member group. + /// + /// The member group being deleted. + /// The event messages collection. public MemberGroupDeletingNotification(IMemberGroup target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple member groups. + /// + /// The member groups being deleted. + /// The event messages collection. public MemberGroupDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberGroupSavedNotification.cs b/src/Umbraco.Core/Notifications/MemberGroupSavedNotification.cs index 9f8671d923de..40f99d9d4314 100644 --- a/src/Umbraco.Core/Notifications/MemberGroupSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberGroupSavedNotification.cs @@ -1,15 +1,37 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after member groups have been saved. +/// +/// +/// This notification is published after member groups have been successfully saved, +/// allowing handlers to react for auditing or cache invalidation purposes. +/// public class MemberGroupSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class + /// with a single member group. + /// + /// The member group that was saved. + /// The event messages collection. public MemberGroupSavedNotification(IMemberGroup target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple member groups. + /// + /// The member groups that were saved. + /// The event messages collection. public MemberGroupSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberGroupSavingNotification.cs b/src/Umbraco.Core/Notifications/MemberGroupSavingNotification.cs index 233714c54270..fca073e98ce5 100644 --- a/src/Umbraco.Core/Notifications/MemberGroupSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberGroupSavingNotification.cs @@ -1,15 +1,37 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before member groups are saved. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation +/// by setting to true. +/// public class MemberGroupSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class + /// with a single member group. + /// + /// The member group being saved. + /// The event messages collection. public MemberGroupSavingNotification(IMemberGroup target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple member groups. + /// + /// The member groups being saved. + /// The event messages collection. public MemberGroupSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberRefreshNotification.cs b/src/Umbraco.Core/Notifications/MemberRefreshNotification.cs index ddab089c0b18..c0d21a5c6369 100644 --- a/src/Umbraco.Core/Notifications/MemberRefreshNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberRefreshNotification.cs @@ -1,13 +1,28 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using System.ComponentModel; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when a member needs to be refreshed in the cache. +/// +/// +/// This notification is used internally for cache synchronization purposes. +/// For normal member operations, use tree change notifications instead. +/// [Obsolete("This is only used for the internal cache and will change, use tree change notifications instead")] [EditorBrowsable(EditorBrowsableState.Never)] public class MemberRefreshNotification : EntityRefreshNotification { + /// + /// Initializes a new instance of the class. + /// + /// The member to refresh. + /// The event messages collection. public MemberRefreshNotification(IMember target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberRolesNotification.cs b/src/Umbraco.Core/Notifications/MemberRolesNotification.cs index 446faee2371e..c4cd97186f74 100644 --- a/src/Umbraco.Core/Notifications/MemberRolesNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberRolesNotification.cs @@ -1,14 +1,34 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications related to member role assignments. +/// +/// +/// This class is used as a base for notifications published when member roles are assigned or removed. +/// public abstract class MemberRolesNotification : INotification { + /// + /// Initializes a new instance of the class. + /// + /// The IDs of the members affected by the role change. + /// The names of the roles being assigned or removed. protected MemberRolesNotification(int[] memberIds, string[] roles) { MemberIds = memberIds; Roles = roles; } + /// + /// Gets the IDs of the members affected by the role change. + /// public int[] MemberIds { get; } + /// + /// Gets the names of the roles being assigned or removed. + /// public string[] Roles { get; } } diff --git a/src/Umbraco.Core/Notifications/MemberSavedNotification.cs b/src/Umbraco.Core/Notifications/MemberSavedNotification.cs index d51db13a5064..ee324377ce89 100644 --- a/src/Umbraco.Core/Notifications/MemberSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberSavedNotification.cs @@ -5,32 +5,36 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMemberService when the Save method is called in the API and after data has been persisted. +/// Notification that is published after a member has been saved. /// +/// +/// This notification is published by the after the member has been persisted. +/// It is not cancelable since the save operation has already completed. +/// public sealed class MemberSavedNotification : SavedNotification { /// - /// Defines the notification state key for tracking the previous username of a saved member. + /// Defines the notification state key for tracking the previous username of a saved member. /// internal const string PreviousUsernameStateKey = "PreviousUsername"; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class with a single member. /// + /// The member that was saved. + /// The event messages collection. public MemberSavedNotification(IMember target, EventMessages messages) : base(target, messages) { } + /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class with multiple members. /// - /// - /// Gets the saved collection of objects. - /// - /// - /// Initializes a new instance of the . - /// + /// The collection of members that were saved. + /// The event messages collection. public MemberSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberSavingNotification.cs b/src/Umbraco.Core/Notifications/MemberSavingNotification.cs index 7f112eef985d..b84d95cbc624 100644 --- a/src/Umbraco.Core/Notifications/MemberSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberSavingNotification.cs @@ -5,24 +5,31 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMemberService when the Saving method is called in the API. +/// Notification that is published before a member is saved. /// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation. +/// The notification is published by the before the member is persisted. +/// public sealed class MemberSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class with a single member. + /// + /// The member being saved. + /// The event messages collection. public MemberSavingNotification(IMember target, EventMessages messages) : base(target, messages) { } + /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class with multiple members. /// - /// - /// Gets the collection of objects being saved. - /// - /// - /// Initializes a new instance of the . - /// + /// The collection of members being saved. + /// The event messages collection. public MemberSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberTwoFactorRequestedNotification.cs b/src/Umbraco.Core/Notifications/MemberTwoFactorRequestedNotification.cs index fc9e392598f2..e9e2ba9a3ac6 100644 --- a/src/Umbraco.Core/Notifications/MemberTwoFactorRequestedNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberTwoFactorRequestedNotification.cs @@ -1,8 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when a member requests two-factor authentication. +/// +/// +/// This notification is published when a member attempts to authenticate and two-factor +/// authentication is required. Handlers can use this for logging or additional security checks. +/// public class MemberTwoFactorRequestedNotification : INotification { + /// + /// Initializes a new instance of the class. + /// + /// The unique key of the member requesting two-factor authentication, or null if not identified. public MemberTwoFactorRequestedNotification(Guid? memberKey) => MemberKey = memberKey; + /// + /// Gets the unique key of the member requesting two-factor authentication, or null if the member is not identified. + /// public Guid? MemberKey { get; } } diff --git a/src/Umbraco.Core/Notifications/MemberTypeChangedNotification.cs b/src/Umbraco.Core/Notifications/MemberTypeChangedNotification.cs index ceaf15d166b1..1dd9400f92e0 100644 --- a/src/Umbraco.Core/Notifications/MemberTypeChangedNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberTypeChangedNotification.cs @@ -9,11 +9,23 @@ namespace Umbraco.Cms.Core.Notifications; /// public class MemberTypeChangedNotification : ContentTypeChangeNotification { + /// + /// Initializes a new instance of the class + /// with a single content type change. + /// + /// The content type change information for the member type. + /// The event messages collection. public MemberTypeChangedNotification(ContentTypeChange target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple content type changes. + /// + /// The content type change information for the member types. + /// The event messages collection. public MemberTypeChangedNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberTypeDeletedNotification.cs b/src/Umbraco.Core/Notifications/MemberTypeDeletedNotification.cs index e285fa99c213..0235765cc4c8 100644 --- a/src/Umbraco.Core/Notifications/MemberTypeDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberTypeDeletedNotification.cs @@ -7,6 +7,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class MemberTypeDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class + /// with a single member type. + /// + /// The member type that was deleted. + /// The event messages collection. public MemberTypeDeletedNotification(IMemberType target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberTypeDeletingNotification.cs b/src/Umbraco.Core/Notifications/MemberTypeDeletingNotification.cs index d120e30a01cc..5f247648e385 100644 --- a/src/Umbraco.Core/Notifications/MemberTypeDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberTypeDeletingNotification.cs @@ -7,6 +7,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class MemberTypeDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single member type. + /// + /// The member type being deleted. + /// The event messages collection. public MemberTypeDeletingNotification(IMemberType target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberTypeMovedNotification.cs b/src/Umbraco.Core/Notifications/MemberTypeMovedNotification.cs index 5ab605612459..e8622eb8350d 100644 --- a/src/Umbraco.Core/Notifications/MemberTypeMovedNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberTypeMovedNotification.cs @@ -1,15 +1,37 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after member types have been moved. +/// +/// +/// This notification is published after member types have been successfully moved +/// to a new parent in the member type tree. +/// public class MemberTypeMovedNotification : MovedNotification { + /// + /// Initializes a new instance of the class + /// with a single move operation. + /// + /// Information about the member type that was moved. + /// The event messages collection. public MemberTypeMovedNotification(MoveEventInfo target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple move operations. + /// + /// Information about the member types that were moved. + /// The event messages collection. public MemberTypeMovedNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberTypeMovingNotification.cs b/src/Umbraco.Core/Notifications/MemberTypeMovingNotification.cs index ce2f71badfff..61a83c1fd369 100644 --- a/src/Umbraco.Core/Notifications/MemberTypeMovingNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberTypeMovingNotification.cs @@ -7,11 +7,23 @@ namespace Umbraco.Cms.Core.Notifications; /// public class MemberTypeMovingNotification : MovingNotification { + /// + /// Initializes a new instance of the class + /// with a single member type move operation. + /// + /// The move event information for the member type being moved. + /// The event messages collection. public MemberTypeMovingNotification(MoveEventInfo target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple member type move operations. + /// + /// The move event information for the member types being moved. + /// The event messages collection. public MemberTypeMovingNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberTypeRefreshedNotification.cs b/src/Umbraco.Core/Notifications/MemberTypeRefreshedNotification.cs index 050c24a9e78d..8674799870c4 100644 --- a/src/Umbraco.Core/Notifications/MemberTypeRefreshedNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberTypeRefreshedNotification.cs @@ -1,3 +1,6 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using System.ComponentModel; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; @@ -5,15 +8,34 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when member types have been refreshed in the cache. +/// +/// +/// This notification is used internally for cache synchronization purposes. +/// For normal member type operations, use tree change notifications instead. +/// [Obsolete("This is only used for the internal cache and will change, use tree change notifications instead")] [EditorBrowsable(EditorBrowsableState.Never)] public class MemberTypeRefreshedNotification : ContentTypeRefreshNotification { + /// + /// Initializes a new instance of the class + /// with a single member type change. + /// + /// The member type change that occurred. + /// The event messages collection. public MemberTypeRefreshedNotification(ContentTypeChange target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple member type changes. + /// + /// The collection of member type changes that occurred. + /// The event messages collection. public MemberTypeRefreshedNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberTypeSavedNotification.cs b/src/Umbraco.Core/Notifications/MemberTypeSavedNotification.cs index e68cb3031b63..4a7149d657e8 100644 --- a/src/Umbraco.Core/Notifications/MemberTypeSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberTypeSavedNotification.cs @@ -1,25 +1,35 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMemberTypeService when the Save method is called in the API, after the entities have been saved. +/// Notification that is published after a member type has been saved. /// +/// +/// This notification is published by the after the member type has been persisted. +/// It is not cancelable since the save operation has already completed. +/// public class MemberTypeSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class with a single member type. + /// + /// The member type that was saved. + /// The event messages collection. public MemberTypeSavedNotification(IMemberType target, EventMessages messages) : base(target, messages) { } + /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class with multiple member types. /// - /// - /// Gets the collection of saved objects. - /// - /// - /// Initializes a new instance of the . - /// + /// The collection of member types that were saved. + /// The event messages collection. public MemberTypeSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MemberTypeSavingNotification.cs b/src/Umbraco.Core/Notifications/MemberTypeSavingNotification.cs index 774adb3ef8aa..ccdab8cea671 100644 --- a/src/Umbraco.Core/Notifications/MemberTypeSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/MemberTypeSavingNotification.cs @@ -1,25 +1,35 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMemberTypeService when the Save method is called in the API. +/// Notification that is published before a member type is saved. /// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation. +/// The notification is published by the before the member type is persisted. +/// public class MemberTypeSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class with a single member type. + /// + /// The member type being saved. + /// The event messages collection. public MemberTypeSavingNotification(IMemberType target, EventMessages messages) : base(target, messages) { } + /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class with multiple member types. /// - /// - /// Gets the collection of objects being saved. - /// - /// - /// Initializes a new instance of the . - /// + /// The collection of member types being saved. + /// The event messages collection. public MemberTypeSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/MovedNotification.cs b/src/Umbraco.Core/Notifications/MovedNotification.cs index 5aab6c6b7a7c..4d3bbbe06012 100644 --- a/src/Umbraco.Core/Notifications/MovedNotification.cs +++ b/src/Umbraco.Core/Notifications/MovedNotification.cs @@ -5,20 +5,38 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published after entities have been moved. +/// +/// The type of entities that were moved. +/// +/// This notification is published after the entities have been moved to their new location. +/// It is not cancelable since the move operation has already completed. +/// public abstract class MovedNotification : ObjectNotification>> { + /// + /// Initializes a new instance of the class with a single move operation. + /// + /// The move information for the entity that was moved. + /// The event messages collection. protected MovedNotification(MoveEventInfo target, EventMessages messages) : base(new[] { target }, messages) { } + /// + /// Initializes a new instance of the class with multiple move operations. + /// + /// The collection of move information for entities that were moved. + /// The event messages collection. protected MovedNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { } /// - /// Gets a enumeration of with the moved entities. + /// Gets an enumeration of with the moved entities. /// public IEnumerable> MoveInfoCollection => Target; } diff --git a/src/Umbraco.Core/Notifications/MovedToRecycleBinNotification.cs b/src/Umbraco.Core/Notifications/MovedToRecycleBinNotification.cs index 686dc407fc68..c2ea6d21426e 100644 --- a/src/Umbraco.Core/Notifications/MovedToRecycleBinNotification.cs +++ b/src/Umbraco.Core/Notifications/MovedToRecycleBinNotification.cs @@ -5,17 +5,38 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published after entities have been moved to the recycle bin. +/// +/// The type of entities that were moved to the recycle bin. +/// +/// This notification is published after the entities have been moved to the recycle bin. +/// It is not cancelable since the operation has already completed. +/// public abstract class MovedToRecycleBinNotification : ObjectNotification>> { + /// + /// Initializes a new instance of the class with a single move operation. + /// + /// The move to recycle bin information for the entity that was moved. + /// The event messages collection. protected MovedToRecycleBinNotification(MoveToRecycleBinEventInfo target, EventMessages messages) : base(new[] { target }, messages) { } + /// + /// Initializes a new instance of the class with multiple move operations. + /// + /// The collection of move to recycle bin information for entities that were moved. + /// The event messages collection. protected MovedToRecycleBinNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { } + /// + /// Gets an enumeration of with the entities that were moved to the recycle bin. + /// public IEnumerable> MoveInfoCollection => Target; } diff --git a/src/Umbraco.Core/Notifications/MovingNotification.cs b/src/Umbraco.Core/Notifications/MovingNotification.cs index 41f4c1754a85..e236a8d83998 100644 --- a/src/Umbraco.Core/Notifications/MovingNotification.cs +++ b/src/Umbraco.Core/Notifications/MovingNotification.cs @@ -5,20 +5,38 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published before entities are moved. +/// +/// The type of entities being moved. +/// +/// This notification is cancelable, allowing handlers to prevent the move operation. +/// The notification is published before the entities are moved to their new location. +/// public abstract class MovingNotification : CancelableObjectNotification>> { + /// + /// Initializes a new instance of the class with a single move operation. + /// + /// The move information for the entity being moved. + /// The event messages collection. protected MovingNotification(MoveEventInfo target, EventMessages messages) : base(new[] { target }, messages) { } + /// + /// Initializes a new instance of the class with multiple move operations. + /// + /// The collection of move information for entities being moved. + /// The event messages collection. protected MovingNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { } /// - /// Gets a enumeration of with the moving entities. + /// Gets an enumeration of with the moving entities. /// public IEnumerable> MoveInfoCollection => Target; } diff --git a/src/Umbraco.Core/Notifications/MovingToRecycleBinNotification.cs b/src/Umbraco.Core/Notifications/MovingToRecycleBinNotification.cs index 38d6bbbc8c45..e5a460d0a561 100644 --- a/src/Umbraco.Core/Notifications/MovingToRecycleBinNotification.cs +++ b/src/Umbraco.Core/Notifications/MovingToRecycleBinNotification.cs @@ -5,17 +5,38 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published before entities are moved to the recycle bin. +/// +/// The type of entities being moved to the recycle bin. +/// +/// This notification is cancelable, allowing handlers to prevent the move to recycle bin operation. +/// The notification is published before the entities are moved. +/// public abstract class MovingToRecycleBinNotification : CancelableObjectNotification>> { + /// + /// Initializes a new instance of the class with a single move operation. + /// + /// The move to recycle bin information for the entity being moved. + /// The event messages collection. protected MovingToRecycleBinNotification(MoveToRecycleBinEventInfo target, EventMessages messages) : base(new[] { target }, messages) { } + /// + /// Initializes a new instance of the class with multiple move operations. + /// + /// The collection of move to recycle bin information for entities being moved. + /// The event messages collection. protected MovingToRecycleBinNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { } + /// + /// Gets an enumeration of with the entities being moved to the recycle bin. + /// public IEnumerable> MoveInfoCollection => Target; } diff --git a/src/Umbraco.Core/Notifications/NotificationExtensions.cs b/src/Umbraco.Core/Notifications/NotificationExtensions.cs index 540cf0840a25..dd50cf40057c 100644 --- a/src/Umbraco.Core/Notifications/NotificationExtensions.cs +++ b/src/Umbraco.Core/Notifications/NotificationExtensions.cs @@ -1,7 +1,20 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Provides extension methods for notifications to support state transfer. +/// public static class NotificationExtensions { + /// + /// Sets the state dictionary on a stateful notification. + /// + /// The type of notification. + /// The notification to set state on. + /// The state dictionary to set. + /// The notification with state set, for method chaining. public static T WithState(this T notification, IDictionary? state) where T : IStatefulNotification { @@ -9,6 +22,14 @@ public static T WithState(this T notification, IDictionary? return notification; } + /// + /// Copies the state from a source notification to the target notification. + /// + /// The type of target notification. + /// The type of source notification. + /// The notification to set state on. + /// The source notification to copy state from. + /// The notification with state copied, for method chaining. public static T WithStateFrom(this T notification, TSource source) where T : IStatefulNotification where TSource : IStatefulNotification diff --git a/src/Umbraco.Core/Notifications/ObjectNotification.cs b/src/Umbraco.Core/Notifications/ObjectNotification.cs index e7c60c5bbc13..96de75174203 100644 --- a/src/Umbraco.Core/Notifications/ObjectNotification.cs +++ b/src/Umbraco.Core/Notifications/ObjectNotification.cs @@ -5,16 +5,35 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications that carry a target object. +/// +/// The type of the target object associated with this notification. +/// +/// This class extends and provides a strongly-typed target object +/// that represents the entity being operated on. +/// public abstract class ObjectNotification : StatefulNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The target object associated with this notification. + /// The event messages collection. protected ObjectNotification(T target, EventMessages messages) { Messages = messages; Target = target; } + /// + /// Gets the event messages collection associated with this notification. + /// public EventMessages Messages { get; } + /// + /// Gets the target object associated with this notification. + /// protected T Target { get; } } diff --git a/src/Umbraco.Core/Notifications/PartialViewCreatedNotification.cs b/src/Umbraco.Core/Notifications/PartialViewCreatedNotification.cs index 3fe571843d53..ad65e62bb3fa 100644 --- a/src/Umbraco.Core/Notifications/PartialViewCreatedNotification.cs +++ b/src/Umbraco.Core/Notifications/PartialViewCreatedNotification.cs @@ -6,8 +6,20 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after a partial view has been created. +/// +/// +/// This notification is published after a partial view file has been successfully created +/// in the file system. +/// public class PartialViewCreatedNotification : CreatedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The partial view that was created. + /// The event messages collection. public PartialViewCreatedNotification(IPartialView target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/PartialViewCreatingNotification.cs b/src/Umbraco.Core/Notifications/PartialViewCreatingNotification.cs index d53b4eb1c88d..986cdfe25dac 100644 --- a/src/Umbraco.Core/Notifications/PartialViewCreatingNotification.cs +++ b/src/Umbraco.Core/Notifications/PartialViewCreatingNotification.cs @@ -6,8 +6,20 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before a partial view is created. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the create operation +/// by setting to true. +/// public class PartialViewCreatingNotification : CreatingNotification { + /// + /// Initializes a new instance of the class. + /// + /// The partial view being created. + /// The event messages collection. public PartialViewCreatingNotification(IPartialView target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/PartialViewDeletedNotification.cs b/src/Umbraco.Core/Notifications/PartialViewDeletedNotification.cs index 29e1548bf326..102dada0c5f6 100644 --- a/src/Umbraco.Core/Notifications/PartialViewDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/PartialViewDeletedNotification.cs @@ -6,8 +6,20 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after a partial view has been deleted. +/// +/// +/// This notification is published after a partial view file has been successfully deleted +/// from the file system. +/// public class PartialViewDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The partial view that was deleted. + /// The event messages collection. public PartialViewDeletedNotification(IPartialView target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/PartialViewDeletingNotification.cs b/src/Umbraco.Core/Notifications/PartialViewDeletingNotification.cs index 26a6fa86e07b..4fe3d2a25e91 100644 --- a/src/Umbraco.Core/Notifications/PartialViewDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/PartialViewDeletingNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before a partial view is deleted. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation +/// by setting to true. +/// public class PartialViewDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single partial view. + /// + /// The partial view being deleted. + /// The event messages collection. public PartialViewDeletingNotification(IPartialView target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple partial views. + /// + /// The partial views being deleted. + /// The event messages collection. public PartialViewDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/PartialViewSavedNotification.cs b/src/Umbraco.Core/Notifications/PartialViewSavedNotification.cs index e7d0702e021e..54ac1f5862fa 100644 --- a/src/Umbraco.Core/Notifications/PartialViewSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/PartialViewSavedNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after partial views have been saved. +/// +/// +/// This notification is published after partial view files have been successfully saved +/// to the file system. +/// public class PartialViewSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class + /// with a single partial view. + /// + /// The partial view that was saved. + /// The event messages collection. public PartialViewSavedNotification(IPartialView target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple partial views. + /// + /// The partial views that were saved. + /// The event messages collection. public PartialViewSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/PartialViewSavingNotification.cs b/src/Umbraco.Core/Notifications/PartialViewSavingNotification.cs index ee7401c772a5..ce8757b9343d 100644 --- a/src/Umbraco.Core/Notifications/PartialViewSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/PartialViewSavingNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before partial views are saved. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation +/// by setting to true. +/// public class PartialViewSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class + /// with a single partial view. + /// + /// The partial view being saved. + /// The event messages collection. public PartialViewSavingNotification(IPartialView target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple partial views. + /// + /// The partial views being saved. + /// The event messages collection. public PartialViewSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/PostRuntimePremigrationsUpgradeNotification.cs b/src/Umbraco.Core/Notifications/PostRuntimePremigrationsUpgradeNotification.cs index 2cbea10692ca..a804411c12c4 100644 --- a/src/Umbraco.Core/Notifications/PostRuntimePremigrationsUpgradeNotification.cs +++ b/src/Umbraco.Core/Notifications/PostRuntimePremigrationsUpgradeNotification.cs @@ -1,6 +1,15 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after runtime pre-migrations have been applied during upgrade. +/// +/// +/// This notification is published after the pre-migration upgrade steps have completed, +/// allowing handlers to perform post-upgrade actions. +/// public class PostRuntimePremigrationsUpgradeNotification : INotification { - } diff --git a/src/Umbraco.Core/Notifications/PublicAccessCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/PublicAccessCacheRefresherNotification.cs index 223cf16cc340..6611977a68ea 100644 --- a/src/Umbraco.Core/Notifications/PublicAccessCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/PublicAccessCacheRefresherNotification.cs @@ -1,9 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when public access cache needs to be refreshed. +/// +/// +/// This notification is used to synchronize public access cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class PublicAccessCacheRefresherNotification : CacheRefresherNotification { + /// + /// Initializes a new instance of the class. + /// + /// The payload containing information about the public access entries to refresh. + /// The type of cache refresh operation. public PublicAccessCacheRefresherNotification(object messageObject, MessageType messageType) : base(messageObject, messageType) { diff --git a/src/Umbraco.Core/Notifications/PublicAccessEntryDeletedNotification.cs b/src/Umbraco.Core/Notifications/PublicAccessEntryDeletedNotification.cs index a90601cf50e7..ba07deafe2e9 100644 --- a/src/Umbraco.Core/Notifications/PublicAccessEntryDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/PublicAccessEntryDeletedNotification.cs @@ -6,8 +6,20 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after public access entries have been deleted. +/// +/// +/// Public access entries control which content nodes are restricted and require +/// authentication. This notification is published after entries have been deleted. +/// public sealed class PublicAccessEntryDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The public access entry that was deleted. + /// The event messages collection. public PublicAccessEntryDeletedNotification(PublicAccessEntry target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/PublicAccessEntryDeletingNotification.cs b/src/Umbraco.Core/Notifications/PublicAccessEntryDeletingNotification.cs index d135af805b8d..a9eea1f6c8e3 100644 --- a/src/Umbraco.Core/Notifications/PublicAccessEntryDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/PublicAccessEntryDeletingNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before public access entries are deleted. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation +/// by setting to true. +/// public sealed class PublicAccessEntryDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single entry. + /// + /// The public access entry being deleted. + /// The event messages collection. public PublicAccessEntryDeletingNotification(PublicAccessEntry target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple entries. + /// + /// The public access entries being deleted. + /// The event messages collection. public PublicAccessEntryDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/PublicAccessEntrySavedNotification.cs b/src/Umbraco.Core/Notifications/PublicAccessEntrySavedNotification.cs index 1f92d935d7e7..ee487b364daa 100644 --- a/src/Umbraco.Core/Notifications/PublicAccessEntrySavedNotification.cs +++ b/src/Umbraco.Core/Notifications/PublicAccessEntrySavedNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after public access entries have been saved. +/// +/// +/// Public access entries control which content nodes are restricted and require +/// authentication. This notification is published after entries have been saved. +/// public sealed class PublicAccessEntrySavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class + /// with a single entry. + /// + /// The public access entry that was saved. + /// The event messages collection. public PublicAccessEntrySavedNotification(PublicAccessEntry target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple entries. + /// + /// The public access entries that were saved. + /// The event messages collection. public PublicAccessEntrySavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/PublicAccessEntrySavingNotification.cs b/src/Umbraco.Core/Notifications/PublicAccessEntrySavingNotification.cs index 9f9e6f8a4a70..c47960f18136 100644 --- a/src/Umbraco.Core/Notifications/PublicAccessEntrySavingNotification.cs +++ b/src/Umbraco.Core/Notifications/PublicAccessEntrySavingNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before public access entries are saved. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation +/// by setting to true. +/// public sealed class PublicAccessEntrySavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class + /// with a single entry. + /// + /// The public access entry being saved. + /// The event messages collection. public PublicAccessEntrySavingNotification(PublicAccessEntry target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple entries. + /// + /// The public access entries being saved. + /// The event messages collection. public PublicAccessEntrySavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/RelationDeletedNotification.cs b/src/Umbraco.Core/Notifications/RelationDeletedNotification.cs index e459c3e5f263..7c76d8a6c990 100644 --- a/src/Umbraco.Core/Notifications/RelationDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/RelationDeletedNotification.cs @@ -10,6 +10,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class RelationDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class + /// with a single relation. + /// + /// The relation that was deleted. + /// The event messages collection. public RelationDeletedNotification(IRelation target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/RelationDeletingNotification.cs b/src/Umbraco.Core/Notifications/RelationDeletingNotification.cs index 06902cbb4b6a..854c916c2311 100644 --- a/src/Umbraco.Core/Notifications/RelationDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/RelationDeletingNotification.cs @@ -10,6 +10,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class RelationDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single relation. + /// + /// The relation being deleted. + /// The event messages collection. public RelationDeletingNotification(IRelation target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/RelationSavedNotification.cs b/src/Umbraco.Core/Notifications/RelationSavedNotification.cs index dd3cb4ca47f3..9a9c32893fc1 100644 --- a/src/Umbraco.Core/Notifications/RelationSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/RelationSavedNotification.cs @@ -10,6 +10,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class RelationSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class + /// with a single relation. + /// + /// The relation that was saved. + /// The event messages collection. public RelationSavedNotification(IRelation target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/RelationSavingNotification.cs b/src/Umbraco.Core/Notifications/RelationSavingNotification.cs index 7da3b971e872..fc906f0123ee 100644 --- a/src/Umbraco.Core/Notifications/RelationSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/RelationSavingNotification.cs @@ -10,6 +10,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class RelationSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class + /// with a single relation. + /// + /// The relation being saved. + /// The event messages collection. public RelationSavingNotification(IRelation target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/RelationTypeCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/RelationTypeCacheRefresherNotification.cs index 1d816a40679e..560cd98029b2 100644 --- a/src/Umbraco.Core/Notifications/RelationTypeCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/RelationTypeCacheRefresherNotification.cs @@ -1,9 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when relation type cache needs to be refreshed. +/// +/// +/// This notification is used to synchronize relation type cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class RelationTypeCacheRefresherNotification : CacheRefresherNotification { + /// + /// Initializes a new instance of the class. + /// + /// The payload containing information about the relation types to refresh. + /// The type of cache refresh operation. public RelationTypeCacheRefresherNotification(object messageObject, MessageType messageType) : base(messageObject, messageType) { diff --git a/src/Umbraco.Core/Notifications/RelationTypeDeletedNotification.cs b/src/Umbraco.Core/Notifications/RelationTypeDeletedNotification.cs index 467d6295b919..fe37ca5a9c24 100644 --- a/src/Umbraco.Core/Notifications/RelationTypeDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/RelationTypeDeletedNotification.cs @@ -10,6 +10,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class RelationTypeDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class + /// with a single relation type. + /// + /// The relation type that was deleted. + /// The event messages collection. public RelationTypeDeletedNotification(IRelationType target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/RelationTypeDeletingNotification.cs b/src/Umbraco.Core/Notifications/RelationTypeDeletingNotification.cs index 25f8049df3d6..549206428b27 100644 --- a/src/Umbraco.Core/Notifications/RelationTypeDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/RelationTypeDeletingNotification.cs @@ -10,6 +10,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class RelationTypeDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single relation type. + /// + /// The relation type being deleted. + /// The event messages collection. public RelationTypeDeletingNotification(IRelationType target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/RelationTypeSavedNotification.cs b/src/Umbraco.Core/Notifications/RelationTypeSavedNotification.cs index f57c02b90053..3a4297f18eda 100644 --- a/src/Umbraco.Core/Notifications/RelationTypeSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/RelationTypeSavedNotification.cs @@ -10,6 +10,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class RelationTypeSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class + /// with a single relation type. + /// + /// The relation type that was saved. + /// The event messages collection. public RelationTypeSavedNotification(IRelationType target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/RelationTypeSavingNotification.cs b/src/Umbraco.Core/Notifications/RelationTypeSavingNotification.cs index 148deb200fa4..fe7aede5c7b3 100644 --- a/src/Umbraco.Core/Notifications/RelationTypeSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/RelationTypeSavingNotification.cs @@ -10,6 +10,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class RelationTypeSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class + /// with a single relation type. + /// + /// The relation type being saved. + /// The event messages collection. public RelationTypeSavingNotification(IRelationType target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/RemovedMemberRolesNotification.cs b/src/Umbraco.Core/Notifications/RemovedMemberRolesNotification.cs index 1b946b1a398c..70c148a01c0f 100644 --- a/src/Umbraco.Core/Notifications/RemovedMemberRolesNotification.cs +++ b/src/Umbraco.Core/Notifications/RemovedMemberRolesNotification.cs @@ -1,18 +1,21 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IMemberService when the DissociateRoles method is called in the API. +/// Notification that is published after roles have been removed from members. /// +/// +/// This notification is published by the when DissociateRoles method completes. +/// public class RemovedMemberRolesNotification : MemberRolesNotification { /// - /// Initializes a new instance of the . + /// Initializes a new instance of the class. /// - /// - /// Collection of Ids of the members the roles are being removed from. - /// - /// - /// Collection of role names being removed. - /// + /// The IDs of the members the roles are being removed from. + /// The names of the roles being removed. public RemovedMemberRolesNotification(int[] memberIds, string[] roles) : base(memberIds, roles) { diff --git a/src/Umbraco.Core/Notifications/RenamedNotification.cs b/src/Umbraco.Core/Notifications/RenamedNotification.cs index ab25fbdeb96e..a5fb003ab6f8 100644 --- a/src/Umbraco.Core/Notifications/RenamedNotification.cs +++ b/src/Umbraco.Core/Notifications/RenamedNotification.cs @@ -5,17 +5,40 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published after entities have been renamed. +/// +/// The type of entity that was renamed. +/// +/// This notification is published after entities have been successfully renamed, +/// allowing handlers to react for auditing or cache invalidation purposes. +/// public abstract class RenamedNotification : EnumerableObjectNotification { + /// + /// Initializes a new instance of the class + /// with a single entity. + /// + /// The entity that was renamed. + /// The event messages collection. protected RenamedNotification(T target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple entities. + /// + /// The entities that were renamed. + /// The event messages collection. protected RenamedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the entities that were renamed. + /// public IEnumerable Entities => Target; } diff --git a/src/Umbraco.Core/Notifications/RenamingNotification.cs b/src/Umbraco.Core/Notifications/RenamingNotification.cs index 4f15827ae4be..82b7f61f2b17 100644 --- a/src/Umbraco.Core/Notifications/RenamingNotification.cs +++ b/src/Umbraco.Core/Notifications/RenamingNotification.cs @@ -5,17 +5,40 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for cancelable notifications published before entities are renamed. +/// +/// The type of entity being renamed. +/// +/// This notification is cancelable, allowing handlers to prevent the rename operation +/// by setting to true. +/// public abstract class RenamingNotification : CancelableEnumerableObjectNotification { + /// + /// Initializes a new instance of the class + /// with a single entity. + /// + /// The entity being renamed. + /// The event messages collection. protected RenamingNotification(T target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple entities. + /// + /// The entities being renamed. + /// The event messages collection. protected RenamingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the entities being renamed. + /// public IEnumerable Entities => Target; } diff --git a/src/Umbraco.Core/Notifications/RolledBackNotification.cs b/src/Umbraco.Core/Notifications/RolledBackNotification.cs index 280f55538e98..e6f89bff1a52 100644 --- a/src/Umbraco.Core/Notifications/RolledBackNotification.cs +++ b/src/Umbraco.Core/Notifications/RolledBackNotification.cs @@ -5,13 +5,29 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published after an entity has been rolled back to a previous version. +/// +/// The type of entity that was rolled back. +/// +/// This notification is published after the entity has been reverted to its previous state. +/// It is not cancelable since the rollback operation has already completed. +/// public abstract class RolledBackNotification : ObjectNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The entity that was rolled back. + /// The event messages collection. protected RolledBackNotification(T target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the entity that was rolled back. + /// public T Entity => Target; } diff --git a/src/Umbraco.Core/Notifications/RollingBackNotification.cs b/src/Umbraco.Core/Notifications/RollingBackNotification.cs index 3d06d443ea9d..110c85ec6a5c 100644 --- a/src/Umbraco.Core/Notifications/RollingBackNotification.cs +++ b/src/Umbraco.Core/Notifications/RollingBackNotification.cs @@ -5,13 +5,29 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published before an entity is rolled back to a previous version. +/// +/// The type of entity being rolled back. +/// +/// This notification is cancelable, allowing handlers to prevent the rollback operation. +/// The notification is published before the entity is reverted to its previous state. +/// public abstract class RollingBackNotification : CancelableObjectNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The entity being rolled back. + /// The event messages collection. protected RollingBackNotification(T target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the entity being rolled back. + /// public T Entity => Target; } diff --git a/src/Umbraco.Core/Notifications/RuntimePremigrationsUpgradeNotification.cs b/src/Umbraco.Core/Notifications/RuntimePremigrationsUpgradeNotification.cs index e9c9fd85ece7..a5b524b810e2 100644 --- a/src/Umbraco.Core/Notifications/RuntimePremigrationsUpgradeNotification.cs +++ b/src/Umbraco.Core/Notifications/RuntimePremigrationsUpgradeNotification.cs @@ -1,16 +1,40 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when runtime pre-migrations need to be executed during upgrade. +/// +/// +/// Handlers can process this notification to perform pre-migration upgrade steps +/// and set the to indicate the outcome. +/// public class RuntimePremigrationsUpgradeNotification : INotification { + /// + /// Represents the possible results of a pre-migration upgrade operation. + /// public enum PremigrationUpgradeResult { + /// + /// No upgrade was required. + /// NotRequired = 0, + + /// + /// The upgrade encountered errors. + /// HasErrors = 1, + + /// + /// The core upgrade completed successfully. + /// CoreUpgradeComplete = 100, } /// - /// Gets/sets the result of the upgrade + /// Gets or sets the result of the upgrade. /// public PremigrationUpgradeResult UpgradeResult { get; set; } = PremigrationUpgradeResult.NotRequired; } diff --git a/src/Umbraco.Core/Notifications/RuntimeUnattendedUpgradeNotification.cs b/src/Umbraco.Core/Notifications/RuntimeUnattendedUpgradeNotification.cs index fd1fa0211301..93ed00a2cd6d 100644 --- a/src/Umbraco.Core/Notifications/RuntimeUnattendedUpgradeNotification.cs +++ b/src/Umbraco.Core/Notifications/RuntimeUnattendedUpgradeNotification.cs @@ -1,3 +1,6 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; /// @@ -9,11 +12,29 @@ namespace Umbraco.Cms.Core.Notifications; /// public class RuntimeUnattendedUpgradeNotification : INotification { + /// + /// Represents the possible results of an unattended upgrade operation. + /// public enum UpgradeResult { + /// + /// No upgrade was required. + /// NotRequired = 0, + + /// + /// The upgrade encountered errors. + /// HasErrors = 1, + + /// + /// The core upgrade completed successfully. + /// CoreUpgradeComplete = 100, + + /// + /// The package migration completed successfully. + /// PackageMigrationComplete = 101, } diff --git a/src/Umbraco.Core/Notifications/SavedNotification.cs b/src/Umbraco.Core/Notifications/SavedNotification.cs index 655b9b66d10b..9d077b8bbb62 100644 --- a/src/Umbraco.Core/Notifications/SavedNotification.cs +++ b/src/Umbraco.Core/Notifications/SavedNotification.cs @@ -5,17 +5,38 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published after entities have been saved. +/// +/// The type of entities that were saved. +/// +/// This notification is published after the entities have been persisted to the database. +/// It is not cancelable since the save operation has already completed. +/// public abstract class SavedNotification : EnumerableObjectNotification { + /// + /// Initializes a new instance of the class with a single entity. + /// + /// The entity that was saved. + /// The event messages collection. protected SavedNotification(T target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple entities. + /// + /// The collection of entities that were saved. + /// The event messages collection. protected SavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the collection of entities that were saved. + /// public IEnumerable SavedEntities => Target; } diff --git a/src/Umbraco.Core/Notifications/SavingNotification.cs b/src/Umbraco.Core/Notifications/SavingNotification.cs index 9724d4580a7d..c038e0527d58 100644 --- a/src/Umbraco.Core/Notifications/SavingNotification.cs +++ b/src/Umbraco.Core/Notifications/SavingNotification.cs @@ -5,17 +5,38 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published before entities are saved. +/// +/// The type of entities being saved. +/// +/// This notification is cancelable, allowing handlers to prevent the save operation. +/// The notification is published before the entities are persisted to the database. +/// public abstract class SavingNotification : CancelableEnumerableObjectNotification { + /// + /// Initializes a new instance of the class with a single entity. + /// + /// The entity being saved. + /// The event messages collection. protected SavingNotification(T target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple entities. + /// + /// The collection of entities being saved. + /// The event messages collection. protected SavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the collection of entities being saved. + /// public IEnumerable SavedEntities => Target; } diff --git a/src/Umbraco.Core/Notifications/ScaffoldedNotification.cs b/src/Umbraco.Core/Notifications/ScaffoldedNotification.cs index f64bfd39331e..bd835ba97605 100644 --- a/src/Umbraco.Core/Notifications/ScaffoldedNotification.cs +++ b/src/Umbraco.Core/Notifications/ScaffoldedNotification.cs @@ -5,9 +5,23 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for cancelable notifications published when entities are scaffolded (copied). +/// +/// The type of entity being scaffolded. +/// +/// This notification provides both the original entity and the scaffold (copy) being created. +/// public abstract class ScaffoldedNotification : CancelableObjectNotification where T : class { + /// + /// Initializes a new instance of the class. + /// + /// The original entity being copied from. + /// The scaffold (copy) being created. + /// The ID of the parent under which the scaffold will be created. + /// The event messages collection. protected ScaffoldedNotification(T original, T scaffold, int parentId, EventMessages messages) : base(original, messages) { @@ -15,9 +29,18 @@ protected ScaffoldedNotification(T original, T scaffold, int parentId, EventMess ParentId = parentId; } + /// + /// Gets the original entity being copied from. + /// public T Original => Target; + /// + /// Gets the scaffold (copy) being created. + /// public T Scaffold { get; } + /// + /// Gets the ID of the parent under which the scaffold will be created. + /// public int ParentId { get; } } diff --git a/src/Umbraco.Core/Notifications/ScopedEntityRemoveNotification.cs b/src/Umbraco.Core/Notifications/ScopedEntityRemoveNotification.cs index f72af376c311..d4678da0ada3 100644 --- a/src/Umbraco.Core/Notifications/ScopedEntityRemoveNotification.cs +++ b/src/Umbraco.Core/Notifications/ScopedEntityRemoveNotification.cs @@ -1,17 +1,35 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using System.ComponentModel; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when an entity is removed within a scope. +/// +/// +/// This notification is used internally for cache synchronization purposes. +/// For normal entity operations, use tree change notifications instead. +/// [Obsolete("This is only used for the internal cache and will change, use tree change notifications instead")] [EditorBrowsable(EditorBrowsableState.Never)] public class ScopedEntityRemoveNotification : ObjectNotification { + /// + /// Initializes a new instance of the class. + /// + /// The entity being removed. + /// The event messages collection. public ScopedEntityRemoveNotification(IContentBase target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the entity being removed. + /// public IContentBase Entity => Target; } diff --git a/src/Umbraco.Core/Notifications/ScriptDeletedNotification.cs b/src/Umbraco.Core/Notifications/ScriptDeletedNotification.cs index 9dea26abfd50..8473512df247 100644 --- a/src/Umbraco.Core/Notifications/ScriptDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/ScriptDeletedNotification.cs @@ -10,6 +10,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class ScriptDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class + /// with a single script. + /// + /// The script that was deleted. + /// The event messages collection. public ScriptDeletedNotification(IScript target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ScriptDeletingNotification.cs b/src/Umbraco.Core/Notifications/ScriptDeletingNotification.cs index abab6ad91585..75f8efe830ec 100644 --- a/src/Umbraco.Core/Notifications/ScriptDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/ScriptDeletingNotification.cs @@ -10,11 +10,23 @@ namespace Umbraco.Cms.Core.Notifications; /// public class ScriptDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single script. + /// + /// The script being deleted. + /// The event messages collection. public ScriptDeletingNotification(IScript target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple scripts. + /// + /// The scripts being deleted. + /// The event messages collection. public ScriptDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ScriptSavedNotification.cs b/src/Umbraco.Core/Notifications/ScriptSavedNotification.cs index ee4f488a6aa9..3b82583601e1 100644 --- a/src/Umbraco.Core/Notifications/ScriptSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/ScriptSavedNotification.cs @@ -5,16 +5,31 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IFileService when the SaveScript method is called in the API, after the script has been saved. +/// Notification that is published after a script file has been saved. /// +/// +/// This notification is published by the after the script has been persisted. +/// It is not cancelable since the save operation has already completed. +/// public class ScriptSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class with a single script. + /// + /// The script that was saved. + /// The event messages collection. public ScriptSavedNotification(IScript target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple scripts. + /// + /// The collection of scripts that were saved. + /// The event messages collection. public ScriptSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/ScriptSavingNotification.cs b/src/Umbraco.Core/Notifications/ScriptSavingNotification.cs index c812cd094dea..ceee224cfc08 100644 --- a/src/Umbraco.Core/Notifications/ScriptSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/ScriptSavingNotification.cs @@ -5,16 +5,31 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IFileService when the SaveScript method is called in the API. +/// Notification that is published before a script file is saved. /// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation. +/// The notification is published by the before the script is persisted. +/// public class ScriptSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class with a single script. + /// + /// The script being saved. + /// The event messages collection. public ScriptSavingNotification(IScript target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple scripts. + /// + /// The collection of scripts being saved. + /// The event messages collection. public ScriptSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/SendEmailNotification.cs b/src/Umbraco.Core/Notifications/SendEmailNotification.cs index 66d7ee038aa2..ad82d8970f7b 100644 --- a/src/Umbraco.Core/Notifications/SendEmailNotification.cs +++ b/src/Umbraco.Core/Notifications/SendEmailNotification.cs @@ -1,15 +1,34 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Models.Email; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when an email needs to be sent. +/// +/// +/// Handlers can intercept this notification to provide custom email sending logic +/// or to modify the email before it is sent. Call to indicate +/// that the email has been handled and should not be processed by the default handler. +/// public class SendEmailNotification : INotification { + /// + /// Initializes a new instance of the class. + /// + /// The email message to send. + /// Metadata about the type of email being sent. public SendEmailNotification(NotificationEmailModel message, string emailType) { Message = message; EmailType = emailType; } + /// + /// Gets the email message to send. + /// public NotificationEmailModel Message { get; } /// diff --git a/src/Umbraco.Core/Notifications/SortedNotification.cs b/src/Umbraco.Core/Notifications/SortedNotification.cs index 49910f82238a..3f25b3bcd8ca 100644 --- a/src/Umbraco.Core/Notifications/SortedNotification.cs +++ b/src/Umbraco.Core/Notifications/SortedNotification.cs @@ -5,12 +5,28 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published after entities have been sorted. +/// +/// The type of entities that were sorted. +/// +/// This notification is published after the new sort order has been persisted. +/// It is not cancelable since the sort operation has already completed. +/// public abstract class SortedNotification : EnumerableObjectNotification { + /// + /// Initializes a new instance of the class. + /// + /// The collection of entities that were sorted. + /// The event messages collection. protected SortedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the collection of entities that were sorted. + /// public IEnumerable SortedEntities => Target; } diff --git a/src/Umbraco.Core/Notifications/SortingNotification.cs b/src/Umbraco.Core/Notifications/SortingNotification.cs index 26e735f91b65..9f700dd0b028 100644 --- a/src/Umbraco.Core/Notifications/SortingNotification.cs +++ b/src/Umbraco.Core/Notifications/SortingNotification.cs @@ -5,12 +5,28 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications published before entities are sorted. +/// +/// The type of entities being sorted. +/// +/// This notification is cancelable, allowing handlers to prevent the sort operation. +/// The notification is published before the new sort order is persisted. +/// public abstract class SortingNotification : CancelableEnumerableObjectNotification { + /// + /// Initializes a new instance of the class. + /// + /// The collection of entities being sorted. + /// The event messages collection. protected SortingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the collection of entities being sorted. + /// public IEnumerable SortedEntities => Target; } diff --git a/src/Umbraco.Core/Notifications/StatefulNotification.cs b/src/Umbraco.Core/Notifications/StatefulNotification.cs index 5f84000d48af..377cb7a46e96 100644 --- a/src/Umbraco.Core/Notifications/StatefulNotification.cs +++ b/src/Umbraco.Core/Notifications/StatefulNotification.cs @@ -1,15 +1,26 @@ // Copyright (c) Umbraco. +// See LICENSE for more details. namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications that can carry state between "ing" (before) and "ed" (after) notifications. +/// +/// +/// This class implements and provides a dictionary for storing +/// custom state data that persists between paired notifications (e.g., ContentSaving and ContentSaved). +/// public abstract class StatefulNotification : IStatefulNotification { private IDictionary? _state; /// - /// This can be used by event subscribers to store state in the notification so they easily deal with custom state data - /// between a starting ("ing") and an ending ("ed") notification + /// Gets or sets a dictionary for storing custom state data. /// + /// + /// This can be used by event subscribers to store state in the notification so they easily deal with custom state data + /// between a starting ("ing") and an ending ("ed") notification. + /// public IDictionary State { get => _state ??= new Dictionary(); diff --git a/src/Umbraco.Core/Notifications/StylesheetDeletedNotification.cs b/src/Umbraco.Core/Notifications/StylesheetDeletedNotification.cs index de6b57c7b357..3d6edec74a79 100644 --- a/src/Umbraco.Core/Notifications/StylesheetDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/StylesheetDeletedNotification.cs @@ -10,6 +10,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class StylesheetDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class + /// with a single stylesheet. + /// + /// The stylesheet that was deleted. + /// The event messages collection. public StylesheetDeletedNotification(IStylesheet target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/StylesheetDeletingNotification.cs b/src/Umbraco.Core/Notifications/StylesheetDeletingNotification.cs index 38b58e380ba3..44750f86f086 100644 --- a/src/Umbraco.Core/Notifications/StylesheetDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/StylesheetDeletingNotification.cs @@ -10,11 +10,23 @@ namespace Umbraco.Cms.Core.Notifications; /// public class StylesheetDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single stylesheet. + /// + /// The stylesheet being deleted. + /// The event messages collection. public StylesheetDeletingNotification(IStylesheet target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple stylesheets. + /// + /// The stylesheets being deleted. + /// The event messages collection. public StylesheetDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/StylesheetSavedNotification.cs b/src/Umbraco.Core/Notifications/StylesheetSavedNotification.cs index 6d5ed9d471d9..7c9e253a8fd3 100644 --- a/src/Umbraco.Core/Notifications/StylesheetSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/StylesheetSavedNotification.cs @@ -1,20 +1,35 @@ // Copyright (c) Umbraco. -// See LICENSE for more details +// See LICENSE for more details. using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IFileService when the SaveStyleSheet method is called in the API, after the script has been saved. +/// Notification that is published after a stylesheet has been saved. /// +/// +/// This notification is published by the after the stylesheet has been persisted. +/// It is not cancelable since the save operation has already completed. +/// public class StylesheetSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class with a single stylesheet. + /// + /// The stylesheet that was saved. + /// The event messages collection. public StylesheetSavedNotification(IStylesheet target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple stylesheets. + /// + /// The collection of stylesheets that were saved. + /// The event messages collection. public StylesheetSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/StylesheetSavingNotification.cs b/src/Umbraco.Core/Notifications/StylesheetSavingNotification.cs index f2b0171251af..fa065839c3d3 100644 --- a/src/Umbraco.Core/Notifications/StylesheetSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/StylesheetSavingNotification.cs @@ -1,20 +1,35 @@ // Copyright (c) Umbraco. -// See LICENSE for more details +// See LICENSE for more details. using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IFileService when the SaveStyleSheet method is called in the API. +/// Notification that is published before a stylesheet is saved. /// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation. +/// The notification is published by the before the stylesheet is persisted. +/// public class StylesheetSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class with a single stylesheet. + /// + /// The stylesheet being saved. + /// The event messages collection. public StylesheetSavingNotification(IStylesheet target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple stylesheets. + /// + /// The collection of stylesheets being saved. + /// The event messages collection. public StylesheetSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/TemplateCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/TemplateCacheRefresherNotification.cs index a8b119390f0b..c0219a82e4a6 100644 --- a/src/Umbraco.Core/Notifications/TemplateCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/TemplateCacheRefresherNotification.cs @@ -1,9 +1,24 @@ -using Umbraco.Cms.Core.Sync; +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when template cache needs to be refreshed. +/// +/// +/// This notification is used to synchronize template cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class TemplateCacheRefresherNotification : CacheRefresherNotification { + /// + /// Initializes a new instance of the class. + /// + /// The payload containing information about the templates to refresh. + /// The type of cache refresh operation. public TemplateCacheRefresherNotification(object messageObject, MessageType messageType) : base(messageObject, messageType) { diff --git a/src/Umbraco.Core/Notifications/TemplateDeletedNotification.cs b/src/Umbraco.Core/Notifications/TemplateDeletedNotification.cs index 919cdb1157d1..d07f4646475e 100644 --- a/src/Umbraco.Core/Notifications/TemplateDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/TemplateDeletedNotification.cs @@ -10,6 +10,12 @@ namespace Umbraco.Cms.Core.Notifications; /// public class TemplateDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class + /// with a single template. + /// + /// The template that was deleted. + /// The event messages collection. public TemplateDeletedNotification(ITemplate target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/TemplateDeletingNotification.cs b/src/Umbraco.Core/Notifications/TemplateDeletingNotification.cs index 406a04917345..a84ae3ffcbe6 100644 --- a/src/Umbraco.Core/Notifications/TemplateDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/TemplateDeletingNotification.cs @@ -10,11 +10,23 @@ namespace Umbraco.Cms.Core.Notifications; /// public class TemplateDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single template. + /// + /// The template being deleted. + /// The event messages collection. public TemplateDeletingNotification(ITemplate target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple templates. + /// + /// The templates being deleted. + /// The event messages collection. public TemplateDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/TemplateSavedNotification.cs b/src/Umbraco.Core/Notifications/TemplateSavedNotification.cs index 905c99efb986..4f8b5b36a892 100644 --- a/src/Umbraco.Core/Notifications/TemplateSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/TemplateSavedNotification.cs @@ -5,24 +5,40 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IFileService when the SaveTemplate method is called in the API, after the template has been saved. +/// A notification that is used to trigger the IFileService when the SaveTemplate method is called in the API, after the template has been saved. /// public class TemplateSavedNotification : SavedNotification { private const string TemplateForContentTypeKey = "CreateTemplateForContentType"; private const string ContentTypeAliasKey = "ContentTypeAlias"; + /// + /// Initializes a new instance of the class + /// with a single template. + /// + /// The template that was saved. + /// The event messages collection. public TemplateSavedNotification(ITemplate target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple templates. + /// + /// The templates that were saved. + /// The event messages collection. public TemplateSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { } + /// + /// Gets or sets a value indicating whether the template was created for a content type. + /// public bool CreateTemplateForContentType { get @@ -49,6 +65,12 @@ public bool CreateTemplateForContentType } } + /// + /// Gets or sets the alias of the content type the template was created for. + /// + /// + /// This is used when creating a document type with a template. It is not recommended to change or set this value. + /// public string? ContentTypeAlias { get diff --git a/src/Umbraco.Core/Notifications/TemplateSavingNotification.cs b/src/Umbraco.Core/Notifications/TemplateSavingNotification.cs index bc8aa577ceda..8654c3181ec4 100644 --- a/src/Umbraco.Core/Notifications/TemplateSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/TemplateSavingNotification.cs @@ -5,19 +5,36 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the IFileService when the SaveTemplate method is called in the API. +/// A notification that is used to trigger the IFileService when the SaveTemplate method is called in the API. /// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation +/// by setting to true. +/// public class TemplateSavingNotification : SavingNotification { private const string TemplateForContentTypeKey = "CreateTemplateForContentType"; private const string ContentTypeAliasKey = "ContentTypeAlias"; + /// + /// Initializes a new instance of the class + /// with a single template. + /// + /// The template being saved. + /// The event messages collection. public TemplateSavingNotification(ITemplate target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple templates. + /// + /// The templates being saved. + /// The event messages collection. public TemplateSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { @@ -66,6 +83,9 @@ public TemplateSavingNotification(IEnumerable target, EventMessages m ContentTypeAlias = contentTypeAlias; } + /// + /// Gets or sets a value indicating whether the template is being created for a content type. + /// public bool CreateTemplateForContentType { get @@ -92,6 +112,12 @@ public bool CreateTemplateForContentType } } + /// + /// Gets or sets the alias of the content type the template is for. + /// + /// + /// This is used when creating a document type with a template. It is not recommended to change or set this value. + /// public string? ContentTypeAlias { get diff --git a/src/Umbraco.Core/Notifications/TreeChangeNotification.cs b/src/Umbraco.Core/Notifications/TreeChangeNotification.cs index 2187f726597f..633ee7d6aa08 100644 --- a/src/Umbraco.Core/Notifications/TreeChangeNotification.cs +++ b/src/Umbraco.Core/Notifications/TreeChangeNotification.cs @@ -1,19 +1,45 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Services.Changes; namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for notifications related to tree structure changes. +/// +/// The type of entity in the tree. +/// +/// Tree change notifications are published when entities are added, removed, moved, or have their +/// structure modified in a hierarchical tree. They are used for cache invalidation and tree synchronization. +/// public abstract class TreeChangeNotification : EnumerableObjectNotification> { + /// + /// Initializes a new instance of the class + /// with a single tree change. + /// + /// The tree change that occurred. + /// The event messages collection. protected TreeChangeNotification(TreeChange target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple tree changes. + /// + /// The collection of tree changes that occurred. + /// The event messages collection. protected TreeChangeNotification(IEnumerable> target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the tree changes that occurred. + /// public IEnumerable> Changes => Target; } diff --git a/src/Umbraco.Core/Notifications/UmbracoApplicationStartedNotification.cs b/src/Umbraco.Core/Notifications/UmbracoApplicationStartedNotification.cs index 1e3f2b7bfd5e..f9607580bab9 100644 --- a/src/Umbraco.Core/Notifications/UmbracoApplicationStartedNotification.cs +++ b/src/Umbraco.Core/Notifications/UmbracoApplicationStartedNotification.cs @@ -1,15 +1,22 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; /// /// Notification that occurs when Umbraco has completely booted up and the request processing pipeline is configured. /// -/// +/// +/// This notification is published after Umbraco has fully started and is ready to process requests. +/// Use this notification for initialization tasks that depend on Umbraco being fully operational. +/// +/// public class UmbracoApplicationStartedNotification : IUmbracoApplicationLifetimeNotification { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// Indicates whether Umbraco is restarting. + /// A value indicating whether Umbraco is restarting. public UmbracoApplicationStartedNotification(bool isRestarting) => IsRestarting = isRestarting; /// diff --git a/src/Umbraco.Core/Notifications/UmbracoApplicationStartingNotification.cs b/src/Umbraco.Core/Notifications/UmbracoApplicationStartingNotification.cs index 63c733f3cb77..a830175d9fe4 100644 --- a/src/Umbraco.Core/Notifications/UmbracoApplicationStartingNotification.cs +++ b/src/Umbraco.Core/Notifications/UmbracoApplicationStartingNotification.cs @@ -1,15 +1,22 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; /// -/// Notification that occurs at the very end of the Umbraco boot process (after all components are initialized). +/// Notification that occurs at the very end of the Umbraco boot process (after all components are initialized). /// +/// +/// This notification is published during the application startup phase, before the request pipeline is fully configured. +/// Use if you need to perform actions after Umbraco is fully started. +/// public class UmbracoApplicationStartingNotification : IUmbracoApplicationLifetimeNotification { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The runtime level - /// Indicates whether Umbraco is restarting. + /// The current runtime level of the application. + /// A value indicating whether Umbraco is restarting. public UmbracoApplicationStartingNotification(RuntimeLevel runtimeLevel, bool isRestarting) { RuntimeLevel = runtimeLevel; @@ -17,11 +24,8 @@ public UmbracoApplicationStartingNotification(RuntimeLevel runtimeLevel, bool is } /// - /// Gets the runtime level. + /// Gets the current runtime level of the application. /// - /// - /// The runtime level. - /// public RuntimeLevel RuntimeLevel { get; } /// diff --git a/src/Umbraco.Core/Notifications/UmbracoApplicationStoppedNotification.cs b/src/Umbraco.Core/Notifications/UmbracoApplicationStoppedNotification.cs index ce9936a137fb..0eee2d42a582 100644 --- a/src/Umbraco.Core/Notifications/UmbracoApplicationStoppedNotification.cs +++ b/src/Umbraco.Core/Notifications/UmbracoApplicationStoppedNotification.cs @@ -1,15 +1,22 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; /// /// Notification that occurs when Umbraco has completely shutdown. /// -/// +/// +/// This notification is published after Umbraco has fully stopped. +/// Use this notification for final cleanup or logging after shutdown. +/// +/// public class UmbracoApplicationStoppedNotification : IUmbracoApplicationLifetimeNotification { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// Indicates whether Umbraco is restarting. + /// A value indicating whether Umbraco is restarting. public UmbracoApplicationStoppedNotification(bool isRestarting) => IsRestarting = isRestarting; /// diff --git a/src/Umbraco.Core/Notifications/UmbracoApplicationStoppingNotification.cs b/src/Umbraco.Core/Notifications/UmbracoApplicationStoppingNotification.cs index 43058fe27f09..045c4896fe03 100644 --- a/src/Umbraco.Core/Notifications/UmbracoApplicationStoppingNotification.cs +++ b/src/Umbraco.Core/Notifications/UmbracoApplicationStoppingNotification.cs @@ -1,14 +1,21 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; /// -/// Notification that occurs when Umbraco is shutting down (after all components are terminated). +/// Notification that occurs when Umbraco is shutting down (after all components are terminated). /// +/// +/// This notification is published during the application shutdown phase. +/// Use this notification to perform cleanup tasks before Umbraco stops. +/// public class UmbracoApplicationStoppingNotification : IUmbracoApplicationLifetimeNotification { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// Indicates whether Umbraco is restarting. + /// A value indicating whether Umbraco is restarting. public UmbracoApplicationStoppingNotification(bool isRestarting) => IsRestarting = isRestarting; diff --git a/src/Umbraco.Core/Notifications/UserCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/UserCacheRefresherNotification.cs index 81003d1eb32c..b1a5b45b1a5d 100644 --- a/src/Umbraco.Core/Notifications/UserCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/UserCacheRefresherNotification.cs @@ -1,20 +1,24 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; + /// -/// A notification that is used to trigger the User Cache Refresher. +/// Notification that triggers the user cache refresher. /// +/// +/// This notification is used to synchronize user cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class UserCacheRefresherNotification : CacheRefresherNotification { /// - /// Initializes a new instance of the + /// Initializes a new instance of the class. /// - /// - /// The refresher payload. - /// - /// - /// Type of the cache refresher message, - /// + /// The payload containing information about the user to refresh. + /// The type of cache refresh operation. public UserCacheRefresherNotification(object messageObject, MessageType messageType) : base(messageObject, messageType) { diff --git a/src/Umbraco.Core/Notifications/UserDeletedNotification.cs b/src/Umbraco.Core/Notifications/UserDeletedNotification.cs index a5d89bf1674b..775467e50ab6 100644 --- a/src/Umbraco.Core/Notifications/UserDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/UserDeletedNotification.cs @@ -6,8 +6,20 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published after a user has been deleted. +/// +/// +/// This notification is published by the after the user has been removed. +/// It is not cancelable since the delete operation has already completed. +/// public sealed class UserDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class with a single user. + /// + /// The user that was deleted. + /// The event messages collection. public UserDeletedNotification(IUser target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/UserDeletingNotification.cs b/src/Umbraco.Core/Notifications/UserDeletingNotification.cs index 611f8aa0ea22..be50efb34653 100644 --- a/src/Umbraco.Core/Notifications/UserDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/UserDeletingNotification.cs @@ -6,13 +6,30 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published before a user is deleted. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation. +/// The notification is published by the before the user is removed. +/// public sealed class UserDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class with a single user. + /// + /// The user being deleted. + /// The event messages collection. public UserDeletingNotification(IUser target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple users. + /// + /// The collection of users being deleted. + /// The event messages collection. public UserDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/UserForgotPasswordChangedNotification.cs b/src/Umbraco.Core/Notifications/UserForgotPasswordChangedNotification.cs index b40e902e104b..7ba540e25ec5 100644 --- a/src/Umbraco.Core/Notifications/UserForgotPasswordChangedNotification.cs +++ b/src/Umbraco.Core/Notifications/UserForgotPasswordChangedNotification.cs @@ -1,7 +1,23 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when a user's password has been changed via the "forgot password" flow. +/// +/// +/// This notification is published after a user has successfully changed their password +/// through the password reset mechanism. +/// public class UserForgotPasswordChangedNotification : UserNotification { + /// + /// Initializes a new instance of the class. + /// + /// The source IP address of the user changing the password. + /// The ID of the user whose password was changed. + /// The ID of the user performing the password change. public UserForgotPasswordChangedNotification(string ipAddress, string affectedUserId, string performingUserId) : base(ipAddress, affectedUserId, performingUserId) { diff --git a/src/Umbraco.Core/Notifications/UserForgotPasswordRequestedNotification.cs b/src/Umbraco.Core/Notifications/UserForgotPasswordRequestedNotification.cs index 6181a33809bf..cf618efa524a 100644 --- a/src/Umbraco.Core/Notifications/UserForgotPasswordRequestedNotification.cs +++ b/src/Umbraco.Core/Notifications/UserForgotPasswordRequestedNotification.cs @@ -1,7 +1,23 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when a user requests a password reset via the "forgot password" flow. +/// +/// +/// This notification is published when a user initiates the password reset process, +/// before the reset email is sent. +/// public class UserForgotPasswordRequestedNotification : UserNotification { + /// + /// Initializes a new instance of the class. + /// + /// The source IP address of the user requesting the password reset. + /// The ID of the user requesting the password reset. + /// The ID of the user performing the request. public UserForgotPasswordRequestedNotification(string ipAddress, string affectedUserId, string performingUserId) : base(ipAddress, affectedUserId, performingUserId) { diff --git a/src/Umbraco.Core/Notifications/UserGroupCacheRefresherNotification.cs b/src/Umbraco.Core/Notifications/UserGroupCacheRefresherNotification.cs index d8e519ee9daa..dccea84f5084 100644 --- a/src/Umbraco.Core/Notifications/UserGroupCacheRefresherNotification.cs +++ b/src/Umbraco.Core/Notifications/UserGroupCacheRefresherNotification.cs @@ -1,9 +1,24 @@ -using Umbraco.Cms.Core.Sync; +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using Umbraco.Cms.Core.Sync; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when user group cache needs to be refreshed. +/// +/// +/// This notification is used to synchronize user group cache invalidation across +/// multiple servers in a load-balanced environment. +/// public class UserGroupCacheRefresherNotification : CacheRefresherNotification { + /// + /// Initializes a new instance of the class. + /// + /// The payload containing information about the user groups to refresh. + /// The type of cache refresh operation. public UserGroupCacheRefresherNotification(object messageObject, MessageType messageType) : base(messageObject, messageType) { diff --git a/src/Umbraco.Core/Notifications/UserGroupDeletedNotification.cs b/src/Umbraco.Core/Notifications/UserGroupDeletedNotification.cs index cbbaa583ff8c..cf1d746e75f3 100644 --- a/src/Umbraco.Core/Notifications/UserGroupDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/UserGroupDeletedNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after user groups have been deleted. +/// +/// +/// This notification is published after user groups have been successfully deleted, +/// allowing handlers to react for auditing or cache invalidation purposes. +/// public sealed class UserGroupDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class + /// with a single user group. + /// + /// The user group that was deleted. + /// The event messages collection. public UserGroupDeletedNotification(IUserGroup target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple user groups. + /// + /// The user groups that were deleted. + /// The event messages collection. public UserGroupDeletedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/UserGroupDeletingNotification.cs b/src/Umbraco.Core/Notifications/UserGroupDeletingNotification.cs index aea73393abce..533c79ddc6c5 100644 --- a/src/Umbraco.Core/Notifications/UserGroupDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/UserGroupDeletingNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before user groups are deleted. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation +/// by setting to true. +/// public sealed class UserGroupDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single user group. + /// + /// The user group being deleted. + /// The event messages collection. public UserGroupDeletingNotification(IUserGroup target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple user groups. + /// + /// The user groups being deleted. + /// The event messages collection. public UserGroupDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/UserGroupSavedNotification.cs b/src/Umbraco.Core/Notifications/UserGroupSavedNotification.cs index aa4484c3d341..50f2e50ae12c 100644 --- a/src/Umbraco.Core/Notifications/UserGroupSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/UserGroupSavedNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after user groups have been saved. +/// +/// +/// This notification is published after user groups have been successfully saved, +/// allowing handlers to react for auditing or cache invalidation purposes. +/// public sealed class UserGroupSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class + /// with a single user group. + /// + /// The user group that was saved. + /// The event messages collection. public UserGroupSavedNotification(IUserGroup target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple user groups. + /// + /// The user groups that were saved. + /// The event messages collection. public UserGroupSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/UserGroupSavingNotification.cs b/src/Umbraco.Core/Notifications/UserGroupSavingNotification.cs index 06c82c0298d3..eb4aca4cc019 100644 --- a/src/Umbraco.Core/Notifications/UserGroupSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/UserGroupSavingNotification.cs @@ -6,13 +6,32 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before user groups are saved. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation +/// by setting to true. +/// public sealed class UserGroupSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class + /// with a single user group. + /// + /// The user group being saved. + /// The event messages collection. public UserGroupSavingNotification(IUserGroup target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple user groups. + /// + /// The user groups being saved. + /// The event messages collection. public UserGroupSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/UserGroupWithUsersSavedNotification.cs b/src/Umbraco.Core/Notifications/UserGroupWithUsersSavedNotification.cs index 399d1946908f..82f63365c3b5 100644 --- a/src/Umbraco.Core/Notifications/UserGroupWithUsersSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/UserGroupWithUsersSavedNotification.cs @@ -5,13 +5,31 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after user groups with their associated users have been saved. +/// +/// +/// This notification includes both the user group and the users assigned to it. +/// public sealed class UserGroupWithUsersSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class + /// with a single user group with users. + /// + /// The user group with users that was saved. + /// The event messages collection. public UserGroupWithUsersSavedNotification(UserGroupWithUsers target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple user groups with users. + /// + /// The user groups with users that were saved. + /// The event messages collection. public UserGroupWithUsersSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/UserGroupWithUsersSavingNotification.cs b/src/Umbraco.Core/Notifications/UserGroupWithUsersSavingNotification.cs index c34d66841c1a..38ca8cc97f02 100644 --- a/src/Umbraco.Core/Notifications/UserGroupWithUsersSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/UserGroupWithUsersSavingNotification.cs @@ -5,8 +5,21 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before user groups with their associated users are saved. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation +/// by setting to true. +/// public sealed class UserGroupWithUsersSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class + /// with a single user group with users. + /// + /// The user group with users being saved. + /// The event messages collection. public UserGroupWithUsersSavingNotification(UserGroupWithUsers target, EventMessages messages) : base( target, @@ -14,6 +27,12 @@ public UserGroupWithUsersSavingNotification(UserGroupWithUsers target, EventMess { } + /// + /// Initializes a new instance of the class + /// with multiple user groups with users. + /// + /// The user groups with users being saved. + /// The event messages collection. public UserGroupWithUsersSavingNotification(IEnumerable target, EventMessages messages) : base( target, messages) diff --git a/src/Umbraco.Core/Notifications/UserLockedNotification.cs b/src/Umbraco.Core/Notifications/UserLockedNotification.cs index 81fc798f639f..169454239289 100644 --- a/src/Umbraco.Core/Notifications/UserLockedNotification.cs +++ b/src/Umbraco.Core/Notifications/UserLockedNotification.cs @@ -1,7 +1,23 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published after a user account has been locked. +/// +/// +/// This notification is useful for audit logging and security monitoring purposes. +/// A user account may be locked after too many failed login attempts or by an administrator. +/// public class UserLockedNotification : UserNotification { + /// + /// Initializes a new instance of the class. + /// + /// The source IP address associated with the lock. + /// The ID of the user whose account was locked. + /// The ID of the user or system that locked the account. public UserLockedNotification(string ipAddress, string? affectedUserId, string performingUserId) : base(ipAddress, affectedUserId, performingUserId) { diff --git a/src/Umbraco.Core/Notifications/UserLoginFailedNotification.cs b/src/Umbraco.Core/Notifications/UserLoginFailedNotification.cs index a8cb3e9cc448..77f677735f7b 100644 --- a/src/Umbraco.Core/Notifications/UserLoginFailedNotification.cs +++ b/src/Umbraco.Core/Notifications/UserLoginFailedNotification.cs @@ -1,7 +1,22 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published when a user login attempt fails. +/// +/// +/// This notification is useful for audit logging, security monitoring, and detecting potential brute-force attacks. +/// public class UserLoginFailedNotification : UserNotification { + /// + /// Initializes a new instance of the class. + /// + /// The source IP address of the failed login attempt. + /// The ID of the user whose login failed. + /// The ID of the user attempting the login. public UserLoginFailedNotification(string ipAddress, string affectedUserId, string performingUserId) : base( ipAddress, affectedUserId, performingUserId) diff --git a/src/Umbraco.Core/Notifications/UserLoginRequiresVerificationNotification.cs b/src/Umbraco.Core/Notifications/UserLoginRequiresVerificationNotification.cs index 57f037712c69..72378793909e 100644 --- a/src/Umbraco.Core/Notifications/UserLoginRequiresVerificationNotification.cs +++ b/src/Umbraco.Core/Notifications/UserLoginRequiresVerificationNotification.cs @@ -1,7 +1,23 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published when a user login requires additional verification (e.g., two-factor authentication). +/// +/// +/// This notification is published when a user successfully provides their credentials but +/// needs to complete an additional verification step before being fully logged in. +/// public class UserLoginRequiresVerificationNotification : UserNotification { + /// + /// Initializes a new instance of the class. + /// + /// The source IP address of the user. + /// The ID of the user requiring verification. + /// The ID of the user performing the login action. public UserLoginRequiresVerificationNotification(string ipAddress, string? affectedUserId, string performingUserId) : base(ipAddress, affectedUserId, performingUserId) { diff --git a/src/Umbraco.Core/Notifications/UserLoginSuccessNotification.cs b/src/Umbraco.Core/Notifications/UserLoginSuccessNotification.cs index 5b20ca48ef86..e508cc268b75 100644 --- a/src/Umbraco.Core/Notifications/UserLoginSuccessNotification.cs +++ b/src/Umbraco.Core/Notifications/UserLoginSuccessNotification.cs @@ -1,7 +1,22 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published after a user has successfully logged in. +/// +/// +/// This notification is useful for audit logging and security monitoring purposes. +/// public class UserLoginSuccessNotification : UserNotification { + /// + /// Initializes a new instance of the class. + /// + /// The source IP address of the user logging in. + /// The ID of the user who logged in. + /// The ID of the user performing the login action. public UserLoginSuccessNotification(string ipAddress, string affectedUserId, string performingUserId) : base(ipAddress, affectedUserId, performingUserId) { diff --git a/src/Umbraco.Core/Notifications/UserLogoutSuccessNotification.cs b/src/Umbraco.Core/Notifications/UserLogoutSuccessNotification.cs index c93d42accf97..80eced507770 100644 --- a/src/Umbraco.Core/Notifications/UserLogoutSuccessNotification.cs +++ b/src/Umbraco.Core/Notifications/UserLogoutSuccessNotification.cs @@ -1,11 +1,32 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published after a user has successfully logged out. +/// +/// +/// This notification is useful for audit logging and implementing custom sign-out redirect behavior. +/// public class UserLogoutSuccessNotification : UserNotification { + /// + /// Initializes a new instance of the class. + /// + /// The source IP address of the user logging out. + /// The ID of the user who logged out. + /// The ID of the user performing the logout action. public UserLogoutSuccessNotification(string ipAddress, string? affectedUserId, string performingUserId) : base(ipAddress, affectedUserId, performingUserId) { } + /// + /// Gets or sets the URL to redirect to after sign-out. + /// + /// + /// Handlers can set this property to customize the redirect URL after the user logs out. + /// public string? SignOutRedirectUrl { get; set; } } diff --git a/src/Umbraco.Core/Notifications/UserNotification.cs b/src/Umbraco.Core/Notifications/UserNotification.cs index 6141cdf389e0..0faa5d922464 100644 --- a/src/Umbraco.Core/Notifications/UserNotification.cs +++ b/src/Umbraco.Core/Notifications/UserNotification.cs @@ -1,7 +1,23 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Abstract base class for user-related notifications such as login, logout, password changes, and locking. +/// +/// +/// This class provides common properties for tracking the user action, the affected user, +/// and the performing user for audit and security logging purposes. +/// public abstract class UserNotification : INotification { + /// + /// Initializes a new instance of the class. + /// + /// The source IP address of the user performing the action. + /// The ID of the user affected by this action. + /// The ID of the user performing this action. protected UserNotification(string ipAddress, string? affectedUserId, string performingUserId) { DateTimeUtc = DateTime.UtcNow; @@ -11,22 +27,25 @@ protected UserNotification(string ipAddress, string? affectedUserId, string perf } /// - /// Current date/time in UTC format + /// Gets the date and time in UTC when this notification was created. /// public DateTime DateTimeUtc { get; } /// - /// The source IP address of the user performing the action + /// Gets the source IP address of the user performing the action. /// public string IpAddress { get; } /// - /// The user affected by the event raised + /// Gets the ID of the user affected by this action. /// public string? AffectedUserId { get; } /// - /// If a user is performing an action on a different user, then this will be set. Otherwise it will be -1 + /// Gets the ID of the user performing this action. /// + /// + /// If a user is performing an action on a different user, this will differ from . + /// public string PerformingUserId { get; } } diff --git a/src/Umbraco.Core/Notifications/UserPasswordChangedNotification.cs b/src/Umbraco.Core/Notifications/UserPasswordChangedNotification.cs index a7cd1e51aebc..e18de6ee6df4 100644 --- a/src/Umbraco.Core/Notifications/UserPasswordChangedNotification.cs +++ b/src/Umbraco.Core/Notifications/UserPasswordChangedNotification.cs @@ -1,7 +1,22 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published after a user's password has been changed. +/// +/// +/// This notification is useful for audit logging and security monitoring purposes. +/// public class UserPasswordChangedNotification : UserNotification { + /// + /// Initializes a new instance of the class. + /// + /// The source IP address of the user changing the password. + /// The ID of the user whose password was changed. + /// The ID of the user performing the password change. public UserPasswordChangedNotification(string ipAddress, string affectedUserId, string performingUserId) : base( ipAddress, affectedUserId, performingUserId) diff --git a/src/Umbraco.Core/Notifications/UserPasswordResetNotification.cs b/src/Umbraco.Core/Notifications/UserPasswordResetNotification.cs index 8b23b5aa4f05..d9bf1cd694b4 100644 --- a/src/Umbraco.Core/Notifications/UserPasswordResetNotification.cs +++ b/src/Umbraco.Core/Notifications/UserPasswordResetNotification.cs @@ -1,7 +1,22 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published after a user's password has been reset. +/// +/// +/// This notification is useful for audit logging and security monitoring purposes. +/// public class UserPasswordResetNotification : UserNotification { + /// + /// Initializes a new instance of the class. + /// + /// The source IP address of the user resetting the password. + /// The ID of the user whose password was reset. + /// The ID of the user performing the password reset. public UserPasswordResetNotification(string ipAddress, string affectedUserId, string performingUserId) : base(ipAddress, affectedUserId, performingUserId) { diff --git a/src/Umbraco.Core/Notifications/UserPasswordResettingNotification.cs b/src/Umbraco.Core/Notifications/UserPasswordResettingNotification.cs index 9edf9ce26513..9110b1bcf837 100644 --- a/src/Umbraco.Core/Notifications/UserPasswordResettingNotification.cs +++ b/src/Umbraco.Core/Notifications/UserPasswordResettingNotification.cs @@ -1,13 +1,31 @@ -using Umbraco.Cms.Core.Events; +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models.Membership; namespace Umbraco.Cms.Core.Notifications; -public class UserPasswordResettingNotification : CancelableObjectNotification +/// +/// Notification published before a user's password is reset. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the password reset +/// by setting to true. +/// +public class UserPasswordResettingNotification : CancelableObjectNotification { + /// + /// Initializes a new instance of the class. + /// + /// The user whose password is being reset. + /// The event messages collection. public UserPasswordResettingNotification(IUser target, EventMessages messages) : base(target, messages) { } + /// + /// Gets the user whose password is being reset. + /// public IUser User => Target; } diff --git a/src/Umbraco.Core/Notifications/UserResetAccessFailedCountNotification.cs b/src/Umbraco.Core/Notifications/UserResetAccessFailedCountNotification.cs index f1cce2df63a0..710714c2686e 100644 --- a/src/Umbraco.Core/Notifications/UserResetAccessFailedCountNotification.cs +++ b/src/Umbraco.Core/Notifications/UserResetAccessFailedCountNotification.cs @@ -1,7 +1,23 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published when a user's failed access count has been reset. +/// +/// +/// This notification is published when a user's account lockout counter is reset, +/// typically after a successful login or manual administrator action. +/// public class UserResetAccessFailedCountNotification : UserNotification { + /// + /// Initializes a new instance of the class. + /// + /// The source IP address of the action. + /// The ID of the user whose failed count was reset. + /// The ID of the user performing the reset. public UserResetAccessFailedCountNotification(string ipAddress, string affectedUserId, string performingUserId) : base(ipAddress, affectedUserId, performingUserId) { diff --git a/src/Umbraco.Core/Notifications/UserSavedNotification.cs b/src/Umbraco.Core/Notifications/UserSavedNotification.cs index 8292cb9f6d19..a8f75641ef9c 100644 --- a/src/Umbraco.Core/Notifications/UserSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/UserSavedNotification.cs @@ -6,13 +6,30 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published after a user has been saved. +/// +/// +/// This notification is published by the after the user has been persisted. +/// It is not cancelable since the save operation has already completed. +/// public sealed class UserSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class with a single user. + /// + /// The user that was saved. + /// The event messages collection. public UserSavedNotification(IUser target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple users. + /// + /// The collection of users that were saved. + /// The event messages collection. public UserSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/UserSavingNotification.cs b/src/Umbraco.Core/Notifications/UserSavingNotification.cs index 3760f02881ac..f895f7d2ebe8 100644 --- a/src/Umbraco.Core/Notifications/UserSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/UserSavingNotification.cs @@ -6,13 +6,30 @@ namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published before a user is saved. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation. +/// The notification is published by the before the user is persisted. +/// public sealed class UserSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class with a single user. + /// + /// The user being saved. + /// The event messages collection. public UserSavingNotification(IUser target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class with multiple users. + /// + /// The collection of users being saved. + /// The event messages collection. public UserSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/UserTwoFactorRequestedNotification.cs b/src/Umbraco.Core/Notifications/UserTwoFactorRequestedNotification.cs index 1eb6d774d0ce..44b3ef72ff79 100644 --- a/src/Umbraco.Core/Notifications/UserTwoFactorRequestedNotification.cs +++ b/src/Umbraco.Core/Notifications/UserTwoFactorRequestedNotification.cs @@ -1,8 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published when two-factor authentication is requested for a user. +/// +/// +/// This notification can be used to implement custom two-factor authentication providers +/// or to perform additional actions when 2FA is triggered. +/// public class UserTwoFactorRequestedNotification : INotification { + /// + /// Initializes a new instance of the class. + /// + /// The unique key of the user requesting two-factor authentication. public UserTwoFactorRequestedNotification(Guid userKey) => UserKey = userKey; + /// + /// Gets the unique key of the user requesting two-factor authentication. + /// public Guid UserKey { get; } } diff --git a/src/Umbraco.Core/Notifications/UserUnlockedNotification.cs b/src/Umbraco.Core/Notifications/UserUnlockedNotification.cs index 7883595733c6..69cc6bc49ddf 100644 --- a/src/Umbraco.Core/Notifications/UserUnlockedNotification.cs +++ b/src/Umbraco.Core/Notifications/UserUnlockedNotification.cs @@ -1,7 +1,22 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification that is published after a user account has been unlocked. +/// +/// +/// This notification is useful for audit logging and security monitoring purposes. +/// public class UserUnlockedNotification : UserNotification { + /// + /// Initializes a new instance of the class. + /// + /// The source IP address associated with the unlock. + /// The ID of the user whose account was unlocked. + /// The ID of the user performing the unlock. public UserUnlockedNotification(string ipAddress, string affectedUserId, string performingUserId) : base(ipAddress, affectedUserId, performingUserId) { diff --git a/src/Umbraco.Core/Notifications/WebhookDeletedNotification.cs b/src/Umbraco.Core/Notifications/WebhookDeletedNotification.cs index eb4394e59c7e..9e7c2324e615 100644 --- a/src/Umbraco.Core/Notifications/WebhookDeletedNotification.cs +++ b/src/Umbraco.Core/Notifications/WebhookDeletedNotification.cs @@ -1,10 +1,25 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after webhooks have been deleted. +/// +/// +/// This notification is published after webhooks have been successfully deleted, +/// allowing handlers to react for auditing or cache invalidation purposes. +/// public class WebhookDeletedNotification : DeletedNotification { + /// + /// Initializes a new instance of the class. + /// + /// The webhook that was deleted. + /// The event messages collection. public WebhookDeletedNotification(IWebhook target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/WebhookDeletingNotification.cs b/src/Umbraco.Core/Notifications/WebhookDeletingNotification.cs index 7e5c8e45799c..fa0f1b104b25 100644 --- a/src/Umbraco.Core/Notifications/WebhookDeletingNotification.cs +++ b/src/Umbraco.Core/Notifications/WebhookDeletingNotification.cs @@ -1,15 +1,37 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before webhooks are deleted. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the delete operation +/// by setting to true. +/// public class WebhookDeletingNotification : DeletingNotification { + /// + /// Initializes a new instance of the class + /// with a single webhook. + /// + /// The webhook being deleted. + /// The event messages collection. public WebhookDeletingNotification(IWebhook target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple webhooks. + /// + /// The webhooks being deleted. + /// The event messages collection. public WebhookDeletingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/WebhookSavedNotification.cs b/src/Umbraco.Core/Notifications/WebhookSavedNotification.cs index d94b87873e17..bb54ff0a3f6c 100644 --- a/src/Umbraco.Core/Notifications/WebhookSavedNotification.cs +++ b/src/Umbraco.Core/Notifications/WebhookSavedNotification.cs @@ -1,15 +1,37 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published after webhooks have been saved. +/// +/// +/// This notification is published after webhooks have been successfully saved, +/// allowing handlers to react for auditing or cache invalidation purposes. +/// public class WebhookSavedNotification : SavedNotification { + /// + /// Initializes a new instance of the class + /// with a single webhook. + /// + /// The webhook that was saved. + /// The event messages collection. public WebhookSavedNotification(IWebhook target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple webhooks. + /// + /// The webhooks that were saved. + /// The event messages collection. public WebhookSavedNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Notifications/WebhookSavingNotification.cs b/src/Umbraco.Core/Notifications/WebhookSavingNotification.cs index 8d0a6ce7ffb2..2b7d779fe9dd 100644 --- a/src/Umbraco.Core/Notifications/WebhookSavingNotification.cs +++ b/src/Umbraco.Core/Notifications/WebhookSavingNotification.cs @@ -1,15 +1,37 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Notifications; +/// +/// Notification published before webhooks are saved. +/// +/// +/// This notification is cancelable, allowing handlers to prevent the save operation +/// by setting to true. +/// public class WebhookSavingNotification : SavingNotification { + /// + /// Initializes a new instance of the class + /// with a single webhook. + /// + /// The webhook being saved. + /// The event messages collection. public WebhookSavingNotification(IWebhook target, EventMessages messages) : base(target, messages) { } + /// + /// Initializes a new instance of the class + /// with multiple webhooks. + /// + /// The webhooks being saved. + /// The event messages collection. public WebhookSavingNotification(IEnumerable target, EventMessages messages) : base(target, messages) { diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index f1ff9555572d..179a3a4bd02f 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -4,15 +4,27 @@ namespace Umbraco.Cms.Core.Packaging; /// -/// Parses the xml document contained in a compiled (zip) Umbraco package +/// Parses the XML document contained in a compiled (zip) Umbraco package. /// public class CompiledPackageXmlParser { private readonly ConflictingPackageData _conflictingPackageData; + /// + /// Initializes a new instance of the class. + /// + /// The service used to detect conflicting package data. public CompiledPackageXmlParser(ConflictingPackageData conflictingPackageData) => _conflictingPackageData = conflictingPackageData; + /// + /// Converts an XML document to a model. + /// + /// The XML document representing the package. + /// A instance containing the parsed package data. + /// Thrown when is null. + /// Thrown when the XML document is invalid. + /// Thrown when the XML document format is not a valid Umbraco package. public CompiledPackage ToCompiledPackage(XDocument xml) { if (xml is null) @@ -70,6 +82,11 @@ public CompiledPackage ToCompiledPackage(XDocument xml) return def; } + /// + /// Gets the installation warnings for a compiled package by checking for conflicts. + /// + /// The compiled package to check for conflicts. + /// An instance containing any detected conflicts. private InstallWarnings GetInstallWarnings(CompiledPackage package) { var installWarnings = new InstallWarnings diff --git a/src/Umbraco.Core/Packaging/ConflictingPackageData.cs b/src/Umbraco.Core/Packaging/ConflictingPackageData.cs index c1b16d7bf320..585608d9a9c3 100644 --- a/src/Umbraco.Core/Packaging/ConflictingPackageData.cs +++ b/src/Umbraco.Core/Packaging/ConflictingPackageData.cs @@ -5,13 +5,27 @@ namespace Umbraco.Cms.Core.Packaging; +/// +/// Provides methods to detect conflicting package data during package installation. +/// public class ConflictingPackageData { private readonly IFileService _fileService; + /// + /// Initializes a new instance of the class. + /// + /// The file service used to check for existing files. + /// Thrown when is null. public ConflictingPackageData(IFileService fileService) => _fileService = fileService ?? throw new ArgumentNullException(nameof(fileService)); + /// + /// Finds stylesheets in the package that already exist in the system. + /// + /// The XML elements representing stylesheets from the package. + /// A collection of existing stylesheets that conflict with the package, or null if no nodes provided. + /// Thrown when a stylesheet node is missing the required "Name" element. public IEnumerable? FindConflictingStylesheets(IEnumerable? stylesheetNodes) => stylesheetNodes? .Select(n => @@ -26,6 +40,12 @@ public ConflictingPackageData(IFileService fileService) }) .Where(v => v != null); + /// + /// Finds templates in the package that already exist in the system. + /// + /// The XML elements representing templates from the package. + /// A collection of existing templates that conflict with the package, or null if no nodes provided. + /// Thrown when a template node is missing the required "Alias" element. public IEnumerable? FindConflictingTemplates(IEnumerable? templateNodes) => templateNodes? .Select(n => diff --git a/src/Umbraco.Core/Packaging/IPackageDefinitionRepository.cs b/src/Umbraco.Core/Packaging/IPackageDefinitionRepository.cs index 07641525151e..1af3287f2c08 100644 --- a/src/Umbraco.Core/Packaging/IPackageDefinitionRepository.cs +++ b/src/Umbraco.Core/Packaging/IPackageDefinitionRepository.cs @@ -1,23 +1,40 @@ namespace Umbraco.Cms.Core.Packaging; /// -/// Defines methods for persisting package definitions to storage +/// Defines methods for persisting package definitions to storage. /// public interface IPackageDefinitionRepository { + /// + /// Gets all package definitions from storage. + /// + /// An enumerable collection of all instances. IEnumerable GetAll(); + /// + /// Gets a package definition by its integer identifier. + /// + /// The identifier of the package definition. + /// The if found; otherwise, null. PackageDefinition? GetById(int id); + /// + /// Gets a package definition by its unique key. + /// + /// The unique key of the package definition. + /// The if found; otherwise, null. PackageDefinition? GetByKey(Guid key); + /// + /// Deletes a package definition from storage. + /// + /// The identifier of the package definition to delete. void Delete(int id); /// - /// Persists a package definition to storage + /// Persists a package definition to storage. /// - /// - /// true if creating/updating the package was successful, otherwise false - /// + /// The package definition to save. + /// true if creating/updating the package was successful; otherwise, false. bool SavePackage(PackageDefinition definition); } diff --git a/src/Umbraco.Core/Packaging/IPackageInstallation.cs b/src/Umbraco.Core/Packaging/IPackageInstallation.cs index a6de8434028c..b8f0e1b2d4a9 100644 --- a/src/Umbraco.Core/Packaging/IPackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/IPackageInstallation.cs @@ -3,26 +3,31 @@ namespace Umbraco.Cms.Core.Packaging; +/// +/// Defines methods for installing Umbraco packages. +/// public interface IPackageInstallation { /// - /// Installs a packages data and entities + /// Installs a package's data and entities. /// - /// - /// - /// - /// - // TODO: The resulting PackageDefinition is only if we wanted to persist what was saved during package data installation. - // This used to be for the installedPackages.config but we don't have that anymore and don't really want it if we can help it. - // Possibly, we could continue to persist that file so that you could uninstall package data for an installed package in the - // back office (but it won't actually uninstall the package until you do that via nuget). If we want that functionality we'll have - // to restore a bunch of deleted code. + /// The compiled package containing the data to install. + /// The identifier of the user performing the installation. + /// When this method returns, contains the package definition created during installation. + /// An containing details about what was installed. + /// + /// The resulting is only if we wanted to persist what was saved during package data installation. + /// This used to be for the installedPackages.config but we don't have that anymore and don't really want it if we can help it. + /// Possibly, we could continue to persist that file so that you could uninstall package data for an installed package in the + /// back office (but it won't actually uninstall the package until you do that via NuGet). If we want that functionality we'll have + /// to restore a bunch of deleted code. + /// InstallationSummary InstallPackageData(CompiledPackage compiledPackage, int userId, out PackageDefinition packageDefinition); /// - /// Reads the package xml and returns the model + /// Reads the package XML and returns the model. /// - /// - /// + /// The XML document containing the package definition. + /// A model representing the package. CompiledPackage ReadPackage(XDocument? packageXmlFile); } diff --git a/src/Umbraco.Core/Packaging/InstallationSummary.cs b/src/Umbraco.Core/Packaging/InstallationSummary.cs index 6625057bb858..f22a0fe4a148 100644 --- a/src/Umbraco.Core/Packaging/InstallationSummary.cs +++ b/src/Umbraco.Core/Packaging/InstallationSummary.cs @@ -5,41 +5,91 @@ namespace Umbraco.Cms.Core.Packaging; +/// +/// Represents a summary of items installed during a package installation. +/// [Serializable] [DataContract(IsReference = true)] public class InstallationSummary { + /// + /// Initializes a new instance of the class. + /// + /// The name of the package being installed. public InstallationSummary(string packageName) => PackageName = packageName; + /// + /// Gets the name of the package that was installed. + /// public string PackageName { get; } + /// + /// Gets or sets the warnings generated during installation. + /// public InstallWarnings Warnings { get; set; } = new(); + /// + /// Gets or sets the collection of data types that were installed. + /// public IEnumerable DataTypesInstalled { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of languages that were installed. + /// public IEnumerable LanguagesInstalled { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of dictionary items that were installed. + /// public IEnumerable DictionaryItemsInstalled { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of templates that were installed. + /// public IEnumerable TemplatesInstalled { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of document types that were installed. + /// public IEnumerable DocumentTypesInstalled { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of media types that were installed. + /// public IEnumerable MediaTypesInstalled { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of stylesheets that were installed. + /// public IEnumerable StylesheetsInstalled { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of scripts that were installed. + /// public IEnumerable ScriptsInstalled { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of partial views that were installed. + /// public IEnumerable PartialViewsInstalled { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of content items that were installed. + /// public IEnumerable ContentInstalled { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of media items that were installed. + /// public IEnumerable MediaInstalled { get; set; } = Enumerable.Empty(); + /// + /// Gets or sets the collection of entity containers that were installed. + /// public IEnumerable EntityContainersInstalled { get; set; } = Enumerable.Empty(); + /// public override string ToString() { var sb = new StringBuilder(); diff --git a/src/Umbraco.Core/Packaging/InstalledPackage.cs b/src/Umbraco.Core/Packaging/InstalledPackage.cs index 42d62317c59e..c25c63f7e026 100644 --- a/src/Umbraco.Core/Packaging/InstalledPackage.cs +++ b/src/Umbraco.Core/Packaging/InstalledPackage.cs @@ -3,25 +3,46 @@ namespace Umbraco.Cms.Core.Packaging; +/// +/// Represents an installed Umbraco package with its metadata and migration status. +/// [DataContract(Name = "installedPackage")] public class InstalledPackage { + /// + /// Gets or sets the unique identifier of the package. + /// [DataMember(Name = "id")] public string? PackageId { get; set; } + /// + /// Gets or sets the name of the package. + /// [DataMember(Name = "name", IsRequired = true)] [Required] public string? PackageName { get; set; } + /// + /// Gets or sets the custom view path for the package in the back office. + /// [DataMember(Name = "packageView")] public string? PackageView { get; set; } + /// + /// Gets or sets the version of the installed package. + /// [DataMember(Name = "version")] public string? Version { get; set; } + /// + /// Gets or sets a value indicating whether the package allows telemetry data collection. + /// [DataMember(Name = "allowPackageTelemetry")] public bool AllowPackageTelemetry { get; set; } = true; + /// + /// Gets or sets the collection of migration plans associated with this package. + /// [DataMember(Name = "plans")] public IEnumerable PackageMigrationPlans { get; set; } = Enumerable.Empty(); diff --git a/src/Umbraco.Core/Packaging/InstalledPackageMigrationPlans.cs b/src/Umbraco.Core/Packaging/InstalledPackageMigrationPlans.cs index 50cafd1d208f..06edbf136e76 100644 --- a/src/Umbraco.Core/Packaging/InstalledPackageMigrationPlans.cs +++ b/src/Umbraco.Core/Packaging/InstalledPackageMigrationPlans.cs @@ -2,9 +2,16 @@ namespace Umbraco.Cms.Core.Packaging; +/// +/// Represents the migration plan status for an installed package. +/// [DataContract(Name = "installedPackageMigrations")] public class InstalledPackageMigrationPlans { + /// + /// Gets a value indicating whether the package has pending migrations. + /// + /// true if the final migration ID differs from the current migration ID; otherwise, false. [DataMember(Name = "hasPendingMigrations")] public bool HasPendingMigrations => FinalMigrationId != CurrentMigrationId; diff --git a/src/Umbraco.Core/Packaging/PackageDefinition.cs b/src/Umbraco.Core/Packaging/PackageDefinition.cs index 23f85619cce5..5a7768bd43e3 100644 --- a/src/Umbraco.Core/Packaging/PackageDefinition.cs +++ b/src/Umbraco.Core/Packaging/PackageDefinition.cs @@ -13,12 +13,21 @@ namespace Umbraco.Cms.Core.Packaging; [DataContract(Name = "packageInstance")] public class PackageDefinition { + /// + /// Gets or sets the unique identifier for this package definition. + /// [DataMember(Name = "id")] public int Id { get; set; } + /// + /// Gets or sets the globally unique identifier for this package. + /// [DataMember(Name = "packageGuid")] public Guid PackageId { get; set; } + /// + /// Gets or sets the name of the package. + /// [DataMember(Name = "name")] [Required] public string Name { get; set; } = string.Empty; @@ -30,42 +39,81 @@ public class PackageDefinition [DataMember(Name = "packagePath")] public string PackagePath { get; set; } = string.Empty; + /// + /// Gets or sets a value indicating whether child content nodes should be loaded. + /// [DataMember(Name = "contentLoadChildNodes")] public bool ContentLoadChildNodes { get; set; } + /// + /// Gets or sets the content node identifier to include in the package. + /// [DataMember(Name = "contentNodeId")] public string? ContentNodeId { get; set; } + /// + /// Gets or sets the collection of language identifiers included in this package. + /// [DataMember(Name = "languages")] public IList Languages { get; set; } = new List(); + /// + /// Gets or sets the collection of dictionary item identifiers included in this package. + /// [DataMember(Name = "dictionaryItems")] public IList DictionaryItems { get; set; } = new List(); + /// + /// Gets or sets the collection of template identifiers included in this package. + /// [DataMember(Name = "templates")] public IList Templates { get; set; } = new List(); + /// + /// Gets or sets the collection of partial view paths included in this package. + /// [DataMember(Name = "partialViews")] public IList PartialViews { get; set; } = new List(); + /// + /// Gets or sets the collection of document type identifiers included in this package. + /// [DataMember(Name = "documentTypes")] public IList DocumentTypes { get; set; } = new List(); + /// + /// Gets or sets the collection of media type identifiers included in this package. + /// [DataMember(Name = "mediaTypes")] public IList MediaTypes { get; set; } = new List(); + /// + /// Gets or sets the collection of stylesheet paths included in this package. + /// [DataMember(Name = "stylesheets")] public IList Stylesheets { get; set; } = new List(); + /// + /// Gets or sets the collection of script paths included in this package. + /// [DataMember(Name = "scripts")] public IList Scripts { get; set; } = new List(); + /// + /// Gets or sets the collection of data type identifiers included in this package. + /// [DataMember(Name = "dataTypes")] public IList DataTypes { get; set; } = new List(); + /// + /// Gets or sets the collection of media UDIs included in this package. + /// [DataMember(Name = "mediaUdis")] public IList MediaUdis { get; set; } = new List(); + /// + /// Gets or sets a value indicating whether child media nodes should be loaded. + /// [DataMember(Name = "mediaLoadChildNodes")] public bool MediaLoadChildNodes { get; set; } } diff --git a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs index 8a60ae84279e..c9efd723da22 100644 --- a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs +++ b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs @@ -4,13 +4,25 @@ namespace Umbraco.Cms.Core.Packaging; /// -/// Converts a to and from XML +/// Converts a to and from XML. /// public class PackageDefinitionXmlParser { + /// + /// An empty string list used as a default value for package definition collections. + /// private static readonly IList EmptyStringList = new List(); + + /// + /// An empty GuidUdi list used as a default value for package definition media collections. + /// private static readonly IList EmptyGuidUdiList = new List(); + /// + /// Converts an XML element to a . + /// + /// The XML element containing the package definition. + /// The parsed , or null if the XML is null. public PackageDefinition? ToPackageDefinition(XElement xml) { if (xml == null) @@ -69,6 +81,11 @@ public class PackageDefinitionXmlParser return retVal; } + /// + /// Converts a to its XML representation. + /// + /// The package definition to convert. + /// An representing the package definition. public XElement ToXml(PackageDefinition def) { var packageXml = new XElement( diff --git a/src/Umbraco.Core/Packaging/PackageMigrationResource.cs b/src/Umbraco.Core/Packaging/PackageMigrationResource.cs index 0d72cad38ac8..a8115586bf13 100644 --- a/src/Umbraco.Core/Packaging/PackageMigrationResource.cs +++ b/src/Umbraco.Core/Packaging/PackageMigrationResource.cs @@ -6,8 +6,17 @@ namespace Umbraco.Cms.Core.Packaging; +/// +/// Provides utility methods for accessing embedded package migration resources. +/// public static class PackageMigrationResource { + /// + /// Gets the embedded package data manifest from the specified plan type. + /// + /// The type of the migration plan to get the embedded package from. + /// When this method returns, contains the zip archive if the package is a zip file; otherwise, null. + /// The package XML document, or null if no embedded package was found. public static XDocument? GetEmbeddedPackageDataManifest(Type planType, out ZipArchive? zipArchive) { XDocument? packageXml; @@ -23,6 +32,11 @@ public static class PackageMigrationResource return packageXml; } + /// + /// Gets the embedded package zip stream from the specified plan type. + /// + /// The type of the migration plan. + /// The stream for the embedded zip file, or null if not found. private static Stream? GetEmbeddedPackageZipStream(Type planType) { // lookup the embedded resource by convention @@ -33,9 +47,20 @@ public static class PackageMigrationResource return stream; } + /// + /// Gets the embedded package data manifest from the specified plan type. + /// + /// The type of the migration plan to get the embedded package from. + /// The package XML document, or null if no embedded package was found. public static XDocument? GetEmbeddedPackageDataManifest(Type planType) => GetEmbeddedPackageDataManifest(planType, out _); + /// + /// Gets a hash of the embedded package data manifest for the specified plan type. + /// + /// The type of the migration plan. + /// A hash string representing the package contents. + /// Thrown when no embedded package files are found for the plan type. public static string GetEmbeddedPackageDataManifestHash(Type planType) { // SEE: HashFromStreams in the benchmarks project for how fast this is. It will run @@ -59,6 +84,11 @@ public static string GetEmbeddedPackageDataManifestHash(Type planType) throw new IOException("Missing embedded files for planType: " + planType); } + /// + /// Gets the embedded package XML document from the specified plan type. + /// + /// The type of the migration plan. + /// The package XML document, or null if not found. private static XDocument? GetEmbeddedPackageXmlDoc(Type planType) { // lookup the embedded resource by convention @@ -79,6 +109,13 @@ public static string GetEmbeddedPackageDataManifestHash(Type planType) return xml; } + /// + /// Attempts to get the embedded package data manifest from the specified plan type. + /// + /// The type of the migration plan. + /// When this method returns, contains the package XML document if found; otherwise, null. + /// When this method returns, contains the zip archive if the package is a zip file; otherwise, null. + /// true if an embedded package was found; otherwise, false. public static bool TryGetEmbeddedPackageDataManifest(Type planType, out XDocument? packageXml, out ZipArchive? zipArchive) { Stream? zipStream = GetEmbeddedPackageZipStream(planType); @@ -93,6 +130,14 @@ public static bool TryGetEmbeddedPackageDataManifest(Type planType, out XDocumen return packageXml is not null; } + /// + /// Gets the package data manifest from a zip stream. + /// + /// The zip stream containing the package. + /// When this method returns, contains the package XML document. + /// The opened for the package. + /// Thrown when is null. + /// Thrown when the zip package does not contain the required package.xml file. public static ZipArchive GetPackageDataManifest(Stream packageZipStream, out XDocument packageXml) { if (packageZipStream == null) diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs index 7e63d6a0fe95..fe01af794ba5 100644 --- a/src/Umbraco.Core/Packaging/PackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -101,8 +101,12 @@ public PackagesRepository( _fileSystems = fileSystems; } + /// + /// Gets the full path to the created packages file. + /// private string CreatedPackagesFile => _packagesFolderPath.EnsureEndsWith('/') + _packageRepositoryFileName; + /// public IEnumerable GetAll() { XDocument packagesXml = EnsureStorage(out _); @@ -117,6 +121,7 @@ public PackagesRepository( } } + /// public PackageDefinition? GetById(int id) { XDocument packagesXml = EnsureStorage(out var packageFile); @@ -125,9 +130,11 @@ public PackagesRepository( return packageXml == null ? null : _parser.ToPackageDefinition(packageXml); } - // Default implementation as the class is obsolete + /// + /// Default implementation returns null as the class is obsolete. public PackageDefinition? GetByKey(Guid key) => null; + /// public void Delete(int id) { XDocument packagesXml = EnsureStorage(out var packagesFile); @@ -143,6 +150,7 @@ public void Delete(int id) packagesXml?.Save(packagesFile); } + /// public bool SavePackage(PackageDefinition definition) { if (definition == null) @@ -190,6 +198,7 @@ public bool SavePackage(PackageDefinition definition) return true; } + /// public string ExportPackage(PackageDefinition definition) { if (definition.Id == default) @@ -301,6 +310,9 @@ public string ExportPackage(PackageDefinition definition) } } + /// + /// Deletes the local repository files including the packages configuration file and folder. + /// public void DeleteLocalRepositoryFiles() { var packagesFile = _hostingEnvironment.MapPathContentRoot(CreatedPackagesFile); @@ -327,6 +339,11 @@ private static XElement GetPackageInfoXml(PackageDefinition definition) return info; } + /// + /// Validates the package definition using data annotations. + /// + /// The package definition to validate. + /// Thrown when validation fails. private void ValidatePackage(PackageDefinition definition) { // ensure it's valid @@ -340,6 +357,11 @@ private void ValidatePackage(PackageDefinition definition) } } + /// + /// Packages data types into the XML container. + /// + /// The package definition containing data type identifiers. + /// The XML container to add data types to. private void PackageDataTypes(PackageDefinition definition, XContainer root) { var dataTypes = new XElement("DataTypes"); @@ -362,6 +384,11 @@ private void PackageDataTypes(PackageDefinition definition, XContainer root) root.Add(dataTypes); } + /// + /// Packages languages into the XML container. + /// + /// The package definition containing language identifiers. + /// The XML container to add languages to. private void PackageLanguages(PackageDefinition definition, XContainer root) { var languages = new XElement("Languages"); @@ -384,6 +411,11 @@ private void PackageLanguages(PackageDefinition definition, XContainer root) root.Add(languages); } + /// + /// Packages dictionary items into the XML container, preserving hierarchy. + /// + /// The package definition containing dictionary item identifiers. + /// The XML container to add dictionary items to. private void PackageDictionaryItems(PackageDefinition definition, XContainer root) { var rootDictionaryItems = new XElement("DictionaryItems"); @@ -444,6 +476,9 @@ private void PackageDictionaryItems(PackageDefinition definition, XContainer roo root.Add(rootDictionaryItems); + /// + /// Appends a dictionary element to the root and tracks it as processed. + /// static void AppendDictionaryElement( XElement rootDictionaryItems, Dictionary items, @@ -462,6 +497,11 @@ static void AppendDictionaryElement( } } + /// + /// Packages stylesheets into the XML container. + /// + /// The package definition containing stylesheet paths. + /// The XML container to add stylesheets to. private void PackageStylesheets(PackageDefinition definition, XContainer root) { var stylesheetsXml = new XElement("Stylesheets"); @@ -482,6 +522,15 @@ private void PackageStylesheets(PackageDefinition definition, XContainer root) root.Add(stylesheetsXml); } + /// + /// Packages static files from a file system into the XML container. + /// + /// The collection of file paths to package. + /// The XML container to add files to. + /// The name of the XML container element. + /// The name of each file element. + /// The file system to read files from. + /// Thrown when a file is not found. private void PackageStaticFiles( IEnumerable filePaths, XContainer root, @@ -519,6 +568,11 @@ private void PackageStaticFiles( root.Add(scriptsXml); } + /// + /// Packages templates into the XML container. + /// + /// The package definition containing template identifiers. + /// The XML container to add templates to. private void PackageTemplates(PackageDefinition definition, XContainer root) { var templatesXml = new XElement("Templates"); @@ -541,6 +595,11 @@ private void PackageTemplates(PackageDefinition definition, XContainer root) root.Add(templatesXml); } + /// + /// Packages document types into the XML container, including parent types. + /// + /// The package definition containing document type identifiers. + /// The XML container to add document types to. private void PackageDocumentTypes(PackageDefinition definition, XContainer root) { var contentTypes = new HashSet(); @@ -569,6 +628,11 @@ private void PackageDocumentTypes(PackageDefinition definition, XContainer root) root.Add(docTypesXml); } + /// + /// Packages media types into the XML container, including parent types. + /// + /// The package definition containing media type identifiers. + /// The XML container to add media types to. private void PackageMediaTypes(PackageDefinition definition, XContainer root) { var mediaTypes = new HashSet(); @@ -597,6 +661,11 @@ private void PackageMediaTypes(PackageDefinition definition, XContainer root) root.Add(mediaTypesXml); } + /// + /// Packages documents and tags into the XML container. + /// + /// The package definition containing content node information. + /// The XML container to add documents to. private void PackageDocumentsAndTags(PackageDefinition definition, XContainer root) { // Documents and tags @@ -684,6 +753,12 @@ private void PackageDocumentsAndTags(PackageDefinition definition, XContainer ro } } + /// + /// Packages media items into the XML container and collects their file streams. + /// + /// The package definition containing media UDIs. + /// The XML element to add media items to. + /// A dictionary of media file paths and their corresponding streams. private Dictionary PackageMedia(PackageDefinition definition, XElement root) { var mediaStreams = new Dictionary(); @@ -745,6 +820,11 @@ void OnSerializedMedia(IMedia media, XElement xmlMedia) return _serializer.Serialize(stylesheet, includeProperties); } + /// + /// Recursively adds a document type and its parent types to the collection. + /// + /// The document type to add. + /// The collection to add document types to. private void AddDocumentType(IContentType dt, HashSet dtl) { if (dt.ParentId > 0) @@ -764,6 +844,11 @@ private void AddDocumentType(IContentType dt, HashSet dtl) } } + /// + /// Recursively adds a media type and its parent types to the collection. + /// + /// The media type to add. + /// The collection to add media types to. private void AddMediaType(IMediaType mediaType, HashSet mediaTypes) { if (mediaType.ParentId > 0) @@ -783,6 +868,11 @@ private void AddMediaType(IMediaType mediaType, HashSet mediaTypes) } } + /// + /// Creates a new compiled package XML document. + /// + /// When this method returns, contains the root element of the document. + /// A new for the compiled package. private static XDocument CreateCompiledPackageXml(out XElement root) { root = new XElement("umbPackage"); @@ -790,6 +880,11 @@ private static XDocument CreateCompiledPackageXml(out XElement root) return compiledPackageXml; } + /// + /// Ensures the package storage exists and returns the packages XML document. + /// + /// When this method returns, contains the path to the packages file. + /// The packages XML document. private XDocument EnsureStorage(out string packagesFile) { var packagesFolder = _hostingEnvironment.MapPathContentRoot(_packagesFolderPath); diff --git a/src/Umbraco.Core/PaginationHelper.cs b/src/Umbraco.Core/PaginationHelper.cs index eb9049c1da98..66236e590d36 100644 --- a/src/Umbraco.Core/PaginationHelper.cs +++ b/src/Umbraco.Core/PaginationHelper.cs @@ -1,7 +1,18 @@ -namespace Umbraco.Cms.Core; +namespace Umbraco.Cms.Core; +/// +/// Provides helper methods for pagination operations. +/// public static class PaginationHelper { + /// + /// Converts skip/take values to page number and page size. + /// + /// The number of items to skip. + /// The number of items to take (page size). + /// When this method returns, contains the calculated page number (zero-based). + /// When this method returns, contains the page size. + /// Skip is not a multiple of take. public static void ConvertSkipTakeToPaging(int skip, int take, out long pageNumber, out int pageSize) { if (skip % take != 0) diff --git a/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs b/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs index 9ac02f409c2e..074f4f118b2b 100644 --- a/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs +++ b/src/Umbraco.Core/Persistence/Constants-DatabaseSchema.cs @@ -2,125 +2,425 @@ namespace Umbraco.Cms.Core; +/// +/// Provides partial constants for the Umbraco application. +/// public static partial class Constants { + /// + /// Provides constants related to the Umbraco database schema. + /// public static class DatabaseSchema { // TODO: Why aren't all table names with the same prefix? + /// + /// The prefix used for Umbraco database table names. + /// public const string TableNamePrefix = "umbraco"; + /// + /// Provides constants for common database column names. + /// public static class Columns { // Defines constants for common field names used throughout the database, to ensure // casing is aligned wherever used. + + /// + /// The primary key column name "id". + /// public const string PrimaryKeyNameId = "id"; + + /// + /// The primary key column name "pk". + /// public const string PrimaryKeyNamePk = "pk"; + + /// + /// The primary key column name "key". + /// public const string PrimaryKeyNameKey = "key"; + + /// + /// The node identifier column name. + /// public const string NodeIdName = "nodeId"; + + /// + /// The unique identifier column name. + /// public const string UniqueIdName = "uniqueId"; } + /// + /// Provides constants for Umbraco database table names. + /// + /// + /// Provides constants for Umbraco database table names. + /// public static class Tables { - + /// + /// The lock table name. + /// public const string Lock = TableNamePrefix + "Lock"; + + /// + /// The log table name. + /// public const string Log = TableNamePrefix + "Log"; + /// + /// The node table name. + /// public const string Node = TableNamePrefix + "Node"; + + /// + /// The node data table name. + /// public const string NodeData = /*TableNamePrefix*/ "cms" + "ContentNu"; + /// + /// The content type table name. + /// public const string ContentType = /*TableNamePrefix*/ "cms" + "ContentType"; + + /// + /// The content child type (allowed content types) table name. + /// public const string ContentChildType = /*TableNamePrefix*/ "cms" + "ContentTypeAllowedContentType"; + + /// + /// The document type table name. + /// public const string DocumentType = /*TableNamePrefix*/ "cms" + "DocumentType"; + /// + /// The element type tree table name. + /// [Obsolete("Please use ContentTypeTree instead. Scheduled for removal in Umbraco 18.")] public const string ElementTypeTree = /*TableNamePrefix*/ "cms" + "ContentType2ContentType"; + /// + /// The content type tree (composition) table name. + /// public const string ContentTypeTree = /*TableNamePrefix*/ "cms" + "ContentType2ContentType"; + /// + /// The data type table name. + /// public const string DataType = TableNamePrefix + "DataType"; + + /// + /// The template table name. + /// public const string Template = /*TableNamePrefix*/ "cms" + "Template"; + /// + /// The content table name. + /// public const string Content = TableNamePrefix + "Content"; + + /// + /// The content version table name. + /// public const string ContentVersion = TableNamePrefix + "ContentVersion"; + + /// + /// The content version culture variation table name. + /// public const string ContentVersionCultureVariation = TableNamePrefix + "ContentVersionCultureVariation"; + + /// + /// The content version cleanup policy table name. + /// public const string ContentVersionCleanupPolicy = TableNamePrefix + "ContentVersionCleanupPolicy"; + /// + /// The document table name. + /// public const string Document = TableNamePrefix + "Document"; + + /// + /// The document culture variation table name. + /// public const string DocumentCultureVariation = TableNamePrefix + "DocumentCultureVariation"; + + /// + /// The document version table name. + /// public const string DocumentVersion = TableNamePrefix + "DocumentVersion"; + + /// + /// The document URL table name. + /// public const string DocumentUrl = TableNamePrefix + "DocumentUrl"; + + /// + /// The media version table name. + /// public const string MediaVersion = TableNamePrefix + "MediaVersion"; + + /// + /// The content schedule table name. + /// public const string ContentSchedule = TableNamePrefix + "ContentSchedule"; + /// + /// The property type table name. + /// public const string PropertyType = /*TableNamePrefix*/ "cms" + "PropertyType"; + + /// + /// The property type group table name. + /// public const string PropertyTypeGroup = /*TableNamePrefix*/ "cms" + "PropertyTypeGroup"; + + /// + /// The property data table name. + /// public const string PropertyData = TableNamePrefix + "PropertyData"; + /// + /// The relation type table name. + /// public const string RelationType = TableNamePrefix + "RelationType"; + + /// + /// The relation table name. + /// public const string Relation = TableNamePrefix + "Relation"; + /// + /// The domain table name. + /// public const string Domain = TableNamePrefix + "Domain"; + + /// + /// The language table name. + /// public const string Language = TableNamePrefix + "Language"; + + /// + /// The dictionary entry table name. + /// public const string DictionaryEntry = /*TableNamePrefix*/ "cms" + "Dictionary"; + + /// + /// The dictionary value (language text) table name. + /// public const string DictionaryValue = /*TableNamePrefix*/ "cms" + "LanguageText"; + /// + /// The user table name. + /// public const string User = TableNamePrefix + "User"; + + /// + /// The user group table name. + /// public const string UserGroup = TableNamePrefix + "UserGroup"; + + /// + /// The user start node table name. + /// public const string UserStartNode = TableNamePrefix + "UserStartNode"; + + /// + /// The user to user group mapping table name. + /// public const string User2UserGroup = TableNamePrefix + "User2UserGroup"; + + /// + /// The user to node notification table name. + /// public const string User2NodeNotify = TableNamePrefix + "User2NodeNotify"; + + /// + /// The user to client ID mapping table name. + /// public const string User2ClientId = TableNamePrefix + "User2ClientId"; + + /// + /// The user group to application mapping table name. + /// public const string UserGroup2App = TableNamePrefix + "UserGroup2App"; + + /// + /// The user data table name. + /// public const string UserData = TableNamePrefix + "UserData"; + /// + /// The user group to node mapping table name. + /// [Obsolete("Will be removed in Umbraco 18 as this table haven't existed since Umbraco 14.")] public const string UserGroup2Node = TableNamePrefix + "UserGroup2Node"; + + /// + /// The user group to node permission mapping table name. + /// [Obsolete("Will be removed in Umbraco 18 as this table haven't existed since Umbraco 14.")] public const string UserGroup2NodePermission = TableNamePrefix + "UserGroup2NodePermission"; + /// + /// The user group to permission mapping table name. + /// public const string UserGroup2Permission = TableNamePrefix + "UserGroup2Permission"; + + /// + /// The user group to granular permission mapping table name. + /// public const string UserGroup2GranularPermission = TableNamePrefix + "UserGroup2GranularPermission"; + + /// + /// The user group to language mapping table name. + /// public const string UserGroup2Language = TableNamePrefix + "UserGroup2Language"; + + /// + /// The external login table name. + /// public const string ExternalLogin = TableNamePrefix + "ExternalLogin"; + + /// + /// The two-factor login table name. + /// public const string TwoFactorLogin = TableNamePrefix + "TwoFactorLogin"; + + /// + /// The external login token table name. + /// public const string ExternalLoginToken = TableNamePrefix + "ExternalLoginToken"; + /// + /// The member table name. + /// public const string Member = /*TableNamePrefix*/ "cms" + "Member"; + + /// + /// The member property type table name. + /// public const string MemberPropertyType = /*TableNamePrefix*/ "cms" + "MemberType"; + + /// + /// The member to member group mapping table name. + /// public const string Member2MemberGroup = /*TableNamePrefix*/ "cms" + "Member2MemberGroup"; + /// + /// The public access table name. + /// public const string Access = TableNamePrefix + "Access"; + + /// + /// The access rule table name. + /// public const string AccessRule = TableNamePrefix + "AccessRule"; + + /// + /// The redirect URL table name. + /// public const string RedirectUrl = TableNamePrefix + "RedirectUrl"; + /// + /// The cache instruction table name. + /// public const string CacheInstruction = TableNamePrefix + "CacheInstruction"; + + /// + /// The server registration table name. + /// public const string Server = TableNamePrefix + "Server"; + /// + /// The tag table name. + /// public const string Tag = /*TableNamePrefix*/ "cms" + "Tags"; + + /// + /// The tag relationship table name. + /// public const string TagRelationship = /*TableNamePrefix*/ "cms" + "TagRelationship"; + /// + /// The key-value table name. + /// public const string KeyValue = TableNamePrefix + "KeyValue"; + /// + /// The audit entry table name. + /// public const string AuditEntry = TableNamePrefix + "Audit"; + + /// + /// The consent table name. + /// public const string Consent = TableNamePrefix + "Consent"; + + /// + /// The user login table name. + /// public const string UserLogin = TableNamePrefix + "UserLogin"; + /// + /// The log viewer query table name. + /// public const string LogViewerQuery = TableNamePrefix + "LogViewerQuery"; + /// + /// The created package schema table name. + /// public const string CreatedPackageSchema = TableNamePrefix + "CreatedPackageSchema"; + + /// + /// The webhook table name. + /// public const string Webhook = TableNamePrefix + "Webhook"; + + /// + /// The webhook to content type keys mapping table name. + /// public const string Webhook2ContentTypeKeys = Webhook + "2ContentTypeKeys"; + + /// + /// The webhook to events mapping table name. + /// public const string Webhook2Events = Webhook + "2Events"; + + /// + /// The webhook to headers mapping table name. + /// public const string Webhook2Headers = Webhook + "2Headers"; + + /// + /// The webhook log table name. + /// public const string WebhookLog = Webhook + "Log"; - public const string WebhookRequest = Webhook + "Request"; + /// + /// The webhook request table name. + /// + public const string WebhookRequest = Webhook + "Request"; + /// + /// The repository cache version table name. + /// public const string RepositoryCacheVersion = TableNamePrefix + "RepositoryCacheVersion"; + + /// + /// The long-running operation table name. + /// public const string LongRunningOperation = TableNamePrefix + "LongRunningOperation"; + /// + /// The last synced table name. + /// public const string LastSynced = TableNamePrefix + "LastSynced"; + + /// + /// The distributed job table name. + /// public const string DistributedJob = TableNamePrefix + "DistributedJob"; } } diff --git a/src/Umbraco.Core/Persistence/Querying/IUserDataFilter.cs b/src/Umbraco.Core/Persistence/Querying/IUserDataFilter.cs index fbcd7aa5d5ae..22573fb1838f 100644 --- a/src/Umbraco.Core/Persistence/Querying/IUserDataFilter.cs +++ b/src/Umbraco.Core/Persistence/Querying/IUserDataFilter.cs @@ -1,10 +1,22 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Querying; +/// +/// Represents a filter for querying user data. +/// public interface IUserDataFilter { + /// + /// Gets or sets the collection of user keys to filter by. + /// public ICollection? UserKeys { get; set; } + /// + /// Gets or sets the collection of group names to filter by. + /// public ICollection? Groups { get; set; } + /// + /// Gets or sets the collection of identifiers to filter by. + /// public ICollection? Identifiers { get; set; } } diff --git a/src/Umbraco.Core/Persistence/Querying/StringPropertyMatchType.cs b/src/Umbraco.Core/Persistence/Querying/StringPropertyMatchType.cs index fa8e674b971b..5ce93750a804 100644 --- a/src/Umbraco.Core/Persistence/Querying/StringPropertyMatchType.cs +++ b/src/Umbraco.Core/Persistence/Querying/StringPropertyMatchType.cs @@ -1,15 +1,32 @@ namespace Umbraco.Cms.Core.Persistence.Querying; /// -/// Determines how to match a string property value +/// Determines how to match a string property value. /// public enum StringPropertyMatchType { + /// + /// Matches the exact value. + /// Exact, + + /// + /// Matches if the property contains the value. + /// Contains, + + /// + /// Matches if the property starts with the value. + /// StartsWith, + + /// + /// Matches if the property ends with the value. + /// EndsWith, - // Deals with % as wildcard chars in a string + /// + /// Matches using wildcard pattern, where % represents any sequence of characters. + /// Wildcard, } diff --git a/src/Umbraco.Core/Persistence/Querying/ValuePropertyMatchType.cs b/src/Umbraco.Core/Persistence/Querying/ValuePropertyMatchType.cs index ab6fd4f938e5..e19020035f17 100644 --- a/src/Umbraco.Core/Persistence/Querying/ValuePropertyMatchType.cs +++ b/src/Umbraco.Core/Persistence/Querying/ValuePropertyMatchType.cs @@ -1,13 +1,32 @@ namespace Umbraco.Cms.Core.Persistence.Querying; /// -/// Determine how to match a number or data value +/// Determines how to match a number or date value. /// public enum ValuePropertyMatchType { + /// + /// Matches the exact value. + /// Exact, + + /// + /// Matches values greater than the specified value. + /// GreaterThan, + + /// + /// Matches values less than the specified value. + /// LessThan, + + /// + /// Matches values greater than or equal to the specified value. + /// GreaterThanOrEqualTo, + + /// + /// Matches values less than or equal to the specified value. + /// LessThanOrEqualTo, } diff --git a/src/Umbraco.Core/Persistence/Repositories/IAuditRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IAuditRepository.cs index acceefef5db6..cd395b188b25 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IAuditRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IAuditRepository.cs @@ -3,9 +3,16 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IAuditRepository : IReadRepository, IWriteRepository, IQueryRepository { + /// + /// Cleans audit logs older than the specified maximum age. + /// + /// The maximum age of logs in minutes. void CleanLogs(int maximumAgeOfLogsInMinutes); /// @@ -36,5 +43,11 @@ IEnumerable GetPagedResultsByQuery( AuditType[]? auditTypeFilter, IQuery? customFilter); + /// + /// Gets audit items by type and query. + /// + /// The audit type to filter by. + /// The query to apply. + /// A collection of objects. IEnumerable Get(AuditType type, IQuery query); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IContentRepository.cs index e1106c57f8a6..769e15745f30 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IContentRepository.cs @@ -81,5 +81,10 @@ IEnumerable GetPage( IQuery? filter, Ordering? ordering); + /// + /// Checks the data integrity of content items. + /// + /// The options for the data integrity check. + /// A report containing the results of the integrity check. ContentDataIntegrityReport CheckDataIntegrity(ContentDataIntegrityReportOptions options); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IContentTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IContentTypeRepository.cs index 77adda58606b..fedf9cca24ab 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IContentTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IContentTypeRepository.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities (document types). +/// public interface IContentTypeRepository : IContentTypeRepositoryBase { /// @@ -28,5 +31,10 @@ public interface IContentTypeRepository : IContentTypeRepositoryBase IEnumerable GetAllContentTypeAliases(params Guid[] objectTypes); + /// + /// Gets content type identifiers by their aliases. + /// + /// The aliases of the content types. + /// A collection of content type identifiers. IEnumerable GetAllContentTypeIds(string[] aliases); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/IContentTypeRepositoryBase.cs index e90c70e89da7..9f771b009e12 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IContentTypeRepositoryBase.cs @@ -6,11 +6,26 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a base repository for content type composition entities. +/// +/// The type of content type composition. public interface IContentTypeRepositoryBase : IReadWriteQueryRepository, IReadRepository where TItem : IContentTypeComposition { + /// + /// Gets a content type by its alias. + /// + /// The alias of the content type. + /// The content type if found; otherwise, null. TItem? Get(string alias); + /// + /// Moves a content type to a container. + /// + /// The content type to move. + /// The target container. + /// A collection of move event information. IEnumerable> Move(TItem moving, EntityContainer container); /// diff --git a/src/Umbraco.Core/Persistence/Repositories/IDataTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDataTypeContainerRepository.cs index 69caeb8038c7..90bad4d427fb 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDataTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDataTypeContainerRepository.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for data type container (folder) entities. +/// public interface IDataTypeContainerRepository : IEntityContainerRepository { } diff --git a/src/Umbraco.Core/Persistence/Repositories/IDataTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDataTypeRepository.cs index f0babf61f378..b0b8e26be2a8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDataTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDataTypeRepository.cs @@ -3,11 +3,24 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IDataTypeRepository : IReadWriteQueryRepository { - + /// + /// Gets a data type by its unique key. + /// + /// The unique key of the data type. + /// The data type if found; otherwise, null. IDataType? Get(Guid key); + /// + /// Moves a data type to a container. + /// + /// The data type to move. + /// The target container, or null to move to the root. + /// A collection of move event information. IEnumerable> Move(IDataType toMove, EntityContainer? container); /// diff --git a/src/Umbraco.Core/Persistence/Repositories/IDataTypeUsageRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDataTypeUsageRepository.cs index 5de73ca05da3..199e37ee15f5 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDataTypeUsageRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDataTypeUsageRepository.cs @@ -1,6 +1,17 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for querying data type usage information. +/// public interface IDataTypeUsageRepository { + /// + /// Determines whether there are any saved property values using the specified data type. + /// + /// The unique key of the data type. + /// + /// A task that represents the asynchronous operation. The task result is true if there are saved values; + /// otherwise, false. + /// Task HasSavedValuesAsync(Guid dataTypeKey); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IDictionaryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDictionaryRepository.cs index dd9383b3e53f..39a0c7fd1749 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDictionaryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDictionaryRepository.cs @@ -2,17 +2,50 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IDictionaryRepository : IReadWriteQueryRepository { + /// + /// Gets a dictionary item by its unique identifier. + /// + /// The unique identifier of the dictionary item. + /// The dictionary item if found; otherwise, null. IDictionaryItem? Get(Guid uniqueId); + /// + /// Gets multiple dictionary items by their unique identifiers. + /// + /// The unique identifiers of the dictionary items. + /// A collection of dictionary items. IEnumerable GetMany(params Guid[] uniqueIds) => Array.Empty(); + /// + /// Gets multiple dictionary items by their keys. + /// + /// The keys of the dictionary items. + /// A collection of dictionary items. IEnumerable GetManyByKeys(params string[] keys) => Array.Empty(); + /// + /// Gets a dictionary item by its key. + /// + /// The key of the dictionary item. + /// The dictionary item if found; otherwise, null. IDictionaryItem? Get(string key); + /// + /// Gets all descendant dictionary items of a parent item. + /// + /// The unique identifier of the parent item, or null for root items. + /// An optional filter to apply to the results. + /// A collection of descendant dictionary items. IEnumerable GetDictionaryItemDescendants(Guid? parentId, string? filter = null); + /// + /// Gets a mapping of dictionary item keys to their unique identifiers. + /// + /// A dictionary mapping keys to unique identifiers. Dictionary GetDictionaryItemKeyMap(); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IDocumentBlueprintContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDocumentBlueprintContainerRepository.cs index 81eeba15e66b..e9fd159f3560 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDocumentBlueprintContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDocumentBlueprintContainerRepository.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Persistence.Repositories; +namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for document blueprint container (folder) entities. +/// public interface IDocumentBlueprintContainerRepository : IEntityContainerRepository { } diff --git a/src/Umbraco.Core/Persistence/Repositories/IDocumentBlueprintRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDocumentBlueprintRepository.cs index 12857f05881c..9add5de4b7a7 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDocumentBlueprintRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDocumentBlueprintRepository.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for document blueprint (content template) entities. +/// public interface IDocumentBlueprintRepository : IDocumentRepository { } diff --git a/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs index 6ac6470a8575..ca39c0870d77 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDocumentRepository.cs @@ -4,6 +4,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for document entities. +/// public interface IDocumentRepository : IContentRepository, IReadRepository { /// @@ -25,12 +28,31 @@ public interface IDocumentRepository : IContentRepository, IReadR /// /// Clears the publishing schedule for all entries having an a date before (lower than, or equal to) a specified date. /// + /// + /// Clears the publishing schedule for all entries having a date before (lower than, or equal to) a specified date. + /// + /// The cutoff date. void ClearSchedule(DateTime date); + /// + /// Clears the publishing schedule for entries matching the specified action and having a date before the specified date. + /// + /// The cutoff date. + /// The schedule action to clear. void ClearSchedule(DateTime date, ContentScheduleAction action); + /// + /// Checks whether there is content scheduled for expiration before the specified date. + /// + /// The date to check. + /// true if there is content scheduled for expiration; otherwise, false. bool HasContentForExpiration(DateTime date); + /// + /// Checks whether there is content scheduled for release before the specified date. + /// + /// The date to check. + /// true if there is content scheduled for release; otherwise, false. bool HasContentForRelease(DateTime date); /// @@ -69,6 +91,11 @@ public interface IDocumentRepository : IContentRepository, IReadR /// int CountPublished(string? contentTypeAlias = null); + /// + /// Checks whether the path to a content item is published. + /// + /// The content item. + /// true if the path is published; otherwise, false. bool IsPathPublished(IContent? content); /// diff --git a/src/Umbraco.Core/Persistence/Repositories/IDocumentTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDocumentTypeContainerRepository.cs index ed604ec16567..e6c128632252 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDocumentTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDocumentTypeContainerRepository.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for document type container (folder) entities. +/// public interface IDocumentTypeContainerRepository : IEntityContainerRepository { } diff --git a/src/Umbraco.Core/Persistence/Repositories/IDocumentUrlRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDocumentUrlRepository.cs index 5a3786aa1277..32f5d5598e4b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDocumentUrlRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDocumentUrlRepository.cs @@ -2,9 +2,26 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for document URL segment entities. +/// public interface IDocumentUrlRepository { + /// + /// Saves a collection of published document URL segments. + /// + /// The URL segments to save. void Save(IEnumerable publishedDocumentUrlSegments); + + /// + /// Gets all published document URL segments. + /// + /// A collection of all published document URL segments. IEnumerable GetAll(); + + /// + /// Deletes document URL segments by document keys. + /// + /// The document keys for which to delete URL segments. void DeleteByDocumentKey(IEnumerable select); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IDocumentVersionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDocumentVersionRepository.cs index 9902c8df302c..50b1d2329479 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDocumentVersionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDocumentVersionRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for document version operations. +/// public interface IDocumentVersionRepository : IRepository { /// diff --git a/src/Umbraco.Core/Persistence/Repositories/IDomainRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IDomainRepository.cs index 18b2ef1f8e89..4922bbc65887 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IDomainRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IDomainRepository.cs @@ -2,13 +2,37 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IDomainRepository : IReadWriteQueryRepository { + /// + /// Gets a domain by its name. + /// + /// The name of the domain. + /// The domain if found; otherwise, null. IDomain? GetByName(string domainName); + /// + /// Checks whether a domain with the specified name exists. + /// + /// The name of the domain. + /// true if a domain with the name exists; otherwise, false. bool Exists(string domainName); + /// + /// Gets all domains. + /// + /// Whether to include wildcard domains. + /// A collection of domains. IEnumerable GetAll(bool includeWildcards); + /// + /// Gets all domains assigned to a content item. + /// + /// The identifier of the content item. + /// Whether to include wildcard domains. + /// A collection of domains assigned to the content. IEnumerable GetAssignedDomains(int contentId, bool includeWildcards); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IEntityContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IEntityContainerRepository.cs index 5b49ba0dc529..9a4a9c9e9cdb 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IEntityContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IEntityContainerRepository.cs @@ -2,13 +2,39 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities (folders). +/// public interface IEntityContainerRepository : IReadRepository, IWriteRepository { + /// + /// Gets a container by its unique identifier. + /// + /// The unique identifier of the container. + /// The container if found; otherwise, null. EntityContainer? Get(Guid id); + /// + /// Gets containers by name and level. + /// + /// The name of the containers. + /// The level of the containers in the hierarchy. + /// A collection of containers matching the criteria. IEnumerable Get(string name, int level); + /// + /// Checks whether a container with the same name exists under the specified parent. + /// + /// The unique key of the parent container. + /// The name to check for duplicates. + /// true if a duplicate name exists; otherwise, false. bool HasDuplicateName(Guid parentKey, string name); + /// + /// Checks whether a container with the same name exists under the specified parent. + /// + /// The identifier of the parent container. + /// The name to check for duplicates. + /// true if a duplicate name exists; otherwise, false. bool HasDuplicateName(int parentId, string name); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IEntityRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IEntityRepository.cs index 9f8640c3c258..1fdec223e99c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IEntityRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IEntityRepository.cs @@ -5,18 +5,55 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for lightweight entity operations. +/// public interface IEntityRepository : IRepository { + /// + /// Gets an entity by its identifier. + /// + /// The identifier of the entity. + /// The entity if found; otherwise, null. IEntitySlim? Get(int id); + /// + /// Gets an entity by its unique key. + /// + /// The unique key of the entity. + /// The entity if found; otherwise, null. IEntitySlim? Get(Guid key); + /// + /// Gets an entity by its identifier and object type. + /// + /// The identifier of the entity. + /// The object type identifier. + /// The entity if found; otherwise, null. IEntitySlim? Get(int id, Guid objectTypeId); + /// + /// Gets an entity by its unique key and object type. + /// + /// The unique key of the entity. + /// The object type identifier. + /// The entity if found; otherwise, null. IEntitySlim? Get(Guid key, Guid objectTypeId); + /// + /// Gets all entities of a specific object type by their identifiers. + /// + /// The object type identifier. + /// The identifiers of the entities. + /// A collection of entities. IEnumerable GetAll(Guid objectType, params int[] ids); + /// + /// Gets all entities of a specific object type by their unique keys. + /// + /// The object type identifier. + /// The unique keys of the entities. + /// A collection of entities. IEnumerable GetAll(Guid objectType, params Guid[] keys); /// @@ -74,34 +111,76 @@ IEnumerable GetTrashedSiblings( } /// - /// Gets entities for a query + /// Gets entities for a query. /// - /// - /// + /// The query to apply. + /// A collection of entities matching the query. IEnumerable GetByQuery(IQuery query); /// - /// Gets entities for a query and a specific object type allowing the query to be slightly more optimized + /// Gets entities for a query and a specific object type, allowing the query to be slightly more optimized. /// - /// - /// - /// + /// The query to apply. + /// The object type identifier. + /// A collection of entities matching the query. IEnumerable GetByQuery(IQuery query, Guid objectType); + /// + /// Gets the object type for an entity by its identifier. + /// + /// The identifier of the entity. + /// The object type of the entity. UmbracoObjectTypes GetObjectType(int id); + /// + /// Gets the object type for an entity by its unique key. + /// + /// The unique key of the entity. + /// The object type of the entity. UmbracoObjectTypes GetObjectType(Guid key); + /// + /// Reserves an identifier for a given unique key. + /// + /// The unique key to reserve an identifier for. + /// The reserved identifier. int ReserveId(Guid key); + /// + /// Gets all entity paths for a specific object type. + /// + /// The object type identifier. + /// Optional identifiers to filter the results. + /// A collection of entity paths. IEnumerable GetAllPaths(Guid objectType, params int[]? ids); + /// + /// Gets all entity paths for a specific object type. + /// + /// The object type identifier. + /// The unique keys to filter the results. + /// A collection of entity paths. IEnumerable GetAllPaths(Guid objectType, params Guid[] keys); + /// + /// Checks whether an entity with the specified identifier exists. + /// + /// The identifier of the entity. + /// true if the entity exists; otherwise, false. bool Exists(int id); + /// + /// Checks whether an entity with the specified unique key exists. + /// + /// The unique key of the entity. + /// true if the entity exists; otherwise, false. bool Exists(Guid key); + /// + /// Checks whether entities with the specified unique keys exist. + /// + /// The unique keys of the entities. + /// true if all entities exist; otherwise, false. bool Exists(IEnumerable keys); /// @@ -121,16 +200,16 @@ IEnumerable GetTrashedSiblings( bool Exists(int id, Guid objectType) => throw new NotImplementedException(); /// - /// Gets paged entities for a query and a specific object type + /// Gets paged entities for a query and a specific object type. /// - /// - /// - /// - /// - /// - /// - /// - /// + /// The query to apply. + /// The object type identifier. + /// The page index. + /// The page size. + /// Returns the total number of records. + /// An optional filter query. + /// The ordering to apply, or null for default ordering. + /// A collection of entities for the specified page. IEnumerable GetPagedResultsByQuery( IQuery query, Guid objectType, @@ -141,6 +220,17 @@ IEnumerable GetPagedResultsByQuery( Ordering? ordering) => GetPagedResultsByQuery(query, new HashSet(){objectType}, pageIndex, pageSize, out totalRecords, filter, ordering); + /// + /// Gets paged entities for a query and multiple object types. + /// + /// The query to apply. + /// The object type identifiers. + /// The page index. + /// The page size. + /// Returns the total number of records. + /// An optional filter query. + /// The ordering to apply, or null for default ordering. + /// A collection of entities for the specified page. IEnumerable GetPagedResultsByQuery( IQuery query, ISet objectTypes, @@ -150,7 +240,22 @@ IEnumerable GetPagedResultsByQuery( IQuery? filter, Ordering? ordering); + /// + /// Counts entities matching a query for a specific object type. + /// + /// The query to apply. + /// The object type identifier. + /// An optional filter query. + /// The count of entities matching the query. int CountByQuery(IQuery query, Guid objectType, IQuery? filter) => CountByQuery(query, new HashSet() { objectType }, filter); + + /// + /// Counts entities matching a query for multiple object types. + /// + /// The query to apply. + /// The object type identifiers. + /// An optional filter query. + /// The count of entities matching the query. int CountByQuery(IQuery query, IEnumerable objectTypes, IQuery? filter); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IFileRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IFileRepository.cs index 53e1bb40741b..eafff263992f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IFileRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IFileRepository.cs @@ -1,10 +1,28 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for file operations. +/// public interface IFileRepository { + /// + /// Gets a stream for reading the content of a file. + /// + /// The path to the file. + /// A stream for reading the file content. Stream GetFileContentStream(string filepath); + /// + /// Sets the content of a file. + /// + /// The path to the file. + /// The stream containing the content to write. void SetFileContent(string filepath, Stream content); + /// + /// Gets the size of a file in bytes. + /// + /// The path to the file. + /// The size of the file in bytes. long GetFileSize(string filepath); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IFileWithFoldersRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IFileWithFoldersRepository.cs index 7f2916fb8528..9477d42b93f3 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IFileWithFoldersRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IFileWithFoldersRepository.cs @@ -1,12 +1,33 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for file operations with folder support. +/// public interface IFileWithFoldersRepository { + /// + /// Adds a new folder. + /// + /// The path of the folder to add. void AddFolder(string folderPath); + /// + /// Deletes a folder. + /// + /// The path of the folder to delete. void DeleteFolder(string folderPath); + /// + /// Checks whether a folder exists. + /// + /// The path of the folder. + /// true if the folder exists; otherwise, false. bool FolderExists(string folderPath); + /// + /// Checks whether a folder contains any content. + /// + /// The path of the folder. + /// true if the folder contains content; otherwise, false. bool FolderHasContent(string folderPath); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IIdKeyMapRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IIdKeyMapRepository.cs index 6520644a7f70..48ddd9677431 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IIdKeyMapRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IIdKeyMapRepository.cs @@ -2,9 +2,24 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for mapping between entity identifiers and unique keys. +/// public interface IIdKeyMapRepository { + /// + /// Gets the integer identifier for a given unique key. + /// + /// The unique key of the entity. + /// The type of the Umbraco object. + /// The integer identifier if found; otherwise, null. int? GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType); + /// + /// Gets the unique key for a given integer identifier. + /// + /// The integer identifier of the entity. + /// The type of the Umbraco object. + /// The unique key if found; otherwise, null. Guid? GetIdForKey(int id, UmbracoObjectTypes umbracoObjectType); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IInstallationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IInstallationRepository.cs index 1c1f65f01b7d..5775b75989b8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IInstallationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IInstallationRepository.cs @@ -1,8 +1,16 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for installation logging. +/// [Obsolete("Installation logging is no longer supported and this interface will be removed in Umbraco 19.")] public interface IInstallationRepository { + /// + /// Saves an installation log entry. + /// + /// The installation log to save. + /// A task representing the asynchronous operation. [Obsolete("This method no longer has any function and will be removed in Umbraco 19.")] Task SaveInstallLogAsync(InstallLog installLog); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IKeyValueRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IKeyValueRepository.cs index c9792f009d9c..8b83fa8eff0f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IKeyValueRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IKeyValueRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IKeyValueRepository : IReadRepository, IWriteRepository { /// diff --git a/src/Umbraco.Core/Persistence/Repositories/ILanguageRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ILanguageRepository.cs index f0cc9ed73ec4..f447fb3e389a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ILanguageRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ILanguageRepository.cs @@ -2,8 +2,16 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface ILanguageRepository : IReadWriteQueryRepository { + /// + /// Gets a language by its ISO code. + /// + /// The ISO code of the language. + /// The language if found; otherwise, null. ILanguage? GetByIsoCode(string isoCode); /// diff --git a/src/Umbraco.Core/Persistence/Repositories/ILogViewerQueryRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ILogViewerQueryRepository.cs index 0d1da11c9d27..7a23f69a1260 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ILogViewerQueryRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ILogViewerQueryRepository.cs @@ -2,7 +2,15 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface ILogViewerQueryRepository : IReadWriteQueryRepository { + /// + /// Gets a log viewer query by its name. + /// + /// The name of the query. + /// The log viewer query if found; otherwise, null. ILogViewerQuery? GetByName(string name); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IMediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMediaRepository.cs index d51f031071f1..565571de1413 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IMediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IMediaRepository.cs @@ -2,9 +2,21 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IMediaRepository : IContentRepository, IReadRepository { + /// + /// Gets a media item by its file path. + /// + /// The file path of the media item. + /// The media item if found; otherwise, null. IMedia? GetMediaByPath(string mediaPath); + /// + /// Returns true if there is any media in the recycle bin. + /// + /// true if the recycle bin contains items; otherwise, false. bool RecycleBinSmells(); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IMediaTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMediaTypeContainerRepository.cs index fe8c798915f9..886e69e7fca8 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IMediaTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IMediaTypeContainerRepository.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for media type container (folder) entities. +/// public interface IMediaTypeContainerRepository : IEntityContainerRepository { } diff --git a/src/Umbraco.Core/Persistence/Repositories/IMediaTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMediaTypeRepository.cs index ac06431ee836..3de2aefb0f35 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IMediaTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IMediaTypeRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IMediaTypeRepository : IContentTypeRepositoryBase { } diff --git a/src/Umbraco.Core/Persistence/Repositories/IMemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMemberGroupRepository.cs index fc12afe1d3ac..2873c495b033 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IMemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IMemberGroupRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IMemberGroupRepository : IReadWriteQueryRepository { /// @@ -38,9 +41,24 @@ public interface IMemberGroupRepository : IReadWriteQueryRepository IEnumerable GetMemberGroupsForMember(string? username); + /// + /// Replaces the roles for the specified members. + /// + /// The identifiers of the members. + /// The names of the roles to assign. void ReplaceRoles(int[] memberIds, string[] roleNames); + /// + /// Assigns roles to the specified members. + /// + /// The identifiers of the members. + /// The names of the roles to assign. void AssignRoles(int[] memberIds, string[] roleNames); + /// + /// Dissociates roles from the specified members. + /// + /// The identifiers of the members. + /// The names of the roles to dissociate. void DissociateRoles(int[] memberIds, string[] roleNames); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IMemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMemberRepository.cs index 456769e7e477..92a1154b4102 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IMemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IMemberRepository.cs @@ -5,10 +5,23 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IMemberRepository : IContentRepository { + /// + /// Gets member identifiers by their names. + /// + /// The names of the members. + /// An array of member identifiers. int[] GetMemberIds(string[] names); + /// + /// Gets a member by their username. + /// + /// The username of the member. + /// The member if found; otherwise, null. IMember? GetByUsername(string? username); /// @@ -41,6 +54,14 @@ public interface IMemberRepository : IContentRepository /// int GetCountByQuery(IQuery? query); + /// + /// Gets paged members matching the specified filter. + /// + /// The filter to apply. + /// The number of records to skip. + /// The number of records to take. + /// The ordering to apply, or null for default ordering. + /// A paged model of members. Task> GetPagedByFilterAsync(MemberFilter memberFilter,int skip, int take, Ordering? ordering = null); /// diff --git a/src/Umbraco.Core/Persistence/Repositories/IMemberTypeContainerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMemberTypeContainerRepository.cs index 255e87220684..5055ea1d5317 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IMemberTypeContainerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IMemberTypeContainerRepository.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for member type container (folder) entities. +/// public interface IMemberTypeContainerRepository : IEntityContainerRepository { } diff --git a/src/Umbraco.Core/Persistence/Repositories/IMemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMemberTypeRepository.cs index f9cd35534ace..9179a693c58a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IMemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IMemberTypeRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IMemberTypeRepository : IContentTypeRepositoryBase { } diff --git a/src/Umbraco.Core/Persistence/Repositories/INavigationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/INavigationRepository.cs index cc65d637a8b4..b5bb141c9c88 100644 --- a/src/Umbraco.Core/Persistence/Repositories/INavigationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/INavigationRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for content navigation operations. +/// public interface INavigationRepository { /// diff --git a/src/Umbraco.Core/Persistence/Repositories/INodeCountRepository.cs b/src/Umbraco.Core/Persistence/Repositories/INodeCountRepository.cs index 5f93a912fcbd..cd163cbb3da4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/INodeCountRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/INodeCountRepository.cs @@ -1,8 +1,20 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for counting nodes in the system. +/// public interface INodeCountRepository { + /// + /// Gets the count of nodes for a specific node type. + /// + /// The unique identifier of the node type. + /// The count of nodes of the specified type. int GetNodeCount(Guid nodeType); + /// + /// Gets the total count of media items. + /// + /// The count of media items. int GetMediaCount(); } diff --git a/src/Umbraco.Core/Persistence/Repositories/INotificationsRepository.cs b/src/Umbraco.Core/Persistence/Repositories/INotificationsRepository.cs index 0c36e233e104..c457ab8eab9d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/INotificationsRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/INotificationsRepository.cs @@ -5,21 +5,73 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface INotificationsRepository : IRepository { + /// + /// Tries to create a notification for a user and entity. + /// + /// The user to create the notification for. + /// The entity related to the notification. + /// The action that triggered the notification. + /// When successful, contains the created notification. + /// true if the notification was created successfully; otherwise, false. bool TryCreateNotification(IUser user, IEntity entity, string action, [NotNullWhen(true)] out Notification? notification); + /// + /// Deletes all notifications for a user. + /// + /// The user whose notifications should be deleted. + /// The number of notifications deleted. int DeleteNotifications(IUser user); + /// + /// Deletes all notifications for an entity. + /// + /// The entity whose notifications should be deleted. + /// The number of notifications deleted. int DeleteNotifications(IEntity entity); + /// + /// Deletes all notifications for a specific user and entity combination. + /// + /// The user. + /// The entity. + /// The number of notifications deleted. int DeleteNotifications(IUser user, IEntity entity); + /// + /// Gets all notifications for an entity. + /// + /// The entity to get notifications for. + /// A collection of notifications. IEnumerable GetEntityNotifications(IEntity entity); + /// + /// Gets all notifications for a user. + /// + /// The user to get notifications for. + /// A collection of notifications. IEnumerable GetUserNotifications(IUser user); + /// + /// Gets notifications for multiple users, filtered by action, node IDs, and object type. + /// + /// The user identifiers. + /// The action to filter by, or null for all actions. + /// The node identifiers to filter by. + /// The object type to filter by. + /// A collection of notifications. IEnumerable GetUsersNotifications(IEnumerable userIds, string? action, IEnumerable nodeIds, Guid objectType); + /// + /// Sets the notifications for a user and entity, replacing any existing notifications. + /// + /// The user. + /// The entity. + /// The actions to set notifications for. + /// A collection of the created notifications. IEnumerable SetNotifications(IUser user, IEntity entity, string[] actions); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IPartialViewRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IPartialViewRepository.cs index 72b8fa2af05b..d119afaffb19 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IPartialViewRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IPartialViewRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IPartialViewRepository : IReadRepository, IWriteRepository, IFileRepository, IFileWithFoldersRepository { diff --git a/src/Umbraco.Core/Persistence/Repositories/IPublicAccessRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IPublicAccessRepository.cs index 84ef0e92f59e..23a1cd0046d0 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IPublicAccessRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IPublicAccessRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IPublicAccessRepository : IReadWriteQueryRepository { } diff --git a/src/Umbraco.Core/Persistence/Repositories/IPublishStatusRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IPublishStatusRepository.cs index 3176b02a3639..043695168e3e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IPublishStatusRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IPublishStatusRepository.cs @@ -1,8 +1,30 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for querying document publish status. +/// public interface IPublishStatusRepository { + /// + /// Gets the publish status for all documents. + /// + /// A cancellation token to observe. + /// A dictionary mapping document keys to their published culture codes. Task>> GetAllPublishStatusAsync(CancellationToken cancellationToken); + + /// + /// Gets the publish status for a specific document. + /// + /// The unique key of the document. + /// A cancellation token to observe. + /// A set of culture codes for which the document is published. Task> GetPublishStatusAsync(Guid documentKey, CancellationToken cancellationToken); + + /// + /// Gets the publish status for a document and all its descendants. + /// + /// The unique key of the root document. + /// A cancellation token to observe. + /// A dictionary mapping document keys to their published culture codes. Task>> GetDescendantsOrSelfPublishStatusAsync(Guid rootDocumentKey, CancellationToken cancellationToken); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IRelationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IRelationRepository.cs index 6a7202feaa34..659fe81ef118 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IRelationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IRelationRepository.cs @@ -6,8 +6,20 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IRelationRepository : IReadWriteQueryRepository { + /// + /// Gets paged relations matching the specified query. + /// + /// The query to apply, or null to get all relations. + /// The page index. + /// The page size. + /// Returns the total number of records. + /// The ordering to apply, or null for default ordering. + /// A collection of relations for the specified page. IEnumerable GetPagedRelationsByQuery(IQuery? query, long pageIndex, int pageSize, out long totalRecords, Ordering? ordering); /// @@ -31,8 +43,35 @@ public interface IRelationRepository : IReadWriteQueryRepository /// void DeleteByParent(int parentId, params string[] relationTypeAliases); + /// + /// Gets paged parent entities for a child entity. + /// + /// The identifier of the child entity. + /// The page index. + /// The page size. + /// Returns the total number of records. + /// The entity types to filter by. + /// A collection of parent entities for the specified page. IEnumerable GetPagedParentEntitiesByChildId(int childId, long pageIndex, int pageSize, out long totalRecords, params Guid[] entityTypes); + /// + /// Gets paged child entities for a parent entity. + /// + /// The identifier of the parent entity. + /// The page index. + /// The page size. + /// Returns the total number of records. + /// The entity types to filter by. + /// A collection of child entities for the specified page. IEnumerable GetPagedChildEntitiesByParentId(int parentId, long pageIndex, int pageSize, out long totalRecords, params Guid[] entityTypes); + + /// + /// Gets paged relations by child entity key. + /// + /// The unique key of the child entity. + /// The number of records to skip. + /// The number of records to take. + /// The relation type alias to filter by, or null for all types. + /// A paged model of relations. Task> GetPagedByChildKeyAsync(Guid childKey, int skip, int take, string? relationTypeAlias); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IRelationTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IRelationTypeRepository.cs index 19929ee83f9c..6dca42b5c541 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IRelationTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IRelationTypeRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IRelationTypeRepository : IReadWriteQueryRepository, IReadRepository { diff --git a/src/Umbraco.Core/Persistence/Repositories/IScriptRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IScriptRepository.cs index f0cfe9490267..e99228a3aa3c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IScriptRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IScriptRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IScriptRepository : IReadRepository, IWriteRepository, IFileRepository, IFileWithFoldersRepository { diff --git a/src/Umbraco.Core/Persistence/Repositories/IServerRegistrationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IServerRegistrationRepository.cs index 5593dec09a5f..865416961e41 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IServerRegistrationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IServerRegistrationRepository.cs @@ -2,9 +2,19 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IServerRegistrationRepository : IReadWriteQueryRepository { + /// + /// Deactivates servers that have not been active within the specified timeout. + /// + /// The timeout after which servers are considered stale. void DeactiveStaleServers(TimeSpan staleTimeout); + /// + /// Clears the server registration cache. + /// void ClearCache(); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IStylesheetRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IStylesheetRepository.cs index 29f132a74a4e..36814ed85c6d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IStylesheetRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IStylesheetRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IStylesheetRepository : IReadRepository, IWriteRepository, IFileRepository, IFileWithFoldersRepository { diff --git a/src/Umbraco.Core/Persistence/Repositories/ITagRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ITagRepository.cs index 35c134adb3a8..99909c40f2d1 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ITagRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ITagRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface ITagRepository : IReadWriteQueryRepository { #region Assign and Remove Tags @@ -61,7 +64,13 @@ public interface ITagRepository : IReadWriteQueryRepository /// TaggedEntity? GetTaggedEntityById(int id); - /// Gets all entities of a type, tagged with any tag in the specified group. + /// + /// Gets all entities of a type, tagged with any tag in the specified group. + /// + /// The type of tagged entities. + /// The tag group. + /// The optional culture. + /// A collection of tagged entities. IEnumerable GetTaggedEntitiesByTagGroup(TaggableObjectTypes objectType, string group, string? culture = null); /// diff --git a/src/Umbraco.Core/Persistence/Repositories/ITemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ITemplateRepository.cs index 5c5881ef7a62..dda277d5c96b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ITemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ITemplateRepository.cs @@ -2,13 +2,36 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface ITemplateRepository : IReadWriteQueryRepository, IFileRepository { + /// + /// Gets a template by its alias. + /// + /// The alias of the template. + /// The template if found; otherwise, null. ITemplate? Get(string? alias); + /// + /// Gets templates by their aliases. + /// + /// The aliases of the templates. + /// A collection of templates. IEnumerable GetAll(params string[] aliases); + /// + /// Gets all child templates of a master template. + /// + /// The identifier of the master template. + /// A collection of child templates. IEnumerable GetChildren(int masterTemplateId); + /// + /// Gets all descendant templates of a master template. + /// + /// The identifier of the master template. + /// A collection of descendant templates. IEnumerable GetDescendants(int masterTemplateId); } diff --git a/src/Umbraco.Core/Persistence/Repositories/ITrackedReferencesRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ITrackedReferencesRepository.cs index b5f3ecf6fb19..dea43d1e66ed 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ITrackedReferencesRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ITrackedReferencesRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for tracking entity references and relations. +/// public interface ITrackedReferencesRepository { /// diff --git a/src/Umbraco.Core/Persistence/Repositories/ITwoFactorLoginRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ITwoFactorLoginRepository.cs index 31a279eb62a6..6305b861b5a9 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ITwoFactorLoginRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ITwoFactorLoginRepository.cs @@ -2,11 +2,30 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface ITwoFactorLoginRepository : IReadRepository, IWriteRepository { + /// + /// Deletes all two-factor login records for a user or member. + /// + /// The unique key of the user or member. + /// true if records were deleted; otherwise, false. Task DeleteUserLoginsAsync(Guid userOrMemberKey); + /// + /// Deletes two-factor login records for a specific provider for a user or member. + /// + /// The unique key of the user or member. + /// The name of the provider. + /// true if records were deleted; otherwise, false. Task DeleteUserLoginsAsync(Guid userOrMemberKey, string providerName); + /// + /// Gets all two-factor login records for a user or member. + /// + /// The unique key of the user or member. + /// A collection of two-factor login records. Task> GetByUserOrMemberKeyAsync(Guid userOrMemberKey); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IUpgradeCheckRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IUpgradeCheckRepository.cs index a782717e8382..5a326ed3ddce 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IUpgradeCheckRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IUpgradeCheckRepository.cs @@ -2,9 +2,17 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for checking for Umbraco upgrades. +/// [Obsolete("Upgrade checks are no longer supported and this interface will be removed in Umbraco 19.")] public interface IUpgradeCheckRepository { + /// + /// Checks for available upgrades for the specified version. + /// + /// The current version to check upgrades for. + /// The upgrade result containing available upgrade information. [Obsolete("This method no longer has any function and will be removed in Umbraco 19.")] Task CheckUpgradeAsync(SemVersion version); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IUserDataRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IUserDataRepository.cs index cf53f049b79b..cc639e13fff9 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IUserDataRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IUserDataRepository.cs @@ -4,15 +4,45 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IUserDataRepository { + /// + /// Gets user data by its unique key. + /// + /// The unique key of the user data. + /// The user data if found; otherwise, null. Task GetAsync(Guid key); + /// + /// Gets paged user data. + /// + /// The number of records to skip. + /// The number of records to take. + /// An optional filter to apply. + /// A paged model of user data. Task> GetAsync(int skip, int take, IUserDataFilter? filter = null); + /// + /// Saves new user data. + /// + /// The user data to save. + /// The saved user data. Task Save(IUserData userData); + /// + /// Updates existing user data. + /// + /// The user data to update. + /// The updated user data. Task Update(IUserData userData); + /// + /// Deletes user data. + /// + /// The user data to delete. + /// A task representing the asynchronous operation. Task Delete(IUserData userData); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IUserGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IUserGroupRepository.cs index 4a9b760ca70a..6a8a67f6f308 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IUserGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IUserGroupRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IUserGroupRepository : IReadWriteQueryRepository { /// diff --git a/src/Umbraco.Core/Persistence/Repositories/IUserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IUserRepository.cs index 4b006ecb1c4f..251ad2aa0861 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IUserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IUserRepository.cs @@ -4,6 +4,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IUserRepository : IReadWriteQueryRepository { /// @@ -135,30 +138,96 @@ IEnumerable GetPagedResultsByQuery( /// IUser? Get(int? id, bool includeSecurityData); + /// + /// Gets a user profile by username. + /// + /// The username. + /// The user profile if found; otherwise, null. IProfile? GetProfile(string username); + /// + /// Gets a user profile by identifier. + /// + /// The user identifier. + /// The user profile if found; otherwise, null. IProfile? GetProfile(int id); + /// + /// Gets the count of users grouped by their state. + /// + /// A dictionary mapping user states to their counts. IDictionary GetUserStates(); + /// + /// Creates a login session for a user. + /// + /// The user identifier. + /// The IP address of the requesting client. + /// Whether to clean stale sessions. + /// The unique identifier of the created session. Guid CreateLoginSession(int? userId, string requestingIpAddress, bool cleanStaleSessions = true); + /// + /// Validates a login session for a user. + /// + /// The user identifier. + /// The session identifier. + /// true if the session is valid; otherwise, false. bool ValidateLoginSession(int userId, Guid sessionId); + /// + /// Clears all login sessions for a user. + /// + /// The user identifier. + /// The number of sessions cleared. int ClearLoginSessions(int userId); + /// + /// Clears login sessions older than the specified timespan. + /// + /// The timespan after which sessions are considered stale. + /// The number of sessions cleared. int ClearLoginSessions(TimeSpan timespan); + /// + /// Clears a specific login session. + /// + /// The session identifier. void ClearLoginSession(Guid sessionId); + /// + /// Gets all client identifiers. + /// + /// A collection of client identifiers. IEnumerable GetAllClientIds(); + /// + /// Gets all client identifiers for a user. + /// + /// The user identifier. + /// A collection of client identifiers. IEnumerable GetClientIds(int id); + /// + /// Adds a client identifier for a user. + /// + /// The user identifier. + /// The client identifier to add. void AddClientId(int id, string clientId); + /// + /// Removes a client identifier from a user. + /// + /// The user identifier. + /// The client identifier to remove. + /// true if the client identifier was removed; otherwise, false. bool RemoveClientId(int id, string clientId); + /// + /// Gets a user by their client identifier. + /// + /// The client identifier. + /// The user if found; otherwise, null. IUser? GetByClientId(string clientId); /// diff --git a/src/Umbraco.Core/Persistence/Repositories/IWebProfilerRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IWebProfilerRepository.cs index d78bcdcd2ca6..878f7ccc168c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IWebProfilerRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IWebProfilerRepository.cs @@ -1,7 +1,21 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for managing web profiler status per user. +/// public interface IWebProfilerRepository { + /// + /// Sets the web profiler status for a user. + /// + /// The identifier of the user. + /// The status to set (true to enable, false to disable). void SetStatus(int userId, bool status); + + /// + /// Gets the web profiler status for a user. + /// + /// The identifier of the user. + /// true if the web profiler is enabled for the user; otherwise, false. bool GetStatus(int userId); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IWebhookLogRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IWebhookLogRepository.cs index cbb012bf04c6..165d66266706 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IWebhookLogRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IWebhookLogRepository.cs @@ -2,13 +2,34 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IWebhookLogRepository { + /// + /// Creates a new webhook log entry. + /// + /// The webhook log to create. + /// A task representing the asynchronous operation. Task CreateAsync(WebhookLog log); + /// + /// Gets paged webhook logs. + /// + /// The number of records to skip. + /// The number of records to take. + /// A paged model of webhook logs. Task> GetPagedAsync(int skip, int take); // TODO (V16): Remove the default implementation on this method. + /// + /// Gets paged webhook logs for a specific webhook. + /// + /// The unique key of the webhook. + /// The number of records to skip. + /// The number of records to take. + /// A paged model of webhook logs for the specified webhook. async Task> GetPagedAsync(Guid webhookKey, int skip, int take) { // This is very inefficient as the filter/skip/take is in-memory, but it will return the correct data. @@ -19,7 +40,17 @@ async Task> GetPagedAsync(Guid webhookKey, int skip, int return new PagedModel(logsForId.Count, logsForId.Skip(skip).Take(take)); } + /// + /// Gets webhook logs older than the specified date. + /// + /// The cutoff date. + /// A collection of webhook logs older than the specified date. Task> GetOlderThanDate(DateTime date); + /// + /// Deletes webhook logs by their identifiers. + /// + /// The identifiers of the logs to delete. + /// A task representing the asynchronous operation. Task DeleteByIds(int[] ids); } diff --git a/src/Umbraco.Core/Persistence/Repositories/IWebhookRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IWebhookRepository.cs index c75bb1b50f7c..7cbbfdd88fcf 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IWebhookRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IWebhookRepository.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IWebhookRepository { /// diff --git a/src/Umbraco.Core/Persistence/Repositories/IWebhookRequestRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IWebhookRequestRepository.cs index 1a2b7b158d90..e8c33834ba8c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IWebhookRequestRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IWebhookRequestRepository.cs @@ -1,7 +1,10 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Represents a repository for entities. +/// public interface IWebhookRequestRepository { /// diff --git a/src/Umbraco.Core/Persistence/Repositories/InstallationRepository.cs b/src/Umbraco.Core/Persistence/Repositories/InstallationRepository.cs index 991af0001ee8..a6ec5919f14a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/InstallationRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/InstallationRepository.cs @@ -3,15 +3,22 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Provides an implementation of for installation logging. +/// [Obsolete("Installation logging is no longer supported and this class will be removed in Umbraco 19.")] public class InstallationRepository : IInstallationRepository { - + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public InstallationRepository(IJsonSerializer jsonSerializer) { } + /// [Obsolete("This method no longer has any function and will be removed in Umbraco 19.")] public Task SaveInstallLogAsync(InstallLog installLog) => Task.CompletedTask; } diff --git a/src/Umbraco.Core/Persistence/Repositories/UpgradeCheckRepository.cs b/src/Umbraco.Core/Persistence/Repositories/UpgradeCheckRepository.cs index ddd9c0cf8204..d60dcad9ba9c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/UpgradeCheckRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/UpgradeCheckRepository.cs @@ -3,14 +3,22 @@ namespace Umbraco.Cms.Core.Persistence.Repositories; +/// +/// Provides an implementation of for checking for Umbraco upgrades. +/// [Obsolete("Upgrade checks are no longer supported and this repository will be removed in Umbraco 19.")] public class UpgradeCheckRepository : IUpgradeCheckRepository { + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public UpgradeCheckRepository(IJsonSerializer jsonSerializer) { } + /// [Obsolete("This method no longer has any function and will be removed in Umbraco 19.")] public Task CheckUpgradeAsync(SemVersion version) => Task.FromResult(new UpgradeResult("None", string.Empty, string.Empty)); } diff --git a/src/Umbraco.Core/Persistence/SqlExpressionExtensions.cs b/src/Umbraco.Core/Persistence/SqlExpressionExtensions.cs index 20db5106d7fe..e5633deb59ec 100644 --- a/src/Umbraco.Core/Persistence/SqlExpressionExtensions.cs +++ b/src/Umbraco.Core/Persistence/SqlExpressionExtensions.cs @@ -21,8 +21,24 @@ public static bool SqlNullableEquals(this T? value, T? other, T fallbackValue where T : struct => (value ?? fallbackValue).Equals(other ?? fallbackValue); + /// + /// Indicates whether a collection contains a specified item for use in SQL IN expressions. + /// + /// The type of elements in the collection. + /// The collection to check. + /// The item to locate. + /// true if the item is found in the collection; otherwise, false. + /// Do not use outside of SQL expressions. public static bool SqlIn(this IEnumerable collection, T item) => collection.Contains(item); + /// + /// Performs a wildcard match on a string, where % represents any sequence of characters. + /// + /// The string to match against. + /// The pattern containing % wildcards. + /// The type of the text column. + /// true if the string matches the pattern; otherwise, false. + /// Do not use outside of SQL expressions. public static bool SqlWildcard(this string str, string txt, TextColumnType columnType) { var wildcardmatch = new Regex("^" + Regex.Escape(txt). @@ -34,14 +50,46 @@ public static bool SqlWildcard(this string str, string txt, TextColumnType colum } #pragma warning disable IDE0060 // Remove unused parameter + /// + /// Indicates whether a string contains another string using culture-invariant comparison. + /// + /// The string to search within. + /// The string to find. + /// The type of the text column. + /// true if the string contains the specified text; otherwise, false. + /// Do not use outside of SQL expressions. public static bool SqlContains(this string str, string txt, TextColumnType columnType) => str.InvariantContains(txt); + /// + /// Indicates whether two strings are equal using culture-invariant comparison. + /// + /// The first string to compare. + /// The second string to compare. + /// The type of the text column. + /// true if the strings are equal; otherwise, false. + /// Do not use outside of SQL expressions. public static bool SqlEquals(this string str, string txt, TextColumnType columnType) => str.InvariantEquals(txt); + /// + /// Indicates whether a string starts with another string using culture-invariant comparison. + /// + /// The string to search within. + /// The string to find at the start. + /// The type of the text column. + /// true if the string starts with the specified text; otherwise, false. + /// Do not use outside of SQL expressions. public static bool SqlStartsWith(this string? str, string txt, TextColumnType columnType) => str?.InvariantStartsWith(txt) ?? false; + /// + /// Indicates whether a string ends with another string using culture-invariant comparison. + /// + /// The string to search within. + /// The string to find at the end. + /// The type of the text column. + /// true if the string ends with the specified text; otherwise, false. + /// Do not use outside of SQL expressions. public static bool SqlEndsWith(this string str, string txt, TextColumnType columnType) => str.InvariantEndsWith(txt); #pragma warning restore IDE0060 // Remove unused parameter diff --git a/src/Umbraco.Core/Persistence/TextColumnType.cs b/src/Umbraco.Core/Persistence/TextColumnType.cs index 9e3a4dd71b70..58f292418213 100644 --- a/src/Umbraco.Core/Persistence/TextColumnType.cs +++ b/src/Umbraco.Core/Persistence/TextColumnType.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Persistence; +/// +/// Specifies the type of text column in the database. +/// public enum TextColumnType { + /// + /// A variable-length Unicode string column (nvarchar). + /// NVarchar, + + /// + /// A large Unicode text column (ntext). + /// NText, } diff --git a/src/Umbraco.Core/Preview/IPreviewTokenGenerator.cs b/src/Umbraco.Core/Preview/IPreviewTokenGenerator.cs index 1b1d649268b7..c69cc77e64ee 100644 --- a/src/Umbraco.Core/Preview/IPreviewTokenGenerator.cs +++ b/src/Umbraco.Core/Preview/IPreviewTokenGenerator.cs @@ -1,7 +1,25 @@ namespace Umbraco.Cms.Core.Preview; +/// +/// Generates and verifies preview tokens for content preview functionality. +/// +/// +/// Preview tokens allow users to preview unpublished content by generating +/// secure, time-limited tokens that can be verified on subsequent requests. +/// public interface IPreviewTokenGenerator { + /// + /// Generates a preview token for the specified user. + /// + /// The unique key of the user requesting the preview token. + /// An attempt containing the generated token string on success, or a failure result. Task> GenerateTokenAsync(Guid userKey); + + /// + /// Verifies a preview token and returns the associated user key. + /// + /// The preview token to verify. + /// An attempt containing the user key on success, or a failure result if the token is invalid or expired. Task> VerifyAsync(string token); } diff --git a/src/Umbraco.Core/Preview/NoopPreviewTokenGenerator.cs b/src/Umbraco.Core/Preview/NoopPreviewTokenGenerator.cs index 8a9c0e823471..429b18f4dc8c 100644 --- a/src/Umbraco.Core/Preview/NoopPreviewTokenGenerator.cs +++ b/src/Umbraco.Core/Preview/NoopPreviewTokenGenerator.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.Preview; +/// +/// A no-operation implementation of that always fails. +/// +/// +/// This implementation is used as a placeholder when preview functionality is not configured or available. +/// All operations return failed attempts. +/// public class NoopPreviewTokenGenerator : IPreviewTokenGenerator { + /// public Task> GenerateTokenAsync(Guid userKey) => Task.FromResult(Attempt.Fail(string.Empty)); + /// public Task> VerifyAsync(string token) => Task.FromResult(Attempt.Fail(null)); } diff --git a/src/Umbraco.Core/PropertyEditors/BlockGridConfiguration.cs b/src/Umbraco.Core/PropertyEditors/BlockGridConfiguration.cs index ade1da8b8af2..a9cf70eacf55 100644 --- a/src/Umbraco.Core/PropertyEditors/BlockGridConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/BlockGridConfiguration.cs @@ -8,49 +8,109 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class BlockGridConfiguration { + /// + /// Gets or sets the configured blocks for the Block Grid editor. + /// [ConfigurationField("blocks")] public BlockGridBlockConfiguration[] Blocks { get; set; } = Array.Empty(); + /// + /// Gets or sets the validation limits for the number of blocks allowed. + /// [ConfigurationField("validationLimit")] public NumberRange ValidationLimit { get; set; } = new NumberRange(); + /// + /// Gets or sets the number of grid columns available in the Block Grid. + /// [ConfigurationField("gridColumns")] public int? GridColumns { get; set; } + /// + /// Represents the configuration for a single block type in the Block Grid editor. + /// public class BlockGridBlockConfiguration : IBlockConfiguration { + /// + /// Gets or sets the number of grid columns available within this block's areas. + /// public int? AreaGridColumns { get; set; } + /// + /// Gets or sets the configured areas within this block. + /// public BlockGridAreaConfiguration[] Areas { get; set; } = Array.Empty(); + /// + /// Gets or sets the unique key of the content element type for this block. + /// public Guid ContentElementTypeKey { get; set; } + /// + /// Gets or sets the unique key of the settings element type for this block, if any. + /// public Guid? SettingsElementTypeKey { get; set; } + /// + /// Gets or sets a value indicating whether this block can be placed at the root level of the grid. + /// public bool AllowAtRoot { get; set; } + /// + /// Gets or sets a value indicating whether this block can be placed within areas of other blocks. + /// public bool AllowInAreas { get; set; } } + /// + /// Represents a numeric range with optional minimum and maximum values. + /// public class NumberRange { + /// + /// Gets or sets the minimum value of the range. + /// public int? Min { get; set; } + /// + /// Gets or sets the maximum value of the range. + /// public int? Max { get; set; } } + /// + /// Represents the configuration for an area within a Block Grid block. + /// public class BlockGridAreaConfiguration { + /// + /// Gets or sets the unique key identifying this area. + /// public Guid Key { get; set; } + /// + /// Gets or sets the alias of this area. + /// public string? Alias { get; set; } + /// + /// Gets or sets the number of columns this area spans. + /// public int? ColumnSpan { get; set; } + /// + /// Gets or sets the number of rows this area spans. + /// public int? RowSpan { get; set; } + /// + /// Gets or sets the minimum number of blocks allowed in this area. + /// public int? MinAllowed { get; set; } + /// + /// Gets or sets the maximum number of blocks allowed in this area. + /// public int? MaxAllowed { get; set; } } } diff --git a/src/Umbraco.Core/PropertyEditors/BlockListConfiguration.cs b/src/Umbraco.Core/PropertyEditors/BlockListConfiguration.cs index 0e4c5fe00f0b..d867bc4b8f9b 100644 --- a/src/Umbraco.Core/PropertyEditors/BlockListConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/BlockListConfiguration.cs @@ -8,27 +8,50 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class BlockListConfiguration { + /// + /// Gets or sets the available block type configurations. + /// [ConfigurationField("blocks")] public BlockConfiguration[] Blocks { get; set; } = Array.Empty(); + /// + /// Gets or sets the validation limit for the number of blocks. + /// [ConfigurationField("validationLimit")] public NumberRange ValidationLimit { get; set; } = new(); + /// + /// Gets or sets a value indicating whether single block mode is enabled. + /// [ConfigurationField("useSingleBlockMode")] [Obsolete("Use SingleBlockPropertyEditor and its configuration instead")] public bool UseSingleBlockMode { get; set; } + /// + /// Represents the configuration for a single block type in the Block List. + /// public class BlockConfiguration : IBlockConfiguration { + /// public Guid ContentElementTypeKey { get; set; } + /// public Guid? SettingsElementTypeKey { get; set; } } + /// + /// Represents a number range with optional minimum and maximum values. + /// public class NumberRange { + /// + /// Gets or sets the minimum number of blocks allowed. + /// public int? Min { get; set; } + /// + /// Gets or sets the maximum number of blocks allowed. + /// public int? Max { get; set; } } } diff --git a/src/Umbraco.Core/PropertyEditors/ColorPickerConfiguration.cs b/src/Umbraco.Core/PropertyEditors/ColorPickerConfiguration.cs index e2c2279248a0..5ded842befa4 100644 --- a/src/Umbraco.Core/PropertyEditors/ColorPickerConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/ColorPickerConfiguration.cs @@ -5,16 +5,31 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class ColorPickerConfiguration { + /// + /// Gets or sets a value indicating whether to display color labels. + /// [ConfigurationField("useLabel")] public bool UseLabel { get; set; } + /// + /// Gets or sets the list of available color items. + /// [ConfigurationField("items")] public List Items { get; set; } = new(); + /// + /// Represents a single color item in the color picker. + /// public class ColorPickerItem { + /// + /// Gets or sets the color value (typically a hex color code). + /// public required string Value { get; set; } + /// + /// Gets or sets the display label for the color. + /// public required string Label { get; set; } } } diff --git a/src/Umbraco.Core/PropertyEditors/ConfigurationEditor{TConfiguration}.cs b/src/Umbraco.Core/PropertyEditors/ConfigurationEditor{TConfiguration}.cs index 041ad5951426..a36acfc1ef57 100644 --- a/src/Umbraco.Core/PropertyEditors/ConfigurationEditor{TConfiguration}.cs +++ b/src/Umbraco.Core/PropertyEditors/ConfigurationEditor{TConfiguration}.cs @@ -46,6 +46,12 @@ public override object ToConfigurationObject( } } + /// + /// Converts a configuration dictionary to the typed configuration object. + /// + /// The configuration dictionary. + /// The configuration editor JSON serializer. + /// The typed configuration object, or default if conversion fails. protected TConfiguration? AsConfigurationObject( IDictionary configuration, IConfigurationEditorJsonSerializer configurationEditorJsonSerializer) => diff --git a/src/Umbraco.Core/PropertyEditors/ContentPickerConfiguration.cs b/src/Umbraco.Core/PropertyEditors/ContentPickerConfiguration.cs index fbef443da1e6..a3a7faffabc3 100644 --- a/src/Umbraco.Core/PropertyEditors/ContentPickerConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/ContentPickerConfiguration.cs @@ -1,7 +1,11 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents the configuration for the content picker property editor. +/// public class ContentPickerConfiguration : IIgnoreUserStartNodesConfig { + /// [ConfigurationField(Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes)] public bool IgnoreUserStartNodes { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/ContentPickerConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/ContentPickerConfigurationEditor.cs index 7997db5f0fd8..04b484bbe515 100644 --- a/src/Umbraco.Core/PropertyEditors/ContentPickerConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ContentPickerConfigurationEditor.cs @@ -5,8 +5,15 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents the configuration editor for the content picker property editor. +/// internal sealed class ContentPickerConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// + /// The IO helper. public ContentPickerConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) { diff --git a/src/Umbraco.Core/PropertyEditors/ContentPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/ContentPickerPropertyEditor.cs index ae8773defcbe..747ab67d82d5 100644 --- a/src/Umbraco.Core/PropertyEditors/ContentPickerPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ContentPickerPropertyEditor.cs @@ -14,7 +14,7 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// -/// Content property editor that stores UDI +/// Content property editor that stores UDI. /// [DataEditor( Constants.PropertyEditors.Aliases.ContentPicker, @@ -24,6 +24,11 @@ public class ContentPickerPropertyEditor : DataEditor { private readonly IIOHelper _ioHelper; + /// + /// Initializes a new instance of the class. + /// + /// The data value editor factory. + /// The IO helper. public ContentPickerPropertyEditor(IDataValueEditorFactory dataValueEditorFactory, IIOHelper ioHelper) : base(dataValueEditorFactory) { @@ -31,15 +36,26 @@ public ContentPickerPropertyEditor(IDataValueEditorFactory dataValueEditorFactor SupportsReadOnly = true; } + /// protected override IConfigurationEditor CreateConfigurationEditor() => new ContentPickerConfigurationEditor(_ioHelper); + /// protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); + /// + /// Provides the value editor for the content picker property editor. + /// internal sealed class ContentPickerPropertyValueEditor : DataValueEditor, IDataValueReference { - + /// + /// Initializes a new instance of the class. + /// + /// The short string helper. + /// The JSON serializer. + /// The IO helper. + /// The data editor attribute. public ContentPickerPropertyValueEditor( IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, @@ -49,6 +65,7 @@ public ContentPickerPropertyValueEditor( { } + /// public IEnumerable GetReferences(object? value) { var asString = value is string str ? str : value?.ToString(); @@ -64,13 +81,17 @@ public IEnumerable GetReferences(object? value) } } - // starting in v14 the passed in value is always a guid, we store it as a document Udi string. Else it's an invalid value + /// + /// + /// Starting in v14, the passed in value is always a GUID. The value is stored as a document UDI string. + /// public override object? FromEditor(ContentPropertyData editorValue, object? currentValue) => editorValue.Value is not null && Guid.TryParse(editorValue.Value.ToString(), out Guid guidValue) ? GuidUdi.Create(Constants.UdiEntityType.Document, guidValue).ToString() : null; + /// public override object? ToEditor(IProperty property, string? culture = null, string? segment = null) { // since our storage type is a string, we can expect the base to return a string diff --git a/src/Umbraco.Core/PropertyEditors/DataEditor.cs b/src/Umbraco.Core/PropertyEditors/DataEditor.cs index 14018dc8117e..a854f1bcd6b3 100644 --- a/src/Umbraco.Core/PropertyEditors/DataEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/DataEditor.cs @@ -58,6 +58,9 @@ public DataEditor(IDataValueEditorFactory dataValueEditorFactory) /// protected DataEditorAttribute? Attribute { get; } + /// + /// Gets the data value editor factory used to create value editors. + /// protected IDataValueEditorFactory DataValueEditorFactory { get; } /// @@ -75,8 +78,13 @@ public DataEditor(IDataValueEditorFactory dataValueEditorFactory) [DataMember(Name = "supportsReadOnly", IsRequired = true)] public bool SupportsReadOnly { get; set; } - // Adding a virtual method that wraps the default implementation allows derived classes - // to override the default implementation without having to explicitly inherit the interface. + /// + /// Gets a value indicating whether the data editor supports configurable elements. + /// + /// + /// Adding a virtual method that wraps the default implementation allows derived classes + /// to override the default implementation without having to explicitly inherit the interface. + /// public virtual bool SupportsConfigurableElements => false; /// @@ -203,6 +211,7 @@ protected virtual IConfigurationEditor CreateConfigurationEditor() /// public virtual object? MergePartialPropertyValueForCulture(object? sourceValue, object? targetValue, string? culture) => sourceValue; + /// public virtual object? MergeVariantInvariantPropertyValue( object? sourceValue, object? targetValue, diff --git a/src/Umbraco.Core/PropertyEditors/DataEditorCollection.cs b/src/Umbraco.Core/PropertyEditors/DataEditorCollection.cs index 40daf7ec7c34..2b6bc3fbfdef 100644 --- a/src/Umbraco.Core/PropertyEditors/DataEditorCollection.cs +++ b/src/Umbraco.Core/PropertyEditors/DataEditorCollection.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a collection of instances. +/// public class DataEditorCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection items. public DataEditorCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs index 36e70f2738f2..5dc9866bd61f 100644 --- a/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/DataEditorCollectionBuilder.cs @@ -1,9 +1,13 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a builder for the . +/// public class DataEditorCollectionBuilder : LazyCollectionBuilderBase { + /// protected override DataEditorCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs b/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs index 1c32dc3de6eb..4de09291e794 100644 --- a/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/DataValueEditor.cs @@ -65,6 +65,9 @@ public DataValueEditor( /// public virtual object? ConfigurationObject { get; set; } + /// + /// Gets or sets a value indicating whether this value editor supports read-only mode. + /// public bool SupportsReadOnly { get; set; } /// @@ -341,8 +344,14 @@ public virtual string ConvertDbToString(IPropertyType propertyType, object? valu } } - // Adding a virtual method that wraps the default implementation allows derived classes - // to override the default implementation without having to explicitly inherit the interface. + /// + /// Gets the keys of element types that are configured for this value editor. + /// + /// An enumerable of element type keys, or an empty enumerable if none are configured. + /// + /// Adding a virtual method that wraps the default implementation allows derived classes + /// to override the default implementation without having to explicitly inherit the interface. + /// public virtual IEnumerable ConfiguredElementTypeKeys() => Enumerable.Empty(); /// diff --git a/src/Umbraco.Core/PropertyEditors/DataValueEditorFactory.cs b/src/Umbraco.Core/PropertyEditors/DataValueEditorFactory.cs index 86b771bcaad4..e8b6783a22ad 100644 --- a/src/Umbraco.Core/PropertyEditors/DataValueEditorFactory.cs +++ b/src/Umbraco.Core/PropertyEditors/DataValueEditorFactory.cs @@ -3,12 +3,20 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Provides a factory for creating instances. +/// public class DataValueEditorFactory : IDataValueEditorFactory { private readonly IServiceProvider _serviceProvider; + /// + /// Initializes a new instance of the class. + /// + /// The service provider used to resolve dependencies. public DataValueEditorFactory(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; + /// public TDataValueEditor Create(params object[] args) where TDataValueEditor : class, IDataValueEditor => _serviceProvider.CreateInstance(args); diff --git a/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollection.cs b/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollection.cs index c5eed0e9c99e..74587ad49da0 100644 --- a/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollection.cs +++ b/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollection.cs @@ -146,6 +146,11 @@ private IEnumerable GetReferencesFromPropertyValues(IEnu return result; } + /// + /// Gets all automatic relation type aliases for all property editors. + /// + /// The property editors collection. + /// A set of automatic relation type aliases. public ISet GetAllAutomaticRelationTypesAliases(PropertyEditorCollection propertyEditors) { // Always add default automatic relation types diff --git a/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionBuilder.cs index f2868276537e..7ec046976aee 100644 --- a/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/DataValueReferenceFactoryCollectionBuilder.cs @@ -1,8 +1,12 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a builder for the . +/// public class DataValueReferenceFactoryCollectionBuilder : OrderedCollectionBuilderBase { + /// protected override DataValueReferenceFactoryCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/PropertyEditors/DateTimeConfiguration.cs b/src/Umbraco.Core/PropertyEditors/DateTimeConfiguration.cs index 0198e9463077..fa57a4311030 100644 --- a/src/Umbraco.Core/PropertyEditors/DateTimeConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/DateTimeConfiguration.cs @@ -5,6 +5,9 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents the configuration for the DateTime property editor. +/// public class DateTimeConfiguration { /// @@ -13,6 +16,9 @@ public class DateTimeConfiguration [ConfigurationField("timeZones")] public TimeZonesConfiguration? TimeZones { get; set; } + /// + /// Represents the time zone configuration options for the DateTime property editor. + /// public class TimeZonesConfiguration { /// @@ -26,6 +32,9 @@ public class TimeZonesConfiguration public List TimeZones { get; set; } = []; } + /// + /// Specifies the time zone display mode for the DateTime property editor. + /// public enum TimeZoneMode { /// diff --git a/src/Umbraco.Core/PropertyEditors/DateValueEditor.cs b/src/Umbraco.Core/PropertyEditors/DateValueEditor.cs index c6c6387c2a81..502b99597fa6 100644 --- a/src/Umbraco.Core/PropertyEditors/DateValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/DateValueEditor.cs @@ -14,6 +14,13 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// internal sealed class DateValueEditor : DataValueEditor { + /// + /// Initializes a new instance of the class. + /// + /// The short string helper. + /// The JSON serializer. + /// The IO helper. + /// The data editor attribute. public DateValueEditor( IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, @@ -22,6 +29,7 @@ public DateValueEditor( : base(shortStringHelper, jsonSerializer, ioHelper, attribute) => Validators.Add(new DateTimeValidator()); + /// public override object ToEditor(IProperty property, string? culture = null, string? segment = null) { Attempt date = property.GetValue(culture, segment).TryConvertTo(); diff --git a/src/Umbraco.Core/PropertyEditors/DecimalConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/DecimalConfigurationEditor.cs index ada98feea458..4be45297b0f0 100644 --- a/src/Umbraco.Core/PropertyEditors/DecimalConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/DecimalConfigurationEditor.cs @@ -7,6 +7,9 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class DecimalConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// public DecimalConfigurationEditor() { Fields.Add(new ConfigurationField(new DecimalValidator()) diff --git a/src/Umbraco.Core/PropertyEditors/DefaultPropertyValueConverterAttribute.cs b/src/Umbraco.Core/PropertyEditors/DefaultPropertyValueConverterAttribute.cs index a414d765428c..027893b62a80 100644 --- a/src/Umbraco.Core/PropertyEditors/DefaultPropertyValueConverterAttribute.cs +++ b/src/Umbraco.Core/PropertyEditors/DefaultPropertyValueConverterAttribute.cs @@ -6,8 +6,16 @@ namespace Umbraco.Cms.Core.PropertyEditors; [AttributeUsage(AttributeTargets.Class, Inherited = false)] public class DefaultPropertyValueConverterAttribute : Attribute { + /// + /// Initializes a new instance of the class. + /// public DefaultPropertyValueConverterAttribute() => DefaultConvertersToShadow = Array.Empty(); + /// + /// Initializes a new instance of the class + /// that shadows the specified converters. + /// + /// The types of default converters that this converter should shadow. public DefaultPropertyValueConverterAttribute(params Type[] convertersToShadow) => DefaultConvertersToShadow = convertersToShadow; diff --git a/src/Umbraco.Core/PropertyEditors/DeliveryApi/IDeliveryApiPropertyValueConverter.cs b/src/Umbraco.Core/PropertyEditors/DeliveryApi/IDeliveryApiPropertyValueConverter.cs index 5cc91549ce41..d823760dd897 100644 --- a/src/Umbraco.Core/PropertyEditors/DeliveryApi/IDeliveryApiPropertyValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/DeliveryApi/IDeliveryApiPropertyValueConverter.cs @@ -2,6 +2,13 @@ namespace Umbraco.Cms.Core.PropertyEditors.DeliveryApi; +/// +/// Provides property value conversion for the Delivery API. +/// +/// +/// Implement this interface in addition to to provide +/// specialized value conversion for the Delivery API output. +/// public interface IDeliveryApiPropertyValueConverter : IPropertyValueConverter { /// diff --git a/src/Umbraco.Core/PropertyEditors/DropDownFlexibleConfiguration.cs b/src/Umbraco.Core/PropertyEditors/DropDownFlexibleConfiguration.cs index fb0db0d9d9ad..019aa004086d 100644 --- a/src/Umbraco.Core/PropertyEditors/DropDownFlexibleConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/DropDownFlexibleConfiguration.cs @@ -1,7 +1,13 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents the configuration for the flexible dropdown property editor. +/// public class DropDownFlexibleConfiguration : ValueListConfiguration { + /// + /// Gets or sets a value indicating whether multiple selections are allowed. + /// [ConfigurationField("multiple")] public bool Multiple { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/EntityDataPickerConfiguration.cs b/src/Umbraco.Core/PropertyEditors/EntityDataPickerConfiguration.cs index bdbaa636dd07..f05eb783d964 100644 --- a/src/Umbraco.Core/PropertyEditors/EntityDataPickerConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/EntityDataPickerConfiguration.cs @@ -1,17 +1,35 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents the configuration for the Entity Data Picker property editor. +/// public sealed class EntityDataPickerConfiguration { + /// + /// Gets or sets the validation limit for the number of selected entities. + /// [ConfigurationField("validationLimit")] public NumberRange ValidationLimit { get; set; } = new(); + /// + /// Gets or sets the data source identifier for the entity picker. + /// [ConfigurationField("umbEditorDataSource")] public string DataSource { get; set; } = string.Empty; + /// + /// Represents a number range with optional minimum and maximum values. + /// public class NumberRange { + /// + /// Gets or sets the minimum number of items allowed. + /// public int? Min { get; set; } + /// + /// Gets or sets the maximum number of items allowed. + /// public int? Max { get; set; } } } diff --git a/src/Umbraco.Core/PropertyEditors/EntityDataPickerConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/EntityDataPickerConfigurationEditor.cs index 16f7d644fafb..96ef16d695e9 100644 --- a/src/Umbraco.Core/PropertyEditors/EntityDataPickerConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/EntityDataPickerConfigurationEditor.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents the configuration editor for the entity data picker property editor. +/// internal sealed class EntityDataPickerConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// + /// The IO helper. public EntityDataPickerConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) { diff --git a/src/Umbraco.Core/PropertyEditors/EntityDataPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/EntityDataPickerPropertyEditor.cs index 29604e24ef67..d51d0ff57ef5 100644 --- a/src/Umbraco.Core/PropertyEditors/EntityDataPickerPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/EntityDataPickerPropertyEditor.cs @@ -119,8 +119,14 @@ public IEnumerable Validate( } } + /// + /// Represents the data transfer object for entity data picker values. + /// internal sealed class EntityDataPickerDto { + /// + /// Gets or sets the array of selected entity identifiers. + /// public string[] Ids { get; set; } = []; } } diff --git a/src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs index f37bb48be6d3..39633c1a509d 100644 --- a/src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/EyeDropperColorPickerPropertyEditor.cs @@ -1,10 +1,17 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a property editor for selecting colors using an eye dropper. +/// [DataEditor( Constants.PropertyEditors.Aliases.ColorPickerEyeDropper, ValueEditorIsReusable = true)] public class EyeDropperColorPickerPropertyEditor : DataEditor { + /// + /// Initializes a new instance of the class. + /// + /// The data value editor factory. public EyeDropperColorPickerPropertyEditor(IDataValueEditorFactory dataValueEditorFactory) : base(dataValueEditorFactory) => SupportsReadOnly = true; diff --git a/src/Umbraco.Core/PropertyEditors/FileExtensionConfigItem.cs b/src/Umbraco.Core/PropertyEditors/FileExtensionConfigItem.cs index a96f3cfe9db9..01fcf2447819 100644 --- a/src/Umbraco.Core/PropertyEditors/FileExtensionConfigItem.cs +++ b/src/Umbraco.Core/PropertyEditors/FileExtensionConfigItem.cs @@ -1,8 +1,13 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a file extension configuration item used by file upload property editors. +/// public class FileExtensionConfigItem : IFileExtensionConfigItem { + /// public int Id { get; set; } + /// public string? Value { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/FileUploadConfiguration.cs b/src/Umbraco.Core/PropertyEditors/FileUploadConfiguration.cs index e7c9bf4e28bf..dfe230f603ad 100644 --- a/src/Umbraco.Core/PropertyEditors/FileUploadConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/FileUploadConfiguration.cs @@ -5,6 +5,9 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class FileUploadConfiguration { + /// + /// Gets or sets the allowed file extensions for uploads. + /// [ConfigurationField("fileExtensions")] public IEnumerable FileExtensions { get; set; } = Enumerable.Empty(); } diff --git a/src/Umbraco.Core/PropertyEditors/FileUploadConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/FileUploadConfigurationEditor.cs index 31fa723b3f81..a31059cc705f 100644 --- a/src/Umbraco.Core/PropertyEditors/FileUploadConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/FileUploadConfigurationEditor.cs @@ -7,6 +7,10 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class FileUploadConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// + /// The IO helper. public FileUploadConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) { diff --git a/src/Umbraco.Core/PropertyEditors/IBlockConfiguration.cs b/src/Umbraco.Core/PropertyEditors/IBlockConfiguration.cs index 350f4a084301..8ff97ffdad87 100644 --- a/src/Umbraco.Core/PropertyEditors/IBlockConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/IBlockConfiguration.cs @@ -3,9 +3,21 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents the configuration for a block in block-based editors. +/// public interface IBlockConfiguration { + /// + /// Gets or sets the unique key of the content element type for this block. + /// public Guid ContentElementTypeKey { get; set; } + /// + /// Gets or sets the unique key of the settings element type for this block. + /// + /// + /// Can be null if the block does not have settings. + /// public Guid? SettingsElementTypeKey { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/IBlockValuePropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/IBlockValuePropertyIndexValueFactory.cs index 8556b993f057..f008e477f0b6 100644 --- a/src/Umbraco.Core/PropertyEditors/IBlockValuePropertyIndexValueFactory.cs +++ b/src/Umbraco.Core/PropertyEditors/IBlockValuePropertyIndexValueFactory.cs @@ -1,5 +1,12 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a property index value factory specifically for block-based property values. +/// +/// +/// This marker interface allows for specialized indexing of block content, +/// such as Block List, Block Grid, and Rich Text block values. +/// public interface IBlockValuePropertyIndexValueFactory : IPropertyIndexValueFactory { } diff --git a/src/Umbraco.Core/PropertyEditors/IDataEditor.cs b/src/Umbraco.Core/PropertyEditors/IDataEditor.cs index 2f6586b40ea2..ddd7745d3fd8 100644 --- a/src/Umbraco.Core/PropertyEditors/IDataEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/IDataEditor.cs @@ -14,8 +14,14 @@ public interface IDataEditor : IDiscoverable /// string Alias { get; } + /// + /// Gets a value indicating whether the editor supports read-only mode. + /// bool SupportsReadOnly => false; + /// + /// Gets a value indicating whether the editor supports configurable elements. + /// bool SupportsConfigurableElements => false; /// diff --git a/src/Umbraco.Core/PropertyEditors/IDataValueEditorFactory.cs b/src/Umbraco.Core/PropertyEditors/IDataValueEditorFactory.cs index a2f84cd71ccd..f729e0b3a63e 100644 --- a/src/Umbraco.Core/PropertyEditors/IDataValueEditorFactory.cs +++ b/src/Umbraco.Core/PropertyEditors/IDataValueEditorFactory.cs @@ -2,8 +2,17 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// A factory for creating instances. +/// public interface IDataValueEditorFactory { + /// + /// Creates a new instance of the specified type. + /// + /// The type of data value editor to create. + /// The constructor arguments for the data value editor. + /// A new instance of the specified data value editor type. TDataValueEditor Create(params object[] args) where TDataValueEditor : class, IDataValueEditor; } diff --git a/src/Umbraco.Core/PropertyEditors/IDataValueReferenceFactory.cs b/src/Umbraco.Core/PropertyEditors/IDataValueReferenceFactory.cs index 8c768c295f24..81ba72c60d73 100644 --- a/src/Umbraco.Core/PropertyEditors/IDataValueReferenceFactory.cs +++ b/src/Umbraco.Core/PropertyEditors/IDataValueReferenceFactory.cs @@ -1,16 +1,20 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a factory for creating instances for specific data editors. +/// public interface IDataValueReferenceFactory { /// /// Gets a value indicating whether the DataValueReference lookup supports a datatype (data editor). /// - /// + /// The data editor to check. /// A value indicating whether the converter supports a datatype. bool IsForEditor(IDataEditor? dataEditor); /// + /// Gets the instance for extracting entity references from property values. /// - /// + /// An instance. IDataValueReference GetDataValueReference(); } diff --git a/src/Umbraco.Core/PropertyEditors/IFileExtensionConfigItem.cs b/src/Umbraco.Core/PropertyEditors/IFileExtensionConfigItem.cs index fa2e8fa5f63a..e0f25f587209 100644 --- a/src/Umbraco.Core/PropertyEditors/IFileExtensionConfigItem.cs +++ b/src/Umbraco.Core/PropertyEditors/IFileExtensionConfigItem.cs @@ -1,8 +1,17 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a file extension configuration item used by file upload property editors. +/// public interface IFileExtensionConfigItem { + /// + /// Gets or sets the unique identifier for this file extension configuration item. + /// int Id { get; set; } + /// + /// Gets or sets the file extension value (e.g., "jpg", "pdf"). + /// string? Value { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/IIgnoreUserStartNodesConfig.cs b/src/Umbraco.Core/PropertyEditors/IIgnoreUserStartNodesConfig.cs index 7e6b0c441040..3a15425258d3 100644 --- a/src/Umbraco.Core/PropertyEditors/IIgnoreUserStartNodesConfig.cs +++ b/src/Umbraco.Core/PropertyEditors/IIgnoreUserStartNodesConfig.cs @@ -5,5 +5,8 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public interface IIgnoreUserStartNodesConfig { + /// + /// Gets or sets a value indicating whether to ignore user start nodes when selecting content. + /// bool IgnoreUserStartNodes { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/IPropertyCacheCompressionOptions.cs b/src/Umbraco.Core/PropertyEditors/IPropertyCacheCompressionOptions.cs index 1cff2e7552b1..c28eca7da971 100644 --- a/src/Umbraco.Core/PropertyEditors/IPropertyCacheCompressionOptions.cs +++ b/src/Umbraco.Core/PropertyEditors/IPropertyCacheCompressionOptions.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Defines options for determining whether property values should be compressed in the cache. +/// public interface IPropertyCacheCompressionOptions { /// diff --git a/src/Umbraco.Core/PropertyEditors/IRichTextEditorIntermediateValue.cs b/src/Umbraco.Core/PropertyEditors/IRichTextEditorIntermediateValue.cs index 24bdb25fb656..94f843798762 100644 --- a/src/Umbraco.Core/PropertyEditors/IRichTextEditorIntermediateValue.cs +++ b/src/Umbraco.Core/PropertyEditors/IRichTextEditorIntermediateValue.cs @@ -3,11 +3,20 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// -/// Models Intermediate Value for Rich Text Editors Property Value Converter. +/// Models the intermediate value for Rich Text Editor property value converters. /// public interface IRichTextEditorIntermediateValue { + /// + /// Gets the HTML markup content of the rich text value. + /// public string Markup { get; } + /// + /// Gets the block model associated with the rich text value. + /// + /// + /// Can be null if no blocks are embedded in the rich text content. + /// public RichTextBlockModel? RichTextBlockModel { get; } } diff --git a/src/Umbraco.Core/PropertyEditors/IRichTextPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/IRichTextPropertyIndexValueFactory.cs index f48f7ad25463..6699fc1b1729 100644 --- a/src/Umbraco.Core/PropertyEditors/IRichTextPropertyIndexValueFactory.cs +++ b/src/Umbraco.Core/PropertyEditors/IRichTextPropertyIndexValueFactory.cs @@ -1,5 +1,12 @@ -namespace Umbraco.Cms.Core.PropertyEditors; +namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a property index value factory specifically for rich text properties. +/// +/// +/// This marker interface allows for specialized indexing of rich text content, +/// which may include markup, embedded media, and block content. +/// public interface IRichTextPropertyIndexValueFactory : IPropertyIndexValueFactory { } diff --git a/src/Umbraco.Core/PropertyEditors/ITagPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/ITagPropertyIndexValueFactory.cs index 33eabb314cae..9b22cb5221c8 100644 --- a/src/Umbraco.Core/PropertyEditors/ITagPropertyIndexValueFactory.cs +++ b/src/Umbraco.Core/PropertyEditors/ITagPropertyIndexValueFactory.cs @@ -1,5 +1,12 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a property index value factory specifically for tag properties. +/// +/// +/// This marker interface allows for specialized indexing of tag values, +/// enabling proper handling of multiple tag values per property. +/// public interface ITagPropertyIndexValueFactory : IPropertyIndexValueFactory { } diff --git a/src/Umbraco.Core/PropertyEditors/IndexValue.cs b/src/Umbraco.Core/PropertyEditors/IndexValue.cs index ebcc321bf9c6..6115ecd958d1 100644 --- a/src/Umbraco.Core/PropertyEditors/IndexValue.cs +++ b/src/Umbraco.Core/PropertyEditors/IndexValue.cs @@ -1,10 +1,28 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents an index value for a property to be indexed in the search system. +/// public sealed class IndexValue { + /// + /// Gets or sets the culture for this index value. + /// + /// + /// Can be null for culture-invariant properties. + /// public required string? Culture { get; set; } + /// + /// Gets or sets the field name to use in the index. + /// public required string FieldName { get; set; } + /// + /// Gets or sets the values to be indexed for this field. + /// + /// + /// A field can have multiple values, for example when indexing tags or multi-select values. + /// public required IEnumerable Values { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/IntegerConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/IntegerConfigurationEditor.cs index eda8ae17fe61..fcc4c4eff8f6 100644 --- a/src/Umbraco.Core/PropertyEditors/IntegerConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/IntegerConfigurationEditor.cs @@ -7,6 +7,9 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class IntegerConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// public IntegerConfigurationEditor() { Fields.Add(new ConfigurationField(new IntegerValidator()) diff --git a/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs b/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs index bfbd38a294b6..9ffead09f776 100644 --- a/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs +++ b/src/Umbraco.Core/PropertyEditors/JsonPropertyIndexValueFactoryBase.cs @@ -15,6 +15,9 @@ public abstract class JsonPropertyIndexValueFactoryBase : IProperty private readonly IJsonSerializer _jsonSerializer; private IndexingSettings _indexingSettings; + /// + /// Gets or sets a value indicating whether to force explicit indexing of each nested property. + /// protected bool ForceExplicitlyIndexEachNestedProperty { get; set; } /// @@ -27,6 +30,7 @@ protected JsonPropertyIndexValueFactoryBase(IJsonSerializer jsonSerializer, IOpt indexingSettings.OnChange(newValue => _indexingSettings = newValue); } + /// public virtual IEnumerable GetIndexValues( IProperty property, string? culture, diff --git a/src/Umbraco.Core/PropertyEditors/LabelConfiguration.cs b/src/Umbraco.Core/PropertyEditors/LabelConfiguration.cs index aac67111f352..6533252a7bd3 100644 --- a/src/Umbraco.Core/PropertyEditors/LabelConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/LabelConfiguration.cs @@ -5,6 +5,9 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class LabelConfiguration : IConfigureValueType { + /// + /// Gets or sets the value type for the label property editor. + /// [ConfigurationField(Constants.PropertyEditors.ConfigurationKeys.DataValueType)] public string ValueType { get; set; } = ValueTypes.String; } diff --git a/src/Umbraco.Core/PropertyEditors/LabelConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/LabelConfigurationEditor.cs index 3eda5e89b83d..69c3685db6a4 100644 --- a/src/Umbraco.Core/PropertyEditors/LabelConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/LabelConfigurationEditor.cs @@ -1,4 +1,4 @@ -// Copyright (c) Umbraco. +// Copyright (c) Umbraco. // See LICENSE for more details. using Umbraco.Cms.Core.IO; @@ -10,11 +10,16 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class LabelConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// + /// The IO helper. public LabelConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) { } + /// public override IDictionary FromConfigurationEditor(IDictionary configuration) { // default value diff --git a/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs index a7456a51a6f7..dbc74a718da4 100644 --- a/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/LabelPropertyEditor.cs @@ -36,9 +36,18 @@ protected override IDataValueEditor CreateValueEditor() => protected override IConfigurationEditor CreateConfigurationEditor() => new LabelConfigurationEditor(_ioHelper); - // provides the property value editor + /// + /// Provides the property value editor for label properties. + /// internal sealed class LabelPropertyValueEditor : DataValueEditor { + /// + /// Initializes a new instance of the class. + /// + /// The short string helper. + /// The JSON serializer. + /// The IO helper. + /// The data editor attribute. public LabelPropertyValueEditor( IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, diff --git a/src/Umbraco.Core/PropertyEditors/ListViewConfiguration.cs b/src/Umbraco.Core/PropertyEditors/ListViewConfiguration.cs index feecea41563c..3c70f9560b61 100644 --- a/src/Umbraco.Core/PropertyEditors/ListViewConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/ListViewConfiguration.cs @@ -5,6 +5,9 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class ListViewConfiguration { + /// + /// Initializes a new instance of the class with default properties. + /// public ListViewConfiguration() => // initialize defaults IncludeProperties = new[] @@ -14,13 +17,25 @@ public ListViewConfiguration() => new Property { Alias = "owner", IsSystem = true }, }; + /// + /// Gets or sets the properties to include in the list view. + /// [ConfigurationField("includeProperties")] public Property[] IncludeProperties { get; set; } + /// + /// Represents a property column configuration in the list view. + /// public class Property { + /// + /// Gets or sets the alias of the property. + /// public string? Alias { get; set; } + /// + /// Gets or sets a value indicating whether this is a system property. + /// public bool IsSystem { get; set; } } } diff --git a/src/Umbraco.Core/PropertyEditors/ListViewConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/ListViewConfigurationEditor.cs index b739d3adf3f5..d487f69f37ce 100644 --- a/src/Umbraco.Core/PropertyEditors/ListViewConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ListViewConfigurationEditor.cs @@ -1,4 +1,4 @@ -// Copyright (c) Umbraco. +// Copyright (c) Umbraco. // See LICENSE for more details. using Umbraco.Cms.Core.IO; @@ -10,6 +10,10 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class ListViewConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// + /// The IO helper. public ListViewConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) { diff --git a/src/Umbraco.Core/PropertyEditors/MarkDownPropertyValueEditor.cs b/src/Umbraco.Core/PropertyEditors/MarkDownPropertyValueEditor.cs index ae78a456cd39..1bbc8d95dc01 100644 --- a/src/Umbraco.Core/PropertyEditors/MarkDownPropertyValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MarkDownPropertyValueEditor.cs @@ -7,10 +7,21 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a value editor for Markdown content that sanitizes the input. +/// internal sealed class MarkDownPropertyValueEditor : DataValueEditor { private readonly IMarkdownSanitizer _markdownSanitizer; + /// + /// Initializes a new instance of the class. + /// + /// The short string helper. + /// The JSON serializer. + /// The IO helper. + /// The data editor attribute. + /// The Markdown sanitizer. public MarkDownPropertyValueEditor( IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, @@ -19,6 +30,7 @@ public MarkDownPropertyValueEditor( IMarkdownSanitizer markdownSanitizer) : base(shortStringHelper, jsonSerializer, ioHelper, attribute) => _markdownSanitizer = markdownSanitizer; + /// public override object? FromEditor(ContentPropertyData editorValue, object? currentValue) { if (string.IsNullOrWhiteSpace(editorValue.Value?.ToString())) diff --git a/src/Umbraco.Core/PropertyEditors/MediaPicker3Configuration.cs b/src/Umbraco.Core/PropertyEditors/MediaPicker3Configuration.cs index 7bffc484bdee..a18c1dd4434d 100644 --- a/src/Umbraco.Core/PropertyEditors/MediaPicker3Configuration.cs +++ b/src/Umbraco.Core/PropertyEditors/MediaPicker3Configuration.cs @@ -5,40 +5,80 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class MediaPicker3Configuration : IIgnoreUserStartNodesConfig { + /// + /// Gets or sets the media type filter. + /// [ConfigurationField("filter")] public string? Filter { get; set; } + /// + /// Gets or sets a value indicating whether multiple media items can be selected. + /// [ConfigurationField("multiple")] public bool Multiple { get; set; } + /// + /// Gets or sets the validation limits for the number of selected items. + /// [ConfigurationField("validationLimit")] public NumberRange ValidationLimit { get; set; } = new(); + /// + /// Gets or sets the start node ID for the media picker. + /// [ConfigurationField("startNodeId")] public Guid? StartNodeId { get; set; } + /// + /// Gets or sets a value indicating whether local focal point editing is enabled. + /// [ConfigurationField("enableLocalFocalPoint")] public bool EnableLocalFocalPoint { get; set; } + /// + /// Gets or sets the configured image crops. + /// [ConfigurationField("crops")] public CropConfiguration[]? Crops { get; set; } + /// [ConfigurationField(Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes)] public bool IgnoreUserStartNodes { get; set; } + /// + /// Represents a numeric range with optional minimum and maximum values. + /// public class NumberRange { + /// + /// Gets or sets the minimum value of the range. + /// public int? Min { get; set; } + /// + /// Gets or sets the maximum value of the range. + /// public int? Max { get; set; } } + /// + /// Represents an image crop configuration. + /// public class CropConfiguration { + /// + /// Gets or sets the alias of the crop. + /// public string? Alias { get; set; } + /// + /// Gets or sets the width of the crop in pixels. + /// public int Width { get; set; } + /// + /// Gets or sets the height of the crop in pixels. + /// public int Height { get; set; } } } diff --git a/src/Umbraco.Core/PropertyEditors/MediaUrlGeneratorCollection.cs b/src/Umbraco.Core/PropertyEditors/MediaUrlGeneratorCollection.cs index 360ba1b023cb..9dac7197b947 100644 --- a/src/Umbraco.Core/PropertyEditors/MediaUrlGeneratorCollection.cs +++ b/src/Umbraco.Core/PropertyEditors/MediaUrlGeneratorCollection.cs @@ -3,13 +3,27 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a collection of instances. +/// public class MediaUrlGeneratorCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection items. public MediaUrlGeneratorCollection(Func> items) : base(items) { } + /// + /// Tries to get the media path from the specified value using the registered generators. + /// + /// The property editor alias. + /// The property value. + /// When this method returns, contains the media path if found; otherwise, null. + /// true if a media path was found; otherwise, false. public bool TryGetMediaPath(string? propertyEditorAlias, object? value, out string? mediaPath) { // We can't get a media path from a null value diff --git a/src/Umbraco.Core/PropertyEditors/MediaUrlGeneratorCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/MediaUrlGeneratorCollectionBuilder.cs index 0c9bf6070f4c..5826ace23c80 100644 --- a/src/Umbraco.Core/PropertyEditors/MediaUrlGeneratorCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/MediaUrlGeneratorCollectionBuilder.cs @@ -3,7 +3,11 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a builder for the . +/// public class MediaUrlGeneratorCollectionBuilder : SetCollectionBuilderBase { + /// protected override MediaUrlGeneratorCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/PropertyEditors/MemberGroupPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/MemberGroupPickerPropertyEditor.cs index 4f25dc74fe7f..ff26712a4597 100644 --- a/src/Umbraco.Core/PropertyEditors/MemberGroupPickerPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MemberGroupPickerPropertyEditor.cs @@ -8,19 +8,30 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a property editor for selecting member groups. +/// [DataEditor( Constants.PropertyEditors.Aliases.MemberGroupPicker, ValueType = ValueTypes.Text, ValueEditorIsReusable = true)] public class MemberGroupPickerPropertyEditor : DataEditor { + /// + /// Initializes a new instance of the class. + /// + /// The data value editor factory. public MemberGroupPickerPropertyEditor(IDataValueEditorFactory dataValueEditorFactory) : base(dataValueEditorFactory) => SupportsReadOnly = true; + /// protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); + /// + /// Provides the value editor for the member group picker property editor. + /// private sealed class MemberGroupPickerPropertyValueEditor : DataValueEditor { private readonly IMemberGroupService _memberGroupService; diff --git a/src/Umbraco.Core/PropertyEditors/MemberPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/MemberPickerPropertyEditor.cs index fd9fb503e363..7dd3ee2ada01 100644 --- a/src/Umbraco.Core/PropertyEditors/MemberPickerPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MemberPickerPropertyEditor.cs @@ -8,19 +8,30 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a property editor for selecting members. +/// [DataEditor( Constants.PropertyEditors.Aliases.MemberPicker, ValueType = ValueTypes.String, ValueEditorIsReusable = true)] public class MemberPickerPropertyEditor : DataEditor { + /// + /// Initializes a new instance of the class. + /// + /// The data value editor factory. public MemberPickerPropertyEditor(IDataValueEditorFactory dataValueEditorFactory) : base(dataValueEditorFactory) => SupportsReadOnly = true; + /// protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); + /// + /// Provides the value editor for the member picker property editor. + /// private sealed class MemberPickerPropertyValueEditor : DataValueEditor, IDataValueReference { private readonly IMemberService _memberService; diff --git a/src/Umbraco.Core/PropertyEditors/MissingPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/MissingPropertyEditor.cs index 374efd67a780..bf55d941298a 100644 --- a/src/Umbraco.Core/PropertyEditors/MissingPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MissingPropertyEditor.cs @@ -30,6 +30,9 @@ public MissingPropertyEditor( Alias = missingEditorAlias; } + /// + /// Initializes a new instance of the class. + /// [Obsolete("Use the non-obsolete constructor instead. Scheduled for removal in Umbraco 18.")] public MissingPropertyEditor() : this( @@ -69,9 +72,18 @@ public IDataValueEditor GetValueEditor() => _valueEditor /// public IConfigurationEditor GetConfigurationEditor() => new ConfigurationEditor(); - // provides the property value editor + /// + /// Provides the property value editor for missing property editors. + /// internal sealed class MissingPropertyValueEditor : DataValueEditor { + /// + /// Initializes a new instance of the class. + /// + /// The short string helper. + /// The JSON serializer. + /// The IO helper. + /// The data editor attribute. public MissingPropertyValueEditor( IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, diff --git a/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfiguration.cs b/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfiguration.cs index 4729474029ce..e4bce3abc7d4 100644 --- a/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfiguration.cs @@ -7,19 +7,32 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class MultiNodePickerConfiguration : IIgnoreUserStartNodesConfig { + /// + /// Gets or sets the tree source configuration for the picker. + /// [JsonPropertyName("startNode")] [ConfigurationField("startNode")] public MultiNodePickerConfigurationTreeSource? TreeSource { get; set; } + /// + /// Gets or sets the minimum number of items that must be selected. + /// [ConfigurationField("minNumber")] public int MinNumber { get; set; } + /// + /// Gets or sets the maximum number of items that can be selected. + /// [ConfigurationField("maxNumber")] public int MaxNumber { get; set; } + /// + /// Gets or sets the content type filter for allowed selections. + /// [ConfigurationField("filter")] public string? Filter { get; set; } + /// [ConfigurationField(Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes)] public bool IgnoreUserStartNodes { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfigurationEditor.cs index b2c5b0bf8cf3..ba214beb0c30 100644 --- a/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfigurationEditor.cs @@ -10,6 +10,10 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class MultiNodePickerConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// + /// The IO helper. public MultiNodePickerConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) { diff --git a/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs b/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs index aac820c11757..1111e41a5cf1 100644 --- a/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs +++ b/src/Umbraco.Core/PropertyEditors/MultiNodePickerConfigurationTreeSource.cs @@ -9,41 +9,74 @@ namespace Umbraco.Cms.Core.PropertyEditors; [DataContract] public class MultiNodePickerConfigurationTreeSource { + /// + /// Gets or sets the object type (e.g., content, media, member). + /// [JsonPropertyName("type")] [DataMember(Name = "type")] public string? ObjectType { get; set; } + /// + /// Gets or sets the XPath query for the start node. + /// [JsonPropertyName("query")] [DataMember(Name = "query")] public string? StartNodeQuery { get; set; } + /// + /// Gets or sets the dynamic root configuration. + /// [DataMember(Name = "dynamicRoot")] public DynamicRoot? DynamicRoot { get; set; } + /// + /// Gets or sets the start node ID. + /// [JsonPropertyName("id")] [DataMember(Name = "id")] public Guid? StartNodeId { get; set; } } +/// +/// Represents a dynamic root configuration for the multi-node picker. +/// [DataContract] public class DynamicRoot { + /// + /// Gets or sets the origin alias for the dynamic root. + /// [DataMember(Name = "originAlias")] public string OriginAlias { get; set; } = string.Empty; + /// + /// Gets or sets the origin key for the dynamic root. + /// [DataMember(Name = "originKey")] public Guid? OriginKey { get; set; } + /// + /// Gets or sets the query steps for traversing the content tree. + /// [DataMember(Name = "querySteps")] public QueryStep[] QuerySteps { get; set; } = Array.Empty(); } +/// +/// Represents a query step for dynamic root traversal in the multi-node picker. +/// [DataContract] public class QueryStep { + /// + /// Gets or sets the alias of the query step. + /// [DataMember(Name = "alias")] public string Alias { get; set; } = string.Empty; + /// + /// Gets or sets the document type keys to filter by. + /// [DataMember(Name = "anyOfDocTypeKeys")] public IEnumerable AnyOfDocTypeKeys { get; set; } = Array.Empty(); } diff --git a/src/Umbraco.Core/PropertyEditors/MultiUrlPickerConfiguration.cs b/src/Umbraco.Core/PropertyEditors/MultiUrlPickerConfiguration.cs index c6e9ec63409b..4ddc22e0560e 100644 --- a/src/Umbraco.Core/PropertyEditors/MultiUrlPickerConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/MultiUrlPickerConfiguration.cs @@ -1,13 +1,23 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents the configuration for the multi URL picker property editor. +/// public class MultiUrlPickerConfiguration : IIgnoreUserStartNodesConfig { + /// + /// Gets or sets the minimum number of URLs that must be selected. + /// [ConfigurationField("minNumber")] public int MinNumber { get; set; } + /// + /// Gets or sets the maximum number of URLs that can be selected. + /// [ConfigurationField("maxNumber")] public int MaxNumber { get; set; } + /// [ConfigurationField(Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes)] public bool IgnoreUserStartNodes { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/MultiUrlPickerConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/MultiUrlPickerConfigurationEditor.cs index 7d2f71bef117..a6765c4955ba 100644 --- a/src/Umbraco.Core/PropertyEditors/MultiUrlPickerConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/MultiUrlPickerConfigurationEditor.cs @@ -5,8 +5,15 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents the configuration editor for the multi URL picker property editor. +/// public class MultiUrlPickerConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// + /// The IO helper. public MultiUrlPickerConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) { diff --git a/src/Umbraco.Core/PropertyEditors/MultipleTextStringConfiguration.cs b/src/Umbraco.Core/PropertyEditors/MultipleTextStringConfiguration.cs index 30ddde5ea5cf..b1a08c449635 100644 --- a/src/Umbraco.Core/PropertyEditors/MultipleTextStringConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/MultipleTextStringConfiguration.cs @@ -5,8 +5,13 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class MultipleTextStringConfiguration { - // fields are configured in the editor + /// + /// Gets or sets the minimum number of text strings required. + /// public int Min { get; set; } + /// + /// Gets or sets the maximum number of text strings allowed. + /// public int Max { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/NoopPropertyCacheCompressionOptions.cs b/src/Umbraco.Core/PropertyEditors/NoopPropertyCacheCompressionOptions.cs index f1d295bc3db6..6c02c405e2e0 100644 --- a/src/Umbraco.Core/PropertyEditors/NoopPropertyCacheCompressionOptions.cs +++ b/src/Umbraco.Core/PropertyEditors/NoopPropertyCacheCompressionOptions.cs @@ -8,5 +8,6 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public sealed class NoopPropertyCacheCompressionOptions : IPropertyCacheCompressionOptions { + /// public bool IsCompressed(IReadOnlyContentBase content, IPropertyType propertyType, IDataEditor dataEditor, bool published) => false; } diff --git a/src/Umbraco.Core/PropertyEditors/PlainTimePropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/PlainTimePropertyEditor.cs index d807ac96f88b..4af7c1d6432d 100644 --- a/src/Umbraco.Core/PropertyEditors/PlainTimePropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/PlainTimePropertyEditor.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Cms.Core.PropertyEditors; +namespace Umbraco.Cms.Core.PropertyEditors; /// /// Represents a property editor for configuration-less time properties. @@ -9,6 +9,10 @@ ValueType = ValueTypes.Time)] public class PlainTimePropertyEditor : DataEditor { + /// + /// Initializes a new instance of the class. + /// + /// The data value editor factory. public PlainTimePropertyEditor(IDataValueEditorFactory dataValueEditorFactory) : base(dataValueEditorFactory) => SupportsReadOnly = true; diff --git a/src/Umbraco.Core/PropertyEditors/PropertyCacheCompression.cs b/src/Umbraco.Core/PropertyEditors/PropertyCacheCompression.cs index 75342371a4dd..9c84ba652511 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyCacheCompression.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyCacheCompression.cs @@ -16,6 +16,13 @@ public class PropertyCacheCompression : IPropertyCacheCompression private readonly PropertyEditorCollection _propertyEditors; + /// + /// Initializes a new instance of the class. + /// + /// The compression options. + /// The content types dictionary. + /// The property editors collection. + /// The cache for compressed storage lookup. public PropertyCacheCompression( IPropertyCacheCompressionOptions compressionOptions, IReadOnlyDictionary contentTypes, @@ -28,6 +35,7 @@ public PropertyCacheCompression( _isCompressedCache = compressedStoragePropertyEditorCache; } + /// public bool IsCompressed(IReadOnlyContentBase content, string alias, bool published) { var compressedStorage = _isCompressedCache.GetOrAdd((content.ContentTypeId, alias, published), x => diff --git a/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs b/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs index b224155ea1fe..03694774c977 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyEditorCollection.cs @@ -4,17 +4,35 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a collection of property editors (). +/// public class PropertyEditorCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// The data editor collection. public PropertyEditorCollection(DataEditorCollection dataEditors) : base(() => dataEditors) { } - // note: virtual so it can be mocked + /// + /// Gets the property editor with the specified alias. + /// + /// The editor alias. + /// The property editor if found; otherwise, null. + /// Virtual so it can be mocked. public virtual IDataEditor? this[string? alias] => this.SingleOrDefault(x => x.Alias == alias); + /// + /// Tries to get the property editor with the specified alias. + /// + /// The editor alias. + /// When this method returns, contains the editor if found; otherwise, null. + /// true if the editor was found; otherwise, false. public virtual bool TryGet(string? alias, [MaybeNullWhen(false)] out IDataEditor editor) { editor = this.FirstOrDefault(x => x.Alias == alias); diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollection.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollection.cs index 2ede3ad78b22..597050c92dd2 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollection.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollection.cs @@ -3,11 +3,18 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a collection of instances. +/// public class PropertyValueConverterCollection : BuilderCollectionBase { private readonly Lock _locker = new(); private Dictionary? _defaultConverters; + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection items. public PropertyValueConverterCollection(Func> items) : base(items) { @@ -40,9 +47,20 @@ private Dictionary DefaultConverters } } + /// + /// Determines whether the specified converter is a default converter. + /// + /// The converter to check. + /// true if the converter is a default converter; otherwise, false. internal bool IsDefault(IPropertyValueConverter converter) => DefaultConverters.ContainsKey(converter); + /// + /// Determines whether one converter shadows another. + /// + /// The converter that may be shadowing. + /// The converter that may be shadowed. + /// true if the shadowing converter shadows the shadowed converter; otherwise, false. internal bool Shadows(IPropertyValueConverter shadowing, IPropertyValueConverter shadowed) { Type shadowedType = shadowed.GetType(); diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs index 6d1e329c7ef9..660c474c0e3e 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterCollectionBuilder.cs @@ -1,8 +1,12 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a builder for the . +/// public class PropertyValueConverterCollectionBuilder : OrderedCollectionBuilderBase { + /// protected override PropertyValueConverterCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/PropertyEditors/RichTextConfiguration.cs b/src/Umbraco.Core/PropertyEditors/RichTextConfiguration.cs index 5ebcb13b5de1..13dcad145d15 100644 --- a/src/Umbraco.Core/PropertyEditors/RichTextConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/RichTextConfiguration.cs @@ -5,19 +5,35 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class RichTextConfiguration : IIgnoreUserStartNodesConfig { + /// + /// Gets or sets the block configurations for the rich text editor. + /// [ConfigurationField("blocks")] public RichTextBlockConfiguration[]? Blocks { get; set; } = Array.Empty(); + /// + /// Gets or sets the media parent ID for uploaded media. + /// [ConfigurationField("mediaParentId")] public Guid? MediaParentId { get; set; } + /// [ConfigurationField(Constants.DataTypes.ReservedPreValueKeys.IgnoreUserStartNodes)] public bool IgnoreUserStartNodes { get; set; } + /// + /// Represents a block configuration for the rich text editor. + /// public class RichTextBlockConfiguration : IBlockConfiguration { + /// + /// Gets or sets the unique key of the content element type for this block. + /// public Guid ContentElementTypeKey { get; set; } + /// + /// Gets or sets the unique key of the settings element type for this block, if any. + /// public Guid? SettingsElementTypeKey { get; set; } } } diff --git a/src/Umbraco.Core/PropertyEditors/RichTextConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/RichTextConfigurationEditor.cs index a6dbf923b8e0..5a214bea25c4 100644 --- a/src/Umbraco.Core/PropertyEditors/RichTextConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/RichTextConfigurationEditor.cs @@ -1,4 +1,4 @@ -// Copyright (c) Umbraco. +// Copyright (c) Umbraco. // See LICENSE for more details. using Umbraco.Cms.Core.IO; @@ -10,6 +10,10 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class RichTextConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// + /// The IO helper. public RichTextConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) { diff --git a/src/Umbraco.Core/PropertyEditors/SingleBlockConfiguration.cs b/src/Umbraco.Core/PropertyEditors/SingleBlockConfiguration.cs index 69d9d2812f4d..e31cd25e7fc1 100644 --- a/src/Umbraco.Core/PropertyEditors/SingleBlockConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/SingleBlockConfiguration.cs @@ -4,10 +4,16 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// -/// The configuration object for the Single Block editor +/// The configuration object for the Single Block editor. /// public class SingleBlockConfiguration { + /// + /// Gets or sets the available block type configurations. + /// + /// + /// For the Single Block editor, this typically contains only one block configuration. + /// [ConfigurationField("blocks")] public BlockListConfiguration.BlockConfiguration[] Blocks { get; set; } = []; } diff --git a/src/Umbraco.Core/PropertyEditors/SliderConfiguration.cs b/src/Umbraco.Core/PropertyEditors/SliderConfiguration.cs index 12ca9f461c76..1834f78e0b0b 100644 --- a/src/Umbraco.Core/PropertyEditors/SliderConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/SliderConfiguration.cs @@ -5,15 +5,27 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class SliderConfiguration { + /// + /// Gets or sets a value indicating whether range selection is enabled (two handles). + /// [ConfigurationField("enableRange")] public bool EnableRange { get; set; } + /// + /// Gets or sets the minimum value of the slider. + /// [ConfigurationField("minVal")] public decimal MinimumValue { get; set; } + /// + /// Gets or sets the maximum value of the slider. + /// [ConfigurationField("maxVal")] public decimal MaximumValue { get; set; } + /// + /// Gets or sets the step increment value for the slider. + /// [ConfigurationField("step")] public decimal Step { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/SliderConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/SliderConfigurationEditor.cs index e239ea002cd1..4e86850fa6b4 100644 --- a/src/Umbraco.Core/PropertyEditors/SliderConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/SliderConfigurationEditor.cs @@ -10,6 +10,10 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class SliderConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// + /// The IO helper. public SliderConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) { diff --git a/src/Umbraco.Core/PropertyEditors/TagConfiguration.cs b/src/Umbraco.Core/PropertyEditors/TagConfiguration.cs index 32f8846d10f5..3bc4652d06d8 100644 --- a/src/Umbraco.Core/PropertyEditors/TagConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/TagConfiguration.cs @@ -7,12 +7,20 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class TagConfiguration { + /// + /// Gets or sets the tag group name. + /// [ConfigurationField("group")] public string Group { get; set; } = "default"; + /// + /// Gets or sets the storage type for tags (CSV or JSON). + /// [ConfigurationField("storageType")] public TagsStorageType StorageType { get; set; } = TagsStorageType.Json; - // not a field + /// + /// Gets or sets the delimiter character used for CSV storage. + /// public char Delimiter { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/TagConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/TagConfigurationEditor.cs index c50788165f98..5b3132ef66aa 100644 --- a/src/Umbraco.Core/PropertyEditors/TagConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/TagConfigurationEditor.cs @@ -11,6 +11,10 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class TagConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// + /// The IO helper. public TagConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) { diff --git a/src/Umbraco.Core/PropertyEditors/TagPropertyIndexValueFactory.cs b/src/Umbraco.Core/PropertyEditors/TagPropertyIndexValueFactory.cs index 9f3ebb674b9b..4428edba126d 100644 --- a/src/Umbraco.Core/PropertyEditors/TagPropertyIndexValueFactory.cs +++ b/src/Umbraco.Core/PropertyEditors/TagPropertyIndexValueFactory.cs @@ -5,10 +5,18 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Provides index value factory for tag properties. +/// public class TagPropertyIndexValueFactory : JsonPropertyIndexValueFactoryBase, ITagPropertyIndexValueFactory { private IndexingSettings _indexingSettings; + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. + /// The indexing settings. public TagPropertyIndexValueFactory( IJsonSerializer jsonSerializer, IOptionsMonitor indexingSettings) @@ -19,6 +27,7 @@ public TagPropertyIndexValueFactory( indexingSettings.OnChange(newValue => _indexingSettings = newValue); } + /// protected override IEnumerable Handle( string[] deserializedPropertyValue, IProperty property, @@ -37,6 +46,7 @@ protected override IEnumerable Handle( } ]; + /// public override IEnumerable GetIndexValues( IProperty property, string? culture, diff --git a/src/Umbraco.Core/PropertyEditors/TextAreaConfiguration.cs b/src/Umbraco.Core/PropertyEditors/TextAreaConfiguration.cs index 7ab29b27cd94..1cc98fbcf2d7 100644 --- a/src/Umbraco.Core/PropertyEditors/TextAreaConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/TextAreaConfiguration.cs @@ -5,6 +5,9 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class TextAreaConfiguration { + /// + /// Gets or sets the maximum number of characters allowed. + /// [ConfigurationField("maxChars")] public int? MaxChars { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/TextAreaConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/TextAreaConfigurationEditor.cs index 7e3c8a177005..6a3a1b1edab8 100644 --- a/src/Umbraco.Core/PropertyEditors/TextAreaConfigurationEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/TextAreaConfigurationEditor.cs @@ -1,4 +1,4 @@ -// Copyright (c) Umbraco. +// Copyright (c) Umbraco. // See LICENSE for more details. using Umbraco.Cms.Core.IO; @@ -10,6 +10,10 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class TextAreaConfigurationEditor : ConfigurationEditor { + /// + /// Initializes a new instance of the class. + /// + /// The IO helper. public TextAreaConfigurationEditor(IIOHelper ioHelper) : base(ioHelper) { diff --git a/src/Umbraco.Core/PropertyEditors/TextOnlyValueEditor.cs b/src/Umbraco.Core/PropertyEditors/TextOnlyValueEditor.cs index 74a8ab627963..de40e6e195d1 100644 --- a/src/Umbraco.Core/PropertyEditors/TextOnlyValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/TextOnlyValueEditor.cs @@ -17,6 +17,14 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class TextOnlyValueEditor : DataValueEditor { + /// + /// Initializes a new instance of the class. + /// + /// The data editor attribute. + /// The localized text service. + /// The short string helper. + /// The JSON serializer. + /// The IO helper. public TextOnlyValueEditor( DataEditorAttribute attribute, ILocalizedTextService localizedTextService, @@ -61,12 +69,16 @@ public override object ToEditor(IProperty property, string? culture = null, stri } /// - /// A common length validator for both textbox and text area. + /// A common length validator for both textbox and text area. /// internal sealed class LengthValidator : IValueValidator { private readonly ILocalizedTextService _localizedTextService; + /// + /// Initializes a new instance of the class. + /// + /// The localized text service. public LengthValidator(ILocalizedTextService localizedTextService) { _localizedTextService = localizedTextService; diff --git a/src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs b/src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs index 1a8a68cde06e..281496e65596 100644 --- a/src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs @@ -4,6 +4,9 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Provides property value conversion for text string properties (TextBox and TextArea). +/// [DefaultPropertyValueConverter] public class TextStringValueConverter : PropertyValueConverterBase, IDeliveryApiPropertyValueConverter { @@ -15,21 +18,30 @@ public class TextStringValueConverter : PropertyValueConverterBase, IDeliveryApi private readonly HtmlLocalLinkParser _linkParser; private readonly HtmlUrlParser _urlParser; + /// + /// Initializes a new instance of the class. + /// + /// The local link parser for resolving internal links. + /// The URL parser for resolving URLs. public TextStringValueConverter(HtmlLocalLinkParser linkParser, HtmlUrlParser urlParser) { _linkParser = linkParser; _urlParser = urlParser; } + /// public override bool IsConverter(IPublishedPropertyType propertyType) => PropertyTypeAliases.Contains(propertyType.EditorAlias); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(string); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Snapshot; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { if (source == null) @@ -46,17 +58,21 @@ public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType return sourceString; } + /// public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) => // source should come from ConvertSource and be a string (or null) already inter ?? string.Empty; + /// public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType) => GetPropertyValueType(propertyType); + /// public object? ConvertIntermediateToDeliveryApiObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview, bool expanding) => ConvertIntermediateToObject(owner, propertyType, referenceCacheLevel, inter, preview); } diff --git a/src/Umbraco.Core/PropertyEditors/TextboxConfiguration.cs b/src/Umbraco.Core/PropertyEditors/TextboxConfiguration.cs index 880c121b69d3..e5d4de602bf4 100644 --- a/src/Umbraco.Core/PropertyEditors/TextboxConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/TextboxConfiguration.cs @@ -5,6 +5,9 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class TextboxConfiguration { + /// + /// Gets or sets the maximum number of characters allowed. + /// [ConfigurationField("maxChars")] public int? MaxChars { get; set; } } diff --git a/src/Umbraco.Core/PropertyEditors/UnPublishedContentPropertyCacheCompressionOptions.cs b/src/Umbraco.Core/PropertyEditors/UnPublishedContentPropertyCacheCompressionOptions.cs index 4e5fc41d494d..545a6c13cd27 100644 --- a/src/Umbraco.Core/PropertyEditors/UnPublishedContentPropertyCacheCompressionOptions.cs +++ b/src/Umbraco.Core/PropertyEditors/UnPublishedContentPropertyCacheCompressionOptions.cs @@ -7,6 +7,7 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class UnPublishedContentPropertyCacheCompressionOptions : IPropertyCacheCompressionOptions { + /// public bool IsCompressed(IReadOnlyContentBase content, IPropertyType propertyType, IDataEditor dataEditor, bool published) { if (!published && propertyType.SupportsPublishing && propertyType.ValueStorageType == ValueStorageType.Ntext) diff --git a/src/Umbraco.Core/PropertyEditors/UserPickerPropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/UserPickerPropertyEditor.cs index c0026e917a61..9e3c27e766b4 100644 --- a/src/Umbraco.Core/PropertyEditors/UserPickerPropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/UserPickerPropertyEditor.cs @@ -8,19 +8,30 @@ namespace Umbraco.Cms.Core.PropertyEditors; +/// +/// Represents a property editor for selecting users. +/// [DataEditor( Constants.PropertyEditors.Aliases.UserPicker, ValueType = ValueTypes.Integer, ValueEditorIsReusable = true)] public class UserPickerPropertyEditor : DataEditor { + /// + /// Initializes a new instance of the class. + /// + /// The data value editor factory. public UserPickerPropertyEditor(IDataValueEditorFactory dataValueEditorFactory) : base(dataValueEditorFactory) => SupportsReadOnly = true; + /// protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create(Attribute!); + /// + /// Provides the value editor for the user picker property editor. + /// private sealed class UserPickerPropertyValueEditor : DataValueEditor { private readonly IUserService _userService; diff --git a/src/Umbraco.Core/PropertyEditors/Validation/IJsonPathValidationResult.cs b/src/Umbraco.Core/PropertyEditors/Validation/IJsonPathValidationResult.cs index 2b3c2b3525fe..7b0ee2aa41f9 100644 --- a/src/Umbraco.Core/PropertyEditors/Validation/IJsonPathValidationResult.cs +++ b/src/Umbraco.Core/PropertyEditors/Validation/IJsonPathValidationResult.cs @@ -1,6 +1,12 @@ -namespace Umbraco.Cms.Core.PropertyEditors.Validation; +namespace Umbraco.Cms.Core.PropertyEditors.Validation; +/// +/// Represents a validation result that includes a JSON path for locating the error. +/// public interface IJsonPathValidationResult { + /// + /// Gets the JSON path where the validation error occurred. + /// string JsonPath { get; } } diff --git a/src/Umbraco.Core/PropertyEditors/Validation/INestedValidationResults.cs b/src/Umbraco.Core/PropertyEditors/Validation/INestedValidationResults.cs index 953119a85a8a..7514d1534e7d 100644 --- a/src/Umbraco.Core/PropertyEditors/Validation/INestedValidationResults.cs +++ b/src/Umbraco.Core/PropertyEditors/Validation/INestedValidationResults.cs @@ -1,8 +1,14 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; namespace Umbraco.Cms.Core.PropertyEditors.Validation; +/// +/// Represents a validation result that contains nested validation results. +/// public interface INestedValidationResults { + /// + /// Gets the collection of nested validation results. + /// IList ValidationResults { get; } } diff --git a/src/Umbraco.Core/PropertyEditors/Validation/ITypedJsonValidator.cs b/src/Umbraco.Core/PropertyEditors/Validation/ITypedJsonValidator.cs index 2484935ed2aa..d9638555d788 100644 --- a/src/Umbraco.Core/PropertyEditors/Validation/ITypedJsonValidator.cs +++ b/src/Umbraco.Core/PropertyEditors/Validation/ITypedJsonValidator.cs @@ -11,6 +11,14 @@ namespace Umbraco.Cms.Core.PropertyEditors.Validation; /// The type of the configuration consumed by validator. public interface ITypedJsonValidator { + /// + /// Validates the specified value against the configuration. + /// + /// The deserialized value to validate. + /// The data type configuration. + /// The value type. + /// The property validation context. + /// A collection of validation results. public abstract IEnumerable Validate( TValue? value, TConfiguration? configuration, diff --git a/src/Umbraco.Core/PropertyEditors/Validation/JsonPathExpression.cs b/src/Umbraco.Core/PropertyEditors/Validation/JsonPathExpression.cs index 80582d50de42..9bc719a1fc53 100644 --- a/src/Umbraco.Core/PropertyEditors/Validation/JsonPathExpression.cs +++ b/src/Umbraco.Core/PropertyEditors/Validation/JsonPathExpression.cs @@ -1,9 +1,19 @@ -using Umbraco.Extensions; +using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors.Validation; +/// +/// Provides helper methods for creating JSON path expressions used in validation error reporting. +/// public static class JsonPathExpression { + /// + /// Creates a JSON path expression for a missing property value. + /// + /// The property alias. + /// The culture, or null for invariant. + /// The segment, or null for no segment. + /// A JSON path filter expression. public static string MissingPropertyValue(string propertyAlias, string? culture, string? segment) => $"?(@.alias == '{propertyAlias}' && @.culture == {(culture.IsNullOrWhiteSpace() ? "null" : $"'{culture}'")} && @.segment == {(segment.IsNullOrWhiteSpace() ? "null" : $"'{segment}'")})"; } diff --git a/src/Umbraco.Core/PropertyEditors/Validation/JsonPathValidationError.cs b/src/Umbraco.Core/PropertyEditors/Validation/JsonPathValidationError.cs index 0a973e888f45..8e0ea88d0635 100644 --- a/src/Umbraco.Core/PropertyEditors/Validation/JsonPathValidationError.cs +++ b/src/Umbraco.Core/PropertyEditors/Validation/JsonPathValidationError.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.PropertyEditors.Validation; +namespace Umbraco.Cms.Core.PropertyEditors.Validation; +/// +/// Represents a validation error with its JSON path location. +/// internal sealed class JsonPathValidationError { + /// + /// Gets the JSON path where the validation error occurred. + /// public required string JsonPath { get; init; } + /// + /// Gets the collection of error messages for this validation error. + /// public required IEnumerable ErrorMessages { get; init; } } diff --git a/src/Umbraco.Core/PropertyEditors/Validation/JsonPathValidator.cs b/src/Umbraco.Core/PropertyEditors/Validation/JsonPathValidator.cs index fd8f462205c0..55d51a89a750 100644 --- a/src/Umbraco.Core/PropertyEditors/Validation/JsonPathValidator.cs +++ b/src/Umbraco.Core/PropertyEditors/Validation/JsonPathValidator.cs @@ -1,10 +1,18 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors.Validation; +/// +/// Provides utility methods for extracting JSON path validation errors from validation results. +/// internal static class JsonPathValidator { + /// + /// Extracts JSON path validation errors from the specified validation result. + /// + /// The validation result to extract errors from. + /// A collection of JSON path validation errors. public static IEnumerable ExtractJsonPathValidationErrors(ValidationResult validationResult) { var root = new JsonPathValidationTreeItem { JsonPath = string.Empty }; diff --git a/src/Umbraco.Core/PropertyEditors/Validation/NestedJsonPathValidationResults.cs b/src/Umbraco.Core/PropertyEditors/Validation/NestedJsonPathValidationResults.cs index 52358f8e6417..c5f33fe952ad 100644 --- a/src/Umbraco.Core/PropertyEditors/Validation/NestedJsonPathValidationResults.cs +++ b/src/Umbraco.Core/PropertyEditors/Validation/NestedJsonPathValidationResults.cs @@ -1,14 +1,23 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; namespace Umbraco.Cms.Core.PropertyEditors.Validation; +/// +/// Represents a validation result that contains nested validation results with a JSON path. +/// public class NestedJsonPathValidationResults : ValidationResult, INestedValidationResults, IJsonPathValidationResult { + /// public string JsonPath { get; } + /// + /// Initializes a new instance of the class. + /// + /// The JSON path where the validation error occurred. public NestedJsonPathValidationResults(string jsonPath) : base(string.Empty) => JsonPath = jsonPath; + /// public IList ValidationResults { get; } = []; } diff --git a/src/Umbraco.Core/PropertyEditors/Validation/NestedValidationResults.cs b/src/Umbraco.Core/PropertyEditors/Validation/NestedValidationResults.cs index 859439ff9353..20fe7e779674 100644 --- a/src/Umbraco.Core/PropertyEditors/Validation/NestedValidationResults.cs +++ b/src/Umbraco.Core/PropertyEditors/Validation/NestedValidationResults.cs @@ -1,13 +1,20 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; namespace Umbraco.Cms.Core.PropertyEditors.Validation; +/// +/// Represents a validation result that contains nested validation results. +/// public class NestedValidationResults : ValidationResult, INestedValidationResults { + /// + /// Initializes a new instance of the class. + /// public NestedValidationResults() : base(string.Empty) { } + /// public IList ValidationResults { get; } = []; } diff --git a/src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs b/src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs index 103351582004..d41183ebbbf1 100644 --- a/src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs +++ b/src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs @@ -9,6 +9,9 @@ namespace Umbraco.Cms.Core.PropertyEditors.Validators; /// public class RequiredValidator : IValueRequiredValidator, IValueValidator { + /// + /// Initializes a new instance of the class. + /// public RequiredValidator() { } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/BigintValueTypeConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/BigintValueTypeConverter.cs index 0e232bdc77f6..a46fea5df53a 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/BigintValueTypeConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/BigintValueTypeConverter.cs @@ -3,22 +3,33 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for property editors with the bigint value type. +/// [DefaultValueTypePropertyValueConverter] public class BigintValueTypeConverter : ValueTypePropertyValueConverterBase { + /// protected override string[] SupportedValueTypes => new[] { ValueTypes.Bigint }; + /// + /// Initializes a new instance of the class. + /// + /// The property editor collection. public BigintValueTypeConverter(PropertyEditorCollection propertyEditors) : base(propertyEditors) { } + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(long); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) => source.TryConvertTo().Result; } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/CheckboxListValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/CheckboxListValueConverter.cs index 2e5c17fe7ee9..0f3361d68ac1 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/CheckboxListValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/CheckboxListValueConverter.cs @@ -4,22 +4,33 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for checkbox list properties. +/// [DefaultPropertyValueConverter] public class CheckboxListValueConverter : PropertyValueConverterBase { private readonly IJsonSerializer _jsonSerializer; + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public CheckboxListValueConverter(IJsonSerializer jsonSerializer) => _jsonSerializer = jsonSerializer; + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.CheckBoxList); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(IEnumerable); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object? source, bool preview) { var sourceString = source?.ToString() ?? string.Empty; diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/ColorPickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/ColorPickerValueConverter.cs index 89c5fff30013..285ee4ce4433 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/ColorPickerValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/ColorPickerValueConverter.cs @@ -8,25 +8,36 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for color picker properties. +/// [DefaultPropertyValueConverter] public class ColorPickerValueConverter : PropertyValueConverterBase { private readonly IJsonSerializer _jsonSerializer; + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public ColorPickerValueConverter(IJsonSerializer jsonSerializer) { _jsonSerializer = jsonSerializer; } + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.ColorPicker); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(PickedColor); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { if (source is null) @@ -50,19 +61,34 @@ public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType private bool UseLabel(IPublishedPropertyType propertyType) => ConfigurationEditor .ConfigurationAs(propertyType.DataType.ConfigurationObject)?.UseLabel ?? false; + /// + /// Represents a picked color from the color picker. + /// public class PickedColor { + /// + /// Initializes a new instance of the class. + /// + /// The color value. + /// The color label. public PickedColor(string color, string label) { Color = color; Label = label; } + /// + /// Gets the color value. + /// [JsonPropertyName("value")] public string Color { get; } + /// + /// Gets the color label. + /// public string Label { get; } + /// public override string ToString() => Color; } } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs index 972f7af03d04..48205e8f50a3 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs @@ -9,6 +9,9 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for content picker properties. +/// public class ContentPickerValueConverter : PropertyValueConverterBase, IDeliveryApiPropertyValueConverter { private static readonly List PropertiesToExclude = new() @@ -20,6 +23,11 @@ public class ContentPickerValueConverter : PropertyValueConverterBase, IDelivery private readonly IPublishedContentCache _publishedContentCache; private readonly IApiContentBuilder _apiContentBuilder; + /// + /// Initializes a new instance of the class. + /// + /// The published content cache. + /// The API content builder. public ContentPickerValueConverter( IPublishedContentCache publishedContentCache, IApiContentBuilder apiContentBuilder) @@ -28,15 +36,19 @@ public ContentPickerValueConverter( _apiContentBuilder = apiContentBuilder; } + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.Equals(Constants.PropertyEditors.Aliases.ContentPicker); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(IPublishedContent); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Elements; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { if (source == null) @@ -71,18 +83,23 @@ public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType return null; } + /// public override object? ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) { IPublishedContent? content = GetContent(propertyType, inter); return content ?? inter; } + /// public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType) => GetPropertyCacheLevel(propertyType); + /// public PropertyCacheLevel GetDeliveryApiPropertyCacheLevelForExpansion(IPublishedPropertyType propertyType) => PropertyCacheLevel.Snapshot; + /// public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType) => typeof(IApiContent); + /// public object? ConvertIntermediateToDeliveryApiObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview, bool expanding) { IPublishedContent? content = GetContent(propertyType, inter); diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DatePickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DatePickerValueConverter.cs index 472bc6aee3d7..689c12c18fc6 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DatePickerValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/DatePickerValueConverter.cs @@ -3,21 +3,33 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for date/time picker properties. +/// [DefaultPropertyValueConverter] public class DatePickerValueConverter : PropertyValueConverterBase { + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.DateTime); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(DateTime); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) => ParseDateTimeValue(source); + /// + /// Parses a source value to a value. + /// + /// The source value to parse. + /// The parsed value, or if parsing fails. internal static DateTime ParseDateTimeValue(object? source) { if (source is DateTime dateTimeValue) diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DateTimeValueTypeConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DateTimeValueTypeConverter.cs index 64dd9cb258aa..b3c4987238c3 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DateTimeValueTypeConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/DateTimeValueTypeConverter.cs @@ -2,22 +2,33 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for property editors with the date or date/time value type. +/// [DefaultValueTypePropertyValueConverter] public class DateTimeValueTypeConverter : ValueTypePropertyValueConverterBase { + /// protected override string[] SupportedValueTypes => new[] { ValueTypes.Date, ValueTypes.DateTime }; + /// + /// Initializes a new instance of the class. + /// + /// The property editor collection. public DateTimeValueTypeConverter(PropertyEditorCollection propertyEditors) : base(propertyEditors) { } + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(DateTime); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) => DatePickerValueConverter.ParseDateTimeValue(source); // reuse the value conversion from the default "Umbraco.DateTime" value converter } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DecimalValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DecimalValueConverter.cs index 0570f1e1a502..def885a2f8c1 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DecimalValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/DecimalValueConverter.cs @@ -3,21 +3,33 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for decimal properties. +/// [DefaultPropertyValueConverter] public class DecimalValueConverter : PropertyValueConverterBase { + /// public override bool IsConverter(IPublishedPropertyType propertyType) => Constants.PropertyEditors.Aliases.Decimal.Equals(propertyType.EditorAlias); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(decimal); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) => ParseDecimalValue(source); + /// + /// Parses a source value to a decimal value. + /// + /// The source value to parse. + /// The parsed decimal value, or 0 if parsing fails. internal static decimal ParseDecimalValue(object? source) { if (source == null) diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DecimalValueTypeConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DecimalValueTypeConverter.cs index 3dd66185e1b5..06406a5c53bd 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DecimalValueTypeConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/DecimalValueTypeConverter.cs @@ -2,22 +2,33 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for property editors with the decimal value type. +/// [DefaultValueTypePropertyValueConverter] public class DecimalValueTypeConverter : ValueTypePropertyValueConverterBase { + /// protected override string[] SupportedValueTypes => new[] { ValueTypes.Decimal }; + /// + /// Initializes a new instance of the class. + /// + /// The property editor collection. public DecimalValueTypeConverter(PropertyEditorCollection propertyEditors) : base(propertyEditors) { } + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(decimal); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) => DecimalValueConverter.ParseDecimalValue(source); // reuse the value conversion from the default "Umbraco.Decimal" value converter } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/EmailAddressValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/EmailAddressValueConverter.cs index 97074b66a338..5ffb79a228ca 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/EmailAddressValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/EmailAddressValueConverter.cs @@ -3,18 +3,25 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for email address properties. +/// [DefaultPropertyValueConverter] public class EmailAddressValueConverter : PropertyValueConverterBase { + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.EmailAddress); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(string); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object ConvertIntermediateToObject( IPublishedElement owner, IPublishedPropertyType propertyType, diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/EyeDropperValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/EyeDropperValueConverter.cs index b6bbff3b4196..ada04c401d8b 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/EyeDropperValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/EyeDropperValueConverter.cs @@ -3,18 +3,25 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for eye dropper color picker properties. +/// [DefaultPropertyValueConverter] public class EyeDropperValueConverter : PropertyValueConverterBase { + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.ColorPickerEyeDropper); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(string); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object? source, bool preview) => source?.ToString() ?? string.Empty; } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/FlexibleDropdownPropertyValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/FlexibleDropdownPropertyValueConverter.cs index 7acc43cdbe3d..71ac6163e6d6 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/FlexibleDropdownPropertyValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/FlexibleDropdownPropertyValueConverter.cs @@ -6,16 +6,25 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for flexible dropdown list properties. +/// [DefaultPropertyValueConverter] public class FlexibleDropdownPropertyValueConverter : PropertyValueConverterBase { private readonly IJsonSerializer _jsonSerializer; + /// + /// Initializes a new instance of the class. + /// + /// The JSON serializer. public FlexibleDropdownPropertyValueConverter(IJsonSerializer jsonSerializer) => _jsonSerializer = jsonSerializer; + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.Equals(Constants.PropertyEditors.Aliases.DropDownListFlexible); + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { if (source is null) @@ -30,6 +39,7 @@ public override bool IsConverter(IPublishedPropertyType propertyType) => : _jsonSerializer.Deserialize(source.ToString()!) ?? Array.Empty(); } + /// public override object? ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) { if (inter is null) @@ -51,6 +61,7 @@ public override bool IsConverter(IPublishedPropertyType propertyType) => : string.Empty; } + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => propertyType.DataType.ConfigurationAs()!.Multiple ? typeof(IEnumerable) diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/IntegerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/IntegerValueConverter.cs index c57ee85f1dcf..3159ce4ae782 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/IntegerValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/IntegerValueConverter.cs @@ -3,18 +3,25 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for integer properties. +/// [DefaultPropertyValueConverter] public class IntegerValueConverter : PropertyValueConverterBase { + /// public override bool IsConverter(IPublishedPropertyType propertyType) => Constants.PropertyEditors.Aliases.Integer.Equals(propertyType.EditorAlias); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(int); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate( IPublishedElement owner, IPublishedPropertyType propertyType, diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/IntegerValueTypeConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/IntegerValueTypeConverter.cs index d8ae0e25a0aa..7fc304ff27dc 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/IntegerValueTypeConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/IntegerValueTypeConverter.cs @@ -3,22 +3,33 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for property editors with the integer value type. +/// [DefaultValueTypePropertyValueConverter] public class IntegerValueTypeConverter : ValueTypePropertyValueConverterBase { + /// protected override string[] SupportedValueTypes => new[] { ValueTypes.Integer }; + /// + /// Initializes a new instance of the class. + /// + /// The property editor collection. public IntegerValueTypeConverter(PropertyEditorCollection propertyEditors) : base(propertyEditors) { } + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(int); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) => source.TryConvertTo().Result; } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/LabelValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/LabelValueConverter.cs index e95d85ebd579..ef65518cb3a8 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/LabelValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/LabelValueConverter.cs @@ -15,9 +15,11 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; [DefaultPropertyValueConverter] public class LabelValueConverter : PropertyValueConverterBase { + /// public override bool IsConverter(IPublishedPropertyType propertyType) => Constants.PropertyEditors.Aliases.Label.Equals(propertyType.EditorAlias); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) { LabelConfiguration? valueType = @@ -40,9 +42,11 @@ public override Type GetPropertyValueType(IPublishedPropertyType propertyType) } } + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { LabelConfiguration? valueType = diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberGroupPickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberGroupPickerValueConverter.cs index 4276e4ae332c..c28c560594ef 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberGroupPickerValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberGroupPickerValueConverter.cs @@ -6,28 +6,42 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for member group picker properties. +/// [DefaultPropertyValueConverter] public class MemberGroupPickerValueConverter : PropertyValueConverterBase, IDeliveryApiPropertyValueConverter { private readonly IMemberGroupService _memberGroupService; + /// + /// Initializes a new instance of the class. + /// + /// The member group service. public MemberGroupPickerValueConverter(IMemberGroupService memberGroupService) => _memberGroupService = memberGroupService; + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.MemberGroupPicker); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(string); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) => source?.ToString() ?? string.Empty; + /// public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType) => GetPropertyCacheLevel(propertyType); + /// public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType) => typeof(string[]); + /// public object? ConvertIntermediateToDeliveryApiObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview, bool expanding) { var memberGroupIds = inter? diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs index 8238bca83006..95ae0d4dd13b 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs @@ -8,12 +8,20 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for member picker properties. +/// [DefaultPropertyValueConverter] public class MemberPickerValueConverter : PropertyValueConverterBase, IDeliveryApiPropertyValueConverter { private readonly IMemberService _memberService; private readonly IPublishedMemberCache _memberCache; + /// + /// Initializes a new instance of the class. + /// + /// The member service. + /// The published member cache. public MemberPickerValueConverter( IMemberService memberService, IPublishedMemberCache memberCache) @@ -22,15 +30,19 @@ public MemberPickerValueConverter( _memberCache = memberCache; } + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.MemberPicker); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Snapshot; + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(IPublishedContent); + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { if (source == null) @@ -53,6 +65,7 @@ public override Type GetPropertyValueType(IPublishedPropertyType propertyType) return null; } + /// public override object? ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object? source, bool preview) { if (source == null) @@ -99,11 +112,16 @@ public override Type GetPropertyValueType(IPublishedPropertyType propertyType) return source; } + /// public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType) => GetPropertyCacheLevel(propertyType); + /// public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType) => typeof(string); - // member picker is unsupported for Delivery API output to avoid leaking member data by accident. + /// + /// + /// Member picker is unsupported for Delivery API output to avoid leaking member data by accident. + /// public object? ConvertIntermediateToDeliveryApiObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview, bool expanding) => "(unsupported)"; } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/MissingPropertyEditorValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MissingPropertyEditorValueConverter.cs index da70e558cfe7..c88a6e272785 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/MissingPropertyEditorValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/MissingPropertyEditorValueConverter.cs @@ -3,19 +3,23 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; /// -/// A value converter for the missing property editor, which always returns a string. +/// Provides property value conversion for the missing property editor, which always returns a string. /// [DefaultPropertyValueConverter] public class MissingPropertyEditorValueConverter : PropertyValueConverterBase { + /// public override bool IsConverter(IPublishedPropertyType propertyType) => "Umb.PropertyEditorUi.Missing".Equals(propertyType.EditorUiAlias); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(string); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) => source?.ToString() ?? string.Empty; } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs index 727c28f0777c..e6d15acc3166 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs @@ -32,6 +32,16 @@ public class MultiNodeTreePickerValueConverter : PropertyValueConverterBase, IDe private readonly IPublishedMediaCache _mediaCache; private readonly IPublishedMemberCache _memberCache; + /// + /// Initializes a new instance of the class. + /// + /// The Umbraco context accessor. + /// The member service. + /// The API content builder. + /// The API media builder. + /// The published content cache. + /// The published media cache. + /// The published member cache. public MultiNodeTreePickerValueConverter( IUmbracoContextAccessor umbracoContextAccessor, IMemberService memberService, @@ -50,17 +60,21 @@ public MultiNodeTreePickerValueConverter( _memberCache = memberCache; } + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.Equals(Constants.PropertyEditors.Aliases.MultiNodeTreePicker); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Snapshot; + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => IsSingleNodePicker(propertyType) ? typeof(IPublishedContent) : typeof(IEnumerable); + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { if (source == null) @@ -80,6 +94,7 @@ public override Type GetPropertyValueType(IPublishedPropertyType propertyType) return null; } + /// public override object? ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object? source, bool preview) { if (source == null) @@ -170,10 +185,13 @@ public override Type GetPropertyValueType(IPublishedPropertyType propertyType) return source; } + /// public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Snapshot; + /// public PropertyCacheLevel GetDeliveryApiPropertyCacheLevelForExpansion(IPublishedPropertyType propertyType) => PropertyCacheLevel.Snapshot; + /// public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType) => GetEntityType(propertyType) switch { @@ -183,6 +201,7 @@ public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType) }; + /// public object? ConvertIntermediateToDeliveryApiObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview, bool expanding) { IEnumerable DefaultValue() => Array.Empty(); diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs index 9908df6b3518..48c6d8d50737 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs @@ -2,20 +2,27 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for multiple text string properties. +/// [DefaultPropertyValueConverter] public class MultipleTextStringValueConverter : PropertyValueConverterBase { private static readonly string[] NewLineDelimiters = { "\r\n", "\r", "\n" }; + /// public override bool IsConverter(IPublishedPropertyType propertyType) => Constants.PropertyEditors.Aliases.MultipleTextstring.Equals(propertyType.EditorAlias); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(IEnumerable); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { // data is (both in database and xml): diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/MustBeStringValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MustBeStringValueConverter.cs index 141cfe53ec3d..5dc85313f1e9 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/MustBeStringValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/MustBeStringValueConverter.cs @@ -21,14 +21,18 @@ public class MustBeStringValueConverter : PropertyValueConverterBase { private static readonly string[] Aliases = { Constants.PropertyEditors.Aliases.MultiNodeTreePicker }; + /// public override bool IsConverter(IPublishedPropertyType propertyType) => Aliases.Contains(propertyType.EditorAlias); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(string); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) => source?.ToString(); } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/RadioButtonListValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/RadioButtonListValueConverter.cs index c18363a2db05..b4eb7edad737 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/RadioButtonListValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/RadioButtonListValueConverter.cs @@ -3,18 +3,25 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for radio button list properties. +/// [DefaultPropertyValueConverter] public class RadioButtonListValueConverter : PropertyValueConverterBase { + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.RadioButtonList); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(string); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { Attempt attempt = source.TryConvertTo(); diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleRichtextValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleRichtextValueConverter.cs index abf4c5b1eb1c..f911ebd5f19b 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleRichtextValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleRichtextValueConverter.cs @@ -9,16 +9,20 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; [DefaultPropertyValueConverter] public class SimpleRichTextValueConverter : PropertyValueConverterBase { + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias == Constants.PropertyEditors.Aliases.RichText; + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(IHtmlEncodedString); + /// // PropertyCacheLevel.Content is ok here because that converter does not parse {locallink} public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) => // in xml a string is: string @@ -26,6 +30,7 @@ public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType // default value is: null source; + /// public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) => // source should come from ConvertSource and be a string (or null) already diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueTypeConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueTypeConverter.cs index 9a57aaf52c45..d53e319c4482 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueTypeConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/TextStringValueTypeConverter.cs @@ -1,23 +1,34 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for property editors with the text or string value type. +/// [DefaultValueTypePropertyValueConverter] public class TextStringValueTypeConverter : ValueTypePropertyValueConverterBase { + /// protected override string[] SupportedValueTypes => new[] { ValueTypes.Text, ValueTypes.String }; + /// + /// Initializes a new instance of the class. + /// + /// The property editor collection. public TextStringValueTypeConverter(PropertyEditorCollection propertyEditors) : base(propertyEditors) { } + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(string); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) => source as string; } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/TimeValueTypeConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/TimeValueTypeConverter.cs index c18890e22a9d..b9fd9985a511 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/TimeValueTypeConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/TimeValueTypeConverter.cs @@ -1,23 +1,34 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for property editors with the time value type. +/// [DefaultValueTypePropertyValueConverter] public class TimeValueTypeConverter : ValueTypePropertyValueConverterBase { + /// protected override string[] SupportedValueTypes => new[] { ValueTypes.Time }; + /// + /// Initializes a new instance of the class. + /// + /// The property editor collection. public TimeValueTypeConverter(PropertyEditorCollection propertyEditors) : base(propertyEditors) { } + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(TimeSpan); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) => source is DateTime dateTimeValue ? dateTimeValue.ToUniversalTime().TimeOfDay : null; } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/UploadPropertyConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/UploadPropertyConverter.cs index 7a9ab907d876..3fd38d16e556 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/UploadPropertyConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/UploadPropertyConverter.cs @@ -3,19 +3,23 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; /// -/// The upload property value converter. +/// Provides property value conversion for file upload properties. /// [DefaultPropertyValueConverter] public class UploadPropertyConverter : PropertyValueConverterBase { + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias.Equals(Constants.PropertyEditors.Aliases.UploadField); + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(string); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel cacheLevel, object? source, bool preview) => source?.ToString() ?? string.Empty; } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/ValueTypePropertyValueConverterBase.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/ValueTypePropertyValueConverterBase.cs index 461de3181207..7a3633f835c2 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/ValueTypePropertyValueConverterBase.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/ValueTypePropertyValueConverterBase.cs @@ -1,17 +1,28 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides a base class for property value converters that match based on value type. +/// public abstract class ValueTypePropertyValueConverterBase : PropertyValueConverterBase { private readonly PropertyEditorCollection _propertyEditors; + /// + /// Gets the value types supported by this converter. + /// protected abstract string[] SupportedValueTypes { get; } + /// + /// Initializes a new instance of the class. + /// + /// The property editor collection. protected ValueTypePropertyValueConverterBase(PropertyEditorCollection propertyEditors) => _propertyEditors = propertyEditors; + /// public override bool IsConverter(IPublishedPropertyType propertyType) => _propertyEditors.TryGet(propertyType.EditorAlias, out IDataEditor? editor) && SupportedValueTypes.InvariantContains(editor.GetValueEditor().ValueType); diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/XmlValueTypeConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/XmlValueTypeConverter.cs index bab85a25d94b..fb02b9da1b5f 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/XmlValueTypeConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/XmlValueTypeConverter.cs @@ -1,25 +1,36 @@ -using System.Xml.Linq; +using System.Xml.Linq; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PropertyEditors.DeliveryApi; namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for property editors with the XML value type. +/// [DefaultValueTypePropertyValueConverter] public class XmlValueTypeConverter : ValueTypePropertyValueConverterBase, IDeliveryApiPropertyValueConverter { + /// protected override string[] SupportedValueTypes => new[] { ValueTypes.Xml }; + /// + /// Initializes a new instance of the class. + /// + /// The property editor collection. public XmlValueTypeConverter(PropertyEditorCollection propertyEditors) : base(propertyEditors) { } + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(XDocument); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { if (source is not string stringValue) @@ -37,13 +48,19 @@ public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType } } + /// public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType) => GetPropertyCacheLevel(propertyType); + /// public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType) => typeof(string); - // System.Text.Json does not appreciate serializing XDocument because of parent/child node references. Let's settle for outputting the raw XML as a string, then. + /// + /// + /// System.Text.Json does not appreciate serializing XDocument because of parent/child node references. + /// The raw XML is output as a string instead. + /// public object? ConvertIntermediateToDeliveryApiObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview, bool expanding) => inter is XDocument xDocumentValue ? xDocumentValue.ToString(SaveOptions.DisableFormatting) diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/YesNoValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/YesNoValueConverter.cs index f3953d73a38f..6a3ca9594f81 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/YesNoValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/YesNoValueConverter.cs @@ -2,18 +2,25 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters; +/// +/// Provides property value conversion for boolean (Yes/No) properties. +/// [DefaultPropertyValueConverter] public class YesNoValueConverter : PropertyValueConverterBase { + /// public override bool IsConverter(IPublishedPropertyType propertyType) => propertyType.EditorAlias == Constants.PropertyEditors.Aliases.Boolean; + /// public override Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(bool); + /// public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + /// public override object? ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object? source, bool preview) { if (source is null) diff --git a/src/Umbraco.Core/PropertyEditors/ValueListConfiguration.cs b/src/Umbraco.Core/PropertyEditors/ValueListConfiguration.cs index 69279ebad8d0..501acac06ee3 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueListConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueListConfiguration.cs @@ -5,6 +5,9 @@ namespace Umbraco.Cms.Core.PropertyEditors; /// public class ValueListConfiguration { + /// + /// Gets or sets the list of selectable items. + /// [ConfigurationField("items")] public List Items { get; set; } = new(); } diff --git a/src/Umbraco.Core/PublishedCache/ICacheManager.cs b/src/Umbraco.Core/PublishedCache/ICacheManager.cs index 062a802adbbb..444685de060b 100644 --- a/src/Umbraco.Core/PublishedCache/ICacheManager.cs +++ b/src/Umbraco.Core/PublishedCache/ICacheManager.cs @@ -1,7 +1,15 @@ -using Umbraco.Cms.Core.Cache; +using Umbraco.Cms.Core.Cache; namespace Umbraco.Cms.Core.PublishedCache; +/// +/// Provides unified access to all published content caches. +/// +/// +/// The cache manager aggregates the content, media, member, and domain caches, +/// providing a single entry point for accessing cached published content. +/// It also provides access to the elements-level cache shared across snapshots. +/// public interface ICacheManager { /// diff --git a/src/Umbraco.Core/PublishedCache/IDocumentCacheService.cs b/src/Umbraco.Core/PublishedCache/IDocumentCacheService.cs index d17c628063b9..2d5b95fac3c3 100644 --- a/src/Umbraco.Core/PublishedCache/IDocumentCacheService.cs +++ b/src/Umbraco.Core/PublishedCache/IDocumentCacheService.cs @@ -1,31 +1,100 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.PublishedCache; +/// +/// Defines operations for the document (content) cache service. +/// +/// +/// This service provides access to published document content with caching support, +/// including operations for cache seeding, refreshing, and rebuilding. +/// public interface IDocumentCacheService { + /// + /// Gets a published content item by its unique key. + /// + /// The unique key of the content. + /// Optional value indicating whether to include unpublished content. If null, uses the default preview setting. + /// The published content, or null if not found. Task GetByKeyAsync(Guid key, bool? preview = null); + /// + /// Gets a published content item by its integer identifier. + /// + /// The integer identifier of the content. + /// Optional value indicating whether to include unpublished content. If null, uses the default preview setting. + /// The published content, or null if not found. Task GetByIdAsync(int id, bool? preview = null); + /// + /// Seeds the cache with initial content data. + /// + /// A cancellation token to observe while waiting for the task to complete. + /// A task representing the asynchronous operation. Task SeedAsync(CancellationToken cancellationToken); + /// + /// Determines whether content with the specified identifier exists in the cache. + /// + /// The integer identifier of the content. + /// A value indicating whether to check for unpublished content. + /// true if content with the specified identifier exists; otherwise, false. Task HasContentByIdAsync(int id, bool preview = false); + /// + /// Refreshes the cache entry for the specified content item. + /// + /// The content item to refresh in the cache. + /// A task representing the asynchronous operation. Task RefreshContentAsync(IContent content); + /// + /// Removes the specified content item from the cache. + /// + /// The content item to remove from the cache. + /// A task representing the asynchronous operation. Task DeleteItemAsync(IContentBase content); + /// + /// Rebuilds the cache for content items of the specified content types. + /// + /// The collection of content type identifiers to rebuild. void Rebuild(IReadOnlyCollection contentTypeIds); + /// + /// Gets all published content items of the specified content type. + /// + /// The published content type to filter by. + /// A collection of published content items of the specified type. IEnumerable GetByContentType(IPublishedContentType contentType); + /// + /// Clears all entries from the memory cache. + /// + /// A cancellation token to observe while waiting for the task to complete. + /// A task representing the asynchronous operation. Task ClearMemoryCacheAsync(CancellationToken cancellationToken); + /// + /// Refreshes the memory cache entry for the content item with the specified key. + /// + /// The unique key of the content to refresh. + /// A task representing the asynchronous operation. Task RefreshMemoryCacheAsync(Guid key); + /// + /// Removes the content item with the specified key from the memory cache. + /// + /// The unique key of the content to remove. + /// A task representing the asynchronous operation. Task RemoveFromMemoryCacheAsync(Guid key); + /// + /// Rebuilds the memory cache for content items of the specified content types. + /// + /// The collection of content type identifiers to rebuild in memory cache. + /// A task representing the asynchronous operation. Task RebuildMemoryCacheByContentTypeAsync(IEnumerable contentTypeIds); } diff --git a/src/Umbraco.Core/PublishedCache/IDomainCache.cs b/src/Umbraco.Core/PublishedCache/IDomainCache.cs index 41443ef1f6f6..ba1d168f0ca7 100644 --- a/src/Umbraco.Core/PublishedCache/IDomainCache.cs +++ b/src/Umbraco.Core/PublishedCache/IDomainCache.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.PublishedCache; +/// +/// Provides caching and retrieval of domain information for published content. +/// public interface IDomainCache { /// diff --git a/src/Umbraco.Core/PublishedCache/IDomainCacheService.cs b/src/Umbraco.Core/PublishedCache/IDomainCacheService.cs index 5d856ff3497e..49f93f4936bd 100644 --- a/src/Umbraco.Core/PublishedCache/IDomainCacheService.cs +++ b/src/Umbraco.Core/PublishedCache/IDomainCacheService.cs @@ -1,16 +1,23 @@ -using Umbraco.Cms.Core.Cache; +using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Routing; namespace Umbraco.Cms.Core.PublishedCache; +/// +/// Defines operations for the domain cache service. +/// +/// +/// This service provides access to domain information with caching support, +/// including operations for retrieving domains and handling cache refresh. +/// public interface IDomainCacheService { /// /// Gets all in the current domain cache, including any domains that may be referenced by /// documents that are no longer published. /// - /// - /// + /// A value indicating whether to include wildcard domains. + /// A collection of all domains in the cache. IEnumerable GetAll(bool includeWildcards); /// @@ -18,6 +25,7 @@ public interface IDomainCacheService /// /// The document identifier. /// A value indicating whether to consider wildcard domains. + /// A collection of domains assigned to the specified document. IEnumerable GetAssigned(int documentId, bool includeWildcards = false); /// @@ -25,7 +33,12 @@ public interface IDomainCacheService /// /// The document identifier. /// A value indicating whether to consider wildcard domains. + /// true if the document has assigned domains; otherwise, false. bool HasAssigned(int documentId, bool includeWildcards = false); + /// + /// Refreshes the domain cache based on the provided payloads. + /// + /// The cache refresh payloads containing domain change information. void Refresh(DomainCacheRefresher.JsonPayload[] payloads); } diff --git a/src/Umbraco.Core/PublishedCache/IMediaCacheService.cs b/src/Umbraco.Core/PublishedCache/IMediaCacheService.cs index b13a4a4aac89..a8f1320633e2 100644 --- a/src/Umbraco.Core/PublishedCache/IMediaCacheService.cs +++ b/src/Umbraco.Core/PublishedCache/IMediaCacheService.cs @@ -1,30 +1,97 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.PublishedCache; +/// +/// Defines operations for the media cache service. +/// +/// +/// This service provides access to published media content with caching support, +/// including operations for cache seeding, refreshing, and rebuilding. +/// public interface IMediaCacheService { + /// + /// Gets a published media item by its unique key. + /// + /// The unique key of the media. + /// The published media content, or null if not found. Task GetByKeyAsync(Guid key); + /// + /// Gets a published media item by its integer identifier. + /// + /// The integer identifier of the media. + /// The published media content, or null if not found. Task GetByIdAsync(int id); + /// + /// Determines whether media with the specified identifier exists in the cache. + /// + /// The integer identifier of the media. + /// true if media with the specified identifier exists; otherwise, false. Task HasContentByIdAsync(int id); + /// + /// Refreshes the cache entry for the specified media item. + /// + /// The media item to refresh in the cache. + /// A task representing the asynchronous operation. Task RefreshMediaAsync(IMedia media); + /// + /// Rebuilds the memory cache for media items of the specified media types. + /// + /// The collection of media type identifiers to rebuild in memory cache. + /// A task representing the asynchronous operation. Task RebuildMemoryCacheByContentTypeAsync(IEnumerable mediaTypeIds); + /// + /// Clears all entries from the memory cache. + /// + /// A cancellation token to observe while waiting for the task to complete. + /// A task representing the asynchronous operation. Task ClearMemoryCacheAsync(CancellationToken cancellationToken); + /// + /// Refreshes the memory cache entry for the media item with the specified key. + /// + /// The unique key of the media to refresh. + /// A task representing the asynchronous operation. Task RefreshMemoryCacheAsync(Guid key); + /// + /// Removes the media item with the specified key from the memory cache. + /// + /// The unique key of the media to remove. + /// A task representing the asynchronous operation. Task RemoveFromMemoryCacheAsync(Guid key); + /// + /// Removes the specified media item from the cache. + /// + /// The media item to remove from the cache. + /// A task representing the asynchronous operation. Task DeleteItemAsync(IContentBase media); + /// + /// Seeds the cache with initial media data. + /// + /// A cancellation token to observe while waiting for the task to complete. + /// A task representing the asynchronous operation. Task SeedAsync(CancellationToken cancellationToken); + /// + /// Rebuilds the cache for media items of the specified media types. + /// + /// The collection of media type identifiers to rebuild. void Rebuild(IReadOnlyCollection contentTypeIds); + + /// + /// Gets all published media items of the specified content type. + /// + /// The published content type to filter by. + /// A collection of published media items of the specified type. IEnumerable GetByContentType(IPublishedContentType contentType); } diff --git a/src/Umbraco.Core/PublishedCache/IPublishedContentCache.cs b/src/Umbraco.Core/PublishedCache/IPublishedContentCache.cs index dd5aa53f5ef1..799c7be59e9d 100644 --- a/src/Umbraco.Core/PublishedCache/IPublishedContentCache.cs +++ b/src/Umbraco.Core/PublishedCache/IPublishedContentCache.cs @@ -2,6 +2,13 @@ namespace Umbraco.Cms.Core.PublishedCache; +/// +/// Provides access to cached published content items with async support. +/// +/// +/// This interface extends with asynchronous methods +/// for retrieving content items, supporting both integer IDs and GUIDs. +/// public interface IPublishedContentCache : IPublishedCache { /// diff --git a/src/Umbraco.Core/PublishedCache/IPublishedContentTypeCache.cs b/src/Umbraco.Core/PublishedCache/IPublishedContentTypeCache.cs index 39c02d9f2f95..84f5766f0ebf 100644 --- a/src/Umbraco.Core/PublishedCache/IPublishedContentTypeCache.cs +++ b/src/Umbraco.Core/PublishedCache/IPublishedContentTypeCache.cs @@ -1,7 +1,14 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.PublishedCache; +/// +/// Provides caching for published content types. +/// +/// +/// This interface defines operations for caching and retrieving instances, +/// including methods for clearing cached types when content types or data types are modified. +/// public interface IPublishedContentTypeCache { /// diff --git a/src/Umbraco.Core/PublishedCache/IPublishedMediaCache.cs b/src/Umbraco.Core/PublishedCache/IPublishedMediaCache.cs index cb66f43c12c6..be7297812b9e 100644 --- a/src/Umbraco.Core/PublishedCache/IPublishedMediaCache.cs +++ b/src/Umbraco.Core/PublishedCache/IPublishedMediaCache.cs @@ -2,6 +2,13 @@ namespace Umbraco.Cms.Core.PublishedCache; +/// +/// Provides access to cached published media items with async support. +/// +/// +/// This interface extends with asynchronous methods +/// for retrieving media items, supporting both integer IDs and GUIDs. +/// public interface IPublishedMediaCache : IPublishedCache { /// diff --git a/src/Umbraco.Core/PublishedCache/ITagQuery.cs b/src/Umbraco.Core/PublishedCache/ITagQuery.cs index 8df363dbe447..dd2d10ae3da5 100644 --- a/src/Umbraco.Core/PublishedCache/ITagQuery.cs +++ b/src/Umbraco.Core/PublishedCache/ITagQuery.cs @@ -3,6 +3,14 @@ namespace Umbraco.Cms.Core.PublishedCache; +/// +/// Provides methods for querying content and media by their associated tags. +/// +/// +/// Tags are organized into groups and can be culture-specific. +/// This interface allows retrieval of content, media, and member items by their tags, +/// as well as listing all available tags. +/// public interface ITagQuery { /// diff --git a/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedContent.cs b/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedContent.cs index df0975115578..d721db14b5b2 100644 --- a/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedContent.cs +++ b/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedContent.cs @@ -8,11 +8,23 @@ namespace Umbraco.Cms.Core.PublishedCache.Internal; // TODO: Only used in unit tests, needs to be moved to test project + +/// +/// Provides an internal implementation of for testing purposes. +/// +/// +/// This class is intended for unit testing only and should not be used in production code. +/// It should be moved to a test project in a future refactoring. +/// [EditorBrowsable(EditorBrowsableState.Never)] public sealed class InternalPublishedContent : IPublishedContent { private Dictionary? _cultures; + /// + /// Initializes a new instance of the class. + /// + /// The published content type. public InternalPublishedContent(IPublishedContentType contentType) { // initialize boring stuff @@ -26,14 +38,29 @@ public InternalPublishedContent(IPublishedContentType contentType) Name = string.Empty; } + /// + /// Gets or sets the version identifier. + /// public Guid Version { get; set; } + /// + /// Gets or sets the parent content identifier. + /// public int ParentId { get; set; } + /// + /// Gets or sets the collection of child content identifiers. + /// public IEnumerable ChildIds { get; set; } = Enumerable.Empty(); + /// public int Id { get; set; } + /// + /// Gets the value of a property by its alias. + /// + /// The property alias. + /// The property value, or null if the property does not exist or has no value. public object? this[string alias] { get @@ -43,53 +70,80 @@ public object? this[string alias] } } + /// public Guid Key { get; set; } + /// public int? TemplateId { get; set; } + /// public int SortOrder { get; set; } + /// public string Name { get; set; } + /// public IReadOnlyDictionary Cultures => _cultures ??= GetCultures(); + /// public string? UrlSegment { get; set; } + /// public int WriterId { get; set; } + /// public int CreatorId { get; set; } + /// public string Path { get; set; } + /// public DateTime CreateDate { get; set; } + /// public DateTime UpdateDate { get; set; } + /// public int Level { get; set; } + /// public PublishedItemType ItemType => PublishedItemType.Content; + /// [Obsolete("Please use TryGetParentKey() on IDocumentNavigationQueryService or IMediaNavigationQueryService instead. Scheduled for removal in V16.")] public IPublishedContent? Parent => this.Parent(StaticServiceProvider.Instance.GetRequiredService(), StaticServiceProvider.Instance.GetRequiredService()); + /// public bool IsDraft(string? culture = null) => false; + /// public bool IsPublished(string? culture = null) => true; + /// [Obsolete("Please use TryGetChildrenKeys() on IDocumentNavigationQueryService or IMediaNavigationQueryService instead. Scheduled for removal in V16.")] public IEnumerable Children => this.Children( StaticServiceProvider.Instance.GetRequiredService(), StaticServiceProvider.Instance.GetRequiredService()); + /// public IEnumerable ChildrenForAllCultures => Children; + /// public IPublishedContentType ContentType { get; set; } + /// public IEnumerable Properties { get; set; } + /// public IPublishedProperty? GetProperty(string alias) => Properties?.FirstOrDefault(p => p.Alias.InvariantEquals(alias)); + /// + /// Gets a property by its alias, optionally recursing up the content tree. + /// + /// The property alias. + /// A value indicating whether to recurse up the content tree if the property is not found or has no value. + /// The property, or null if not found. public IPublishedProperty? GetProperty(string alias, bool recurse) { IPublishedProperty? property = GetProperty(alias); @@ -108,6 +162,10 @@ public object? this[string alias] return property; } + /// + /// Gets the culture information dictionary for this content. + /// + /// A dictionary mapping culture codes to instances. private Dictionary GetCultures() => new() { { string.Empty, new PublishedCultureInfo(string.Empty, Name, UrlSegment, UpdateDate) }, diff --git a/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedProperty.cs b/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedProperty.cs index 9b54d65a52e5..a06c1e65e201 100644 --- a/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedProperty.cs +++ b/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedProperty.cs @@ -4,26 +4,53 @@ namespace Umbraco.Cms.Core.PublishedCache.Internal; // TODO: Only used in unit tests, needs to be moved to test project + +/// +/// Provides an internal implementation of for testing purposes. +/// +/// +/// This class is intended for unit testing only and should not be used in production code. +/// It allows setting property values directly via properties rather than through conversion. +/// It should be moved to a test project in a future refactoring. +/// [EditorBrowsable(EditorBrowsableState.Never)] public class InternalPublishedProperty : IPublishedProperty { + /// + /// Gets or sets the solid source value to be returned by . + /// public object? SolidSourceValue { get; set; } + /// + /// Gets or sets the solid converted value to be returned by . + /// public object? SolidValue { get; set; } + /// + /// Gets or sets a value indicating whether the property has a value. + /// public bool SolidHasValue { get; set; } + /// + /// Gets or sets the solid Delivery API value to be returned by . + /// public object? SolidDeliveryApiValue { get; set; } + /// public IPublishedPropertyType PropertyType { get; set; } = null!; + /// public string Alias { get; set; } = string.Empty; + /// public virtual object? GetSourceValue(string? culture = null, string? segment = null) => SolidSourceValue; + /// public virtual object? GetValue(string? culture = null, string? segment = null) => SolidValue; + /// public virtual object? GetDeliveryApiValue(bool expanding, string? culture = null, string? segment = null) => SolidDeliveryApiValue; + /// public virtual bool HasValue(string? culture = null, string? segment = null) => SolidHasValue; } diff --git a/src/Umbraco.Core/PublishedCache/PublishedCacheBase.cs b/src/Umbraco.Core/PublishedCache/PublishedCacheBase.cs index 6dbc832a5b9d..808ac31de2a0 100644 --- a/src/Umbraco.Core/PublishedCache/PublishedCacheBase.cs +++ b/src/Umbraco.Core/PublishedCache/PublishedCacheBase.cs @@ -2,32 +2,64 @@ namespace Umbraco.Cms.Core.PublishedCache; +/// +/// Provides a base implementation for published content caches. +/// public abstract class PublishedCacheBase : IPublishedCache { private readonly IVariationContextAccessor? _variationContextAccessor; + /// + /// Initializes a new instance of the class. + /// + /// The variation context accessor for culture and segment information. + /// A value indicating whether preview mode is enabled by default. public PublishedCacheBase(IVariationContextAccessor variationContextAccessor, bool previewDefault) { _variationContextAccessor = variationContextAccessor; PreviewDefault = previewDefault; } + /// + /// Gets a value indicating whether preview mode is enabled by default. + /// public bool PreviewDefault { get; } + /// public abstract IPublishedContent? GetById(bool preview, int contentId); + /// public IPublishedContent? GetById(int contentId) => GetById(PreviewDefault, contentId); + /// public abstract IPublishedContent? GetById(bool preview, Guid contentId); + /// public IPublishedContent? GetById(Guid contentId) => GetById(PreviewDefault, contentId); + /// + /// Determines whether content with the specified identifier exists. + /// + /// A value indicating whether to consider unpublished content. + /// The content unique identifier. + /// true if content with the specified identifier exists; otherwise, false. public abstract bool HasById(bool preview, int contentId); + /// + /// Determines whether content with the specified identifier exists using the default preview setting. + /// + /// The content unique identifier. + /// true if content with the specified identifier exists; otherwise, false. public bool HasById(int contentId) => HasById(PreviewDefault, contentId); + /// + /// Gets content items at the root of the content tree. + /// + /// A value indicating whether to consider unpublished content. + /// The optional culture to filter by. + /// A collection of published content items at the root level. public abstract IEnumerable GetAtRoot(bool preview, string? culture = null); } diff --git a/src/Umbraco.Core/PublishedCache/PublishedElement.cs b/src/Umbraco.Core/PublishedCache/PublishedElement.cs index c8d8acab4d2e..07c5e63b390d 100644 --- a/src/Umbraco.Core/PublishedCache/PublishedElement.cs +++ b/src/Umbraco.Core/PublishedCache/PublishedElement.cs @@ -13,12 +13,31 @@ namespace Umbraco.Cms.Core.PublishedCache; // an entirely new models factory + not even sure it makes sense at all since // sets are created manually todo yes it does! - what does this all mean? // + +/// +/// Represents a published element that provides access to content type information and properties. +/// +/// +/// A published element does NOT manage any tree-like elements. It represents detached content +/// that is not part of the content tree hierarchy (e.g., nested content items, block list items). +/// public class PublishedElement : IPublishedElement { private readonly IPublishedProperty[] _propertiesArray; - // initializes a new instance of the PublishedElement class - // within the context of a published snapshot service (eg a published content property value) + /// + /// Initializes a new instance of the class + /// within the context of a published snapshot service (e.g., a published content property value). + /// + /// The published content type. + /// The unique identifier for this element. + /// The property values dictionary. + /// A value indicating whether this is a preview request. + /// The reference cache level for property value caching. + /// The variation context for culture and segment. + /// The cache manager for property value caching. + /// Thrown when is an empty GUID. + /// Thrown when or is null. public PublishedElement(IPublishedContentType contentType, Guid key, Dictionary? values, bool previewing, PropertyCacheLevel referenceCacheLevel, VariationContext variationContext, ICacheManager? cacheManager) { if (key == Guid.Empty) @@ -47,20 +66,35 @@ public PublishedElement(IPublishedContentType contentType, Guid key, Dictionary< ?? []; } - // initializes a new instance of the PublishedElement class - // without any context, so it's purely 'standalone' and should NOT interfere with the published snapshot service - // + using an initial reference cache level of .None ensures that everything will be - // cached at .Content level - and that reference cache level will propagate to all - // properties + /// + /// Initializes a new instance of the class + /// without any context, making it purely standalone and not interfering with the published snapshot service. + /// + /// The published content type. + /// The unique identifier for this element. + /// The property values dictionary. + /// A value indicating whether this is a preview request. + /// The variation context for culture and segment. + /// + /// Using an initial reference cache level of ensures that everything will be + /// cached at element level, and that reference cache level will propagate to all properties. + /// public PublishedElement(IPublishedContentType contentType, Guid key, Dictionary values, bool previewing, VariationContext variationContext) : this(contentType, key, values, previewing, PropertyCacheLevel.None, variationContext, null) { } + /// public IPublishedContentType ContentType { get; } + /// public Guid Key { get; } + /// + /// Converts a property values dictionary to use case-insensitive key comparison. + /// + /// The original property values dictionary. + /// A dictionary with case-insensitive key comparison. private static Dictionary GetCaseInsensitiveValueDictionary(Dictionary values) { // ensure we ignore case for property aliases @@ -71,8 +105,10 @@ public PublishedElement(IPublishedContentType contentType, Guid key, Dictionary< return ignoreCase ? values : new Dictionary(values, StringComparer.OrdinalIgnoreCase); } + /// public IEnumerable Properties => _propertiesArray; + /// public IPublishedProperty? GetProperty(string alias) { var index = ContentType.GetPropertyIndex(alias); diff --git a/src/Umbraco.Core/PublishedCache/PublishedElementPropertyBase.cs b/src/Umbraco.Core/PublishedCache/PublishedElementPropertyBase.cs index 5427b87781c5..8d47694e686b 100644 --- a/src/Umbraco.Core/PublishedCache/PublishedElementPropertyBase.cs +++ b/src/Umbraco.Core/PublishedCache/PublishedElementPropertyBase.cs @@ -55,10 +55,16 @@ public PublishedElementPropertyBase( _isMember = propertyType.ContentType?.ItemType == PublishedItemType.Member; } - // used to cache the CacheValues of this property + /// + /// Gets the cache key used to store the of this property. + /// // ReSharper disable InconsistentlySynchronizedField private string ValuesCacheKey => _valuesCacheKey ??= PropertyCacheValuesKey(); + /// + /// Generates the cache key for this property's cached values. + /// + /// A unique cache key string for this property. private string PropertyCacheValuesKey() => $"PublishedSnapshot.Property.CacheValues[{(_isPreviewing ? "D:" : "P:")}{_element.Key}:{Alias}:{_variationContext.Culture.IfNullOrWhiteSpace("inv")}+{_variationContext.Segment.IfNullOrWhiteSpace("inv")}]"; @@ -100,15 +106,36 @@ public override bool HasValue(string? culture = null, string? segment = null) /// public override object? GetSourceValue(string? culture = null, string? segment = null) => _sourceValue; + /// + /// Gets the cache levels for standard property value conversion. + /// + /// When this method returns, contains the actual cache level for the property. + /// When this method returns, contains the new reference cache level. private void GetCacheLevels(out PropertyCacheLevel cacheLevel, out PropertyCacheLevel referenceCacheLevel) => GetCacheLevels(PropertyType.CacheLevel, out cacheLevel, out referenceCacheLevel); + /// + /// Gets the cache levels for Delivery API property value conversion. + /// + /// When this method returns, contains the actual cache level for the property. + /// When this method returns, contains the new reference cache level. private void GetDeliveryApiCacheLevels(out PropertyCacheLevel cacheLevel, out PropertyCacheLevel referenceCacheLevel) => GetCacheLevels(PropertyType.DeliveryApiCacheLevel, out cacheLevel, out referenceCacheLevel); + /// + /// Gets the cache levels for Delivery API property value conversion during expansion. + /// + /// When this method returns, contains the actual cache level for the property. + /// When this method returns, contains the new reference cache level. private void GetDeliveryApiCacheLevelsForExpansion(out PropertyCacheLevel cacheLevel, out PropertyCacheLevel referenceCacheLevel) => GetCacheLevels(PropertyType.DeliveryApiCacheLevelForExpansion, out cacheLevel, out referenceCacheLevel); + /// + /// Calculates the actual cache level and reference cache level based on the property type's cache level. + /// + /// The property type's specified cache level. + /// When this method returns, contains the actual cache level for the property. + /// When this method returns, contains the new reference cache level. private void GetCacheLevels(PropertyCacheLevel propertyTypeCacheLevel, out PropertyCacheLevel cacheLevel, out PropertyCacheLevel referenceCacheLevel) { // based upon the current reference cache level (ReferenceCacheLevel) and this property @@ -135,6 +162,12 @@ private void GetCacheLevels(PropertyCacheLevel propertyTypeCacheLevel, out Prope } } + /// + /// Gets or creates the cache values container for the specified cache level. + /// + /// The cache level to get values for. + /// The cache values container. + /// Thrown when an invalid cache level is specified. private CacheValues GetCacheValues(PropertyCacheLevel cacheLevel) { CacheValues cacheValues; @@ -160,6 +193,10 @@ private CacheValues GetCacheValues(PropertyCacheLevel cacheLevel) return cacheValues; } + /// + /// Gets the intermediate value by converting the source value if not already initialized. + /// + /// The intermediate value. private object? GetInterValue() { if (_interInitialized) @@ -216,6 +253,12 @@ private CacheValues GetCacheValues(PropertyCacheLevel cacheLevel) } } + /// + /// Gets the default Delivery API object value, initializing it if necessary. + /// + /// The cache values container. + /// A function to compute the value if not cached. + /// The Delivery API default object value. private object? GetDeliveryApiDefaultObject(CacheValues cacheValues, Func getValue) { if (cacheValues.DeliveryApiDefaultObjectInitialized == false) @@ -227,6 +270,12 @@ private CacheValues GetCacheValues(PropertyCacheLevel cacheLevel) return cacheValues.DeliveryApiDefaultObjectValue; } + /// + /// Gets the expanded Delivery API object value, initializing it if necessary. + /// + /// The cache values container. + /// A function to compute the value if not cached. + /// The Delivery API expanded object value. private object? GetDeliveryApiExpandedObject(CacheValues cacheValues, Func getValue) { if (cacheValues.DeliveryApiExpandedObjectInitialized == false) @@ -238,15 +287,49 @@ private CacheValues GetCacheValues(PropertyCacheLevel cacheLevel) return cacheValues.DeliveryApiExpandedObjectValue; } + /// + /// Represents cached property values for different conversion levels and API types. + /// private class CacheValues { + /// + /// Gets or sets a value indicating whether the object value has been initialized. + /// public bool ObjectInitialized { get; set; } + + /// + /// Gets or sets the cached object value. + /// public object? ObjectValue { get; set; } + + /// + /// Gets or sets a value indicating whether the XPath value has been initialized. + /// public bool XPathInitialized { get; set; } + + /// + /// Gets or sets the cached XPath value. + /// public object? XPathValue { get; set; } + + /// + /// Gets or sets a value indicating whether the Delivery API default object value has been initialized. + /// public bool DeliveryApiDefaultObjectInitialized { get; set; } + + /// + /// Gets or sets the cached Delivery API default object value. + /// public object? DeliveryApiDefaultObjectValue { get; set; } + + /// + /// Gets or sets a value indicating whether the Delivery API expanded object value has been initialized. + /// public bool DeliveryApiExpandedObjectInitialized { get; set; } + + /// + /// Gets or sets the cached Delivery API expanded object value. + /// public object? DeliveryApiExpandedObjectValue { get; set; } } } diff --git a/src/Umbraco.Core/Routing/AliasUrlProvider.cs b/src/Umbraco.Core/Routing/AliasUrlProvider.cs index eb8aa3d576e8..c16602a84715 100644 --- a/src/Umbraco.Core/Routing/AliasUrlProvider.cs +++ b/src/Umbraco.Core/Routing/AliasUrlProvider.cs @@ -21,6 +21,16 @@ public class AliasUrlProvider : IUrlProvider private readonly UriUtility _uriUtility; private RequestHandlerSettings _requestConfig; + /// + /// Initializes a new instance of the class. + /// + /// The request handler settings. + /// The site domain mapper. + /// The URI utility. + /// The published value fallback. + /// The Umbraco context accessor. + /// The navigation query service. + /// The published content status filtering service. public AliasUrlProvider( IOptionsMonitor requestConfig, ISiteDomainMapper siteDomainMapper, diff --git a/src/Umbraco.Core/Routing/ContentFinderByIdentifierPathBase.cs b/src/Umbraco.Core/Routing/ContentFinderByIdentifierPathBase.cs index fd54317cde84..f131929f3aa5 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByIdentifierPathBase.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByIdentifierPathBase.cs @@ -3,22 +3,37 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Provides a base class for content finders that handle identifier-based paths (like keys or IDs). +/// public abstract class ContentFinderByIdentifierPathBase { private readonly IRequestAccessor _requestAccessor; private readonly ILogger _logger; + /// + /// Gets the log message template used when content lookup fails. + /// /// - /// Used as the log message inside >. + /// Used as the log message inside . /// protected abstract string FailureLogMessageTemplate { get; } + /// + /// Initializes a new instance of the class. + /// + /// The request accessor. + /// The logger. protected ContentFinderByIdentifierPathBase(IRequestAccessor requestAccessor, ILogger logger) { _requestAccessor = requestAccessor; _logger = logger; } + /// + /// Resolves the culture from the query string and sets it on the request. + /// + /// The published request builder. protected void ResolveAndSetCultureOnRequest(IPublishedRequestBuilder frequest) { var cultureFromQuerystring = _requestAccessor.GetQueryStringValue("culture"); @@ -32,6 +47,10 @@ protected void ResolveAndSetCultureOnRequest(IPublishedRequestBuilder frequest) } } + /// + /// Resolves the segment from the query string and sets it on the request. + /// + /// The published request builder. protected void ResolveAndSetSegmentOnRequest(IPublishedRequestBuilder frequest) { var segmentFromQuerystring = _requestAccessor.GetQueryStringValue("segment"); @@ -44,6 +63,10 @@ protected void ResolveAndSetSegmentOnRequest(IPublishedRequestBuilder frequest) } } + /// + /// Logs a debug message and returns a failed task result. + /// + /// A task that returns false. protected Task LogAndReturnFailure() { if (_logger.IsEnabled(LogLevel.Debug)) diff --git a/src/Umbraco.Core/Routing/ContentFinderByKeyPath.cs b/src/Umbraco.Core/Routing/ContentFinderByKeyPath.cs index 1f5caac1310e..c782d962c2f4 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByKeyPath.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByKeyPath.cs @@ -18,6 +18,7 @@ public class ContentFinderByKeyPath : ContentFinderByIdentifierPathBase, IConten private readonly IUmbracoContextAccessor _umbracoContextAccessor; private WebRoutingSettings _webRoutingSettings; + /// protected override string FailureLogMessageTemplate => "Not a node key"; /// diff --git a/src/Umbraco.Core/Routing/ContentFinderCollection.cs b/src/Umbraco.Core/Routing/ContentFinderCollection.cs index cc3b711d9882..3de5a59d41a2 100644 --- a/src/Umbraco.Core/Routing/ContentFinderCollection.cs +++ b/src/Umbraco.Core/Routing/ContentFinderCollection.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Represents a collection of instances. +/// public class ContentFinderCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the content finders. public ContentFinderCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/Routing/ContentFinderCollectionBuilder.cs b/src/Umbraco.Core/Routing/ContentFinderCollectionBuilder.cs index 3c8a0e925d22..3015a41252b4 100644 --- a/src/Umbraco.Core/Routing/ContentFinderCollectionBuilder.cs +++ b/src/Umbraco.Core/Routing/ContentFinderCollectionBuilder.cs @@ -1,8 +1,12 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.Routing; +/// +/// Builds a by registering implementations. +/// public class ContentFinderCollectionBuilder : OrderedCollectionBuilderBase { + /// protected override ContentFinderCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/Routing/DefaultMediaUrlProvider.cs b/src/Umbraco.Core/Routing/DefaultMediaUrlProvider.cs index 1f0b59f71a44..60c30791f464 100644 --- a/src/Umbraco.Core/Routing/DefaultMediaUrlProvider.cs +++ b/src/Umbraco.Core/Routing/DefaultMediaUrlProvider.cs @@ -11,6 +11,11 @@ public class DefaultMediaUrlProvider : IMediaUrlProvider private readonly MediaUrlGeneratorCollection _mediaPathGenerators; private readonly IUrlAssembler _urlAssembler; + /// + /// Initializes a new instance of the class. + /// + /// The media path generators. + /// The URL assembler. public DefaultMediaUrlProvider(MediaUrlGeneratorCollection mediaPathGenerators, IUrlAssembler urlAssembler) { _mediaPathGenerators = mediaPathGenerators; diff --git a/src/Umbraco.Core/Routing/DefaultUrlAssembler.cs b/src/Umbraco.Core/Routing/DefaultUrlAssembler.cs index 25c1ce3e32da..ace6f66e5891 100644 --- a/src/Umbraco.Core/Routing/DefaultUrlAssembler.cs +++ b/src/Umbraco.Core/Routing/DefaultUrlAssembler.cs @@ -2,12 +2,20 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Provides the default implementation of . +/// public class DefaultUrlAssembler : IUrlAssembler { private readonly UriUtility _uriUtility; -public DefaultUrlAssembler(UriUtility uriUtility) => _uriUtility = uriUtility; + /// + /// Initializes a new instance of the class. + /// + /// The URI utility. + public DefaultUrlAssembler(UriUtility uriUtility) => _uriUtility = uriUtility; + /// public Uri AssembleUrl(string path, Uri current, UrlMode mode) { if (string.IsNullOrWhiteSpace(path)) diff --git a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs index bbbffbc2913f..79959abf3bbe 100644 --- a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs +++ b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs @@ -186,6 +186,16 @@ public virtual IEnumerable GetOtherUrls(int id, Uri current) return GetUrlFromRoute(route, umbracoContext, content.Id, current, mode, culture); } + /// + /// Gets a URL info from a route string. + /// + /// The route string. + /// The Umbraco context. + /// The content ID. + /// The current URI. + /// The URL mode. + /// The culture. + /// The URL info, or null if the route could not be resolved. internal UrlInfo? GetUrlFromRoute( string? route, IUmbracoContext umbracoContext, diff --git a/src/Umbraco.Core/Routing/DomainAndUri.cs b/src/Umbraco.Core/Routing/DomainAndUri.cs index c5f9497d77b2..038108cd1202 100644 --- a/src/Umbraco.Core/Routing/DomainAndUri.cs +++ b/src/Umbraco.Core/Routing/DomainAndUri.cs @@ -43,5 +43,6 @@ public DomainAndUri(Domain domain, Uri currentUri) /// public Uri Uri { get; } + /// public override string ToString() => $"{{ \"{Name}\", \"{Uri}\" }}"; } diff --git a/src/Umbraco.Core/Routing/IPublishedUrlInfoProvider.cs b/src/Umbraco.Core/Routing/IPublishedUrlInfoProvider.cs index aa3d322381ff..7a62697aa79b 100644 --- a/src/Umbraco.Core/Routing/IPublishedUrlInfoProvider.cs +++ b/src/Umbraco.Core/Routing/IPublishedUrlInfoProvider.cs @@ -1,7 +1,10 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Routing; +/// +/// Provides URL information for published content items. +/// public interface IPublishedUrlInfoProvider { /// diff --git a/src/Umbraco.Core/Routing/IPublishedUrlProvider.cs b/src/Umbraco.Core/Routing/IPublishedUrlProvider.cs index a9bbe155c370..0086f18f04e2 100644 --- a/src/Umbraco.Core/Routing/IPublishedUrlProvider.cs +++ b/src/Umbraco.Core/Routing/IPublishedUrlProvider.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Provides URLs for published content and media items. +/// public interface IPublishedUrlProvider { /// @@ -48,6 +51,13 @@ public interface IPublishedUrlProvider /// string GetUrl(IPublishedContent content, UrlMode mode = UrlMode.Default, string? culture = null, Uri? current = null); + /// + /// Gets the url of a published content from a route. + /// + /// The published content identifier. + /// The route. + /// A culture. + /// The url for the published content. string GetUrlFromRoute(int id, string? route, string? culture); /// diff --git a/src/Umbraco.Core/Routing/IUrlAssembler.cs b/src/Umbraco.Core/Routing/IUrlAssembler.cs index c56b216e7003..766e46920b4c 100644 --- a/src/Umbraco.Core/Routing/IUrlAssembler.cs +++ b/src/Umbraco.Core/Routing/IUrlAssembler.cs @@ -2,7 +2,17 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Provides URL assembly functionality for constructing URLs from path components. +/// public interface IUrlAssembler { + /// + /// Assembles a URL from the specified path, current URI, and URL mode. + /// + /// The path component of the URL. + /// The current request URI. + /// The URL mode determining how the URL should be formatted. + /// The assembled . Uri AssembleUrl(string path, Uri current, UrlMode mode); } diff --git a/src/Umbraco.Core/Routing/MediaUrlProviderCollection.cs b/src/Umbraco.Core/Routing/MediaUrlProviderCollection.cs index 85b864d717be..597a7d27d433 100644 --- a/src/Umbraco.Core/Routing/MediaUrlProviderCollection.cs +++ b/src/Umbraco.Core/Routing/MediaUrlProviderCollection.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Represents a collection of instances. +/// public class MediaUrlProviderCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the media URL providers. public MediaUrlProviderCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/Routing/MediaUrlProviderCollectionBuilder.cs b/src/Umbraco.Core/Routing/MediaUrlProviderCollectionBuilder.cs index ba0a9b9fc238..249bc2a71343 100644 --- a/src/Umbraco.Core/Routing/MediaUrlProviderCollectionBuilder.cs +++ b/src/Umbraco.Core/Routing/MediaUrlProviderCollectionBuilder.cs @@ -1,8 +1,12 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.Routing; +/// +/// Builds a by registering implementations. +/// public class MediaUrlProviderCollectionBuilder : OrderedCollectionBuilderBase { + /// protected override MediaUrlProviderCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/Routing/PublishedRequest.cs b/src/Umbraco.Core/Routing/PublishedRequest.cs index f3ef192feca3..e9c4b93303a4 100644 --- a/src/Umbraco.Core/Routing/PublishedRequest.cs +++ b/src/Umbraco.Core/Routing/PublishedRequest.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Represents the result of Umbraco routing, containing all information needed to render a published content item. +/// public class PublishedRequest : IPublishedRequest { /// diff --git a/src/Umbraco.Core/Routing/PublishedRequestBuilder.cs b/src/Umbraco.Core/Routing/PublishedRequestBuilder.cs index c89fa616cd81..248e32e577bb 100644 --- a/src/Umbraco.Core/Routing/PublishedRequestBuilder.cs +++ b/src/Umbraco.Core/Routing/PublishedRequestBuilder.cs @@ -6,6 +6,9 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Provides a builder for constructing instances during the routing process. +/// public class PublishedRequestBuilder : IPublishedRequestBuilder { private readonly IFileService _fileService; diff --git a/src/Umbraco.Core/Routing/PublishedRequestExtensions.cs b/src/Umbraco.Core/Routing/PublishedRequestExtensions.cs index 6b9720e4ace2..8a6e69fe5846 100644 --- a/src/Umbraco.Core/Routing/PublishedRequestExtensions.cs +++ b/src/Umbraco.Core/Routing/PublishedRequestExtensions.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Provides extension methods for and . +/// public static class PublishedRequestExtensions { /// diff --git a/src/Umbraco.Core/Routing/PublishedRouter.cs b/src/Umbraco.Core/Routing/PublishedRouter.cs index 472fe4712229..3329d05e4da1 100644 --- a/src/Umbraco.Core/Routing/PublishedRouter.cs +++ b/src/Umbraco.Core/Routing/PublishedRouter.cs @@ -433,6 +433,13 @@ internal void HandleWildcardDomains(IPublishedRequestBuilder request) } } + /// + /// Finds a template rendering engine in the specified directory. + /// + /// The directory to search. + /// The template alias. + /// The file extensions to search for. + /// true if the template was found; otherwise, false. internal bool FindTemplateRenderingEngineInDirectory(DirectoryInfo? directory, string alias, string[] extensions) { if (directory == null || directory.Exists == false) diff --git a/src/Umbraco.Core/Routing/PublishedUrlInfoProvider.cs b/src/Umbraco.Core/Routing/PublishedUrlInfoProvider.cs index 0e1fbffab69b..367969999bd2 100644 --- a/src/Umbraco.Core/Routing/PublishedUrlInfoProvider.cs +++ b/src/Umbraco.Core/Routing/PublishedUrlInfoProvider.cs @@ -8,6 +8,9 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Provides the default implementation of . +/// public class PublishedUrlInfoProvider : IPublishedUrlInfoProvider { private const string UrlProviderAlias = Constants.UrlProviders.Content; @@ -21,6 +24,17 @@ public class PublishedUrlInfoProvider : IPublishedUrlInfoProvider private readonly UriUtility _uriUtility; private readonly IVariationContextAccessor _variationContextAccessor; + /// + /// Initializes a new instance of the class. + /// + /// The published URL provider. + /// The language service. + /// The published router. + /// The Umbraco context accessor. + /// The localized text service. + /// The logger. + /// The URI utility. + /// The variation context accessor. public PublishedUrlInfoProvider( IPublishedUrlProvider publishedUrlProvider, ILanguageService languageService, diff --git a/src/Umbraco.Core/Routing/SiteDomainMapper.cs b/src/Umbraco.Core/Routing/SiteDomainMapper.cs index 496bd6fe437c..aff1c1315609 100644 --- a/src/Umbraco.Core/Routing/SiteDomainMapper.cs +++ b/src/Umbraco.Core/Routing/SiteDomainMapper.cs @@ -8,10 +8,15 @@ namespace Umbraco.Cms.Core.Routing /// public class SiteDomainMapper : ISiteDomainMapper, IDisposable { + /// public void Dispose() => // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method Dispose(true); + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (!_disposedValue) @@ -33,7 +38,14 @@ protected virtual void Dispose(bool disposing) private Dictionary>? _qualifiedSites; private bool _disposedValue; + /// + /// Gets the dictionary of sites, mapping site keys to their domain URLs. + /// internal Dictionary? Sites { get; private set; } + + /// + /// Gets the dictionary of site bindings, mapping site keys to lists of bound site keys. + /// internal Dictionary>? Bindings { get; private set; } // these are for validation diff --git a/src/Umbraco.Core/Routing/UmbracoRequestPathsOptions.cs b/src/Umbraco.Core/Routing/UmbracoRequestPathsOptions.cs index 91f13eab3bc2..03618e4738a2 100644 --- a/src/Umbraco.Core/Routing/UmbracoRequestPathsOptions.cs +++ b/src/Umbraco.Core/Routing/UmbracoRequestPathsOptions.cs @@ -1,5 +1,8 @@ -namespace Umbraco.Cms.Core.Routing; +namespace Umbraco.Cms.Core.Routing; +/// +/// Provides options for configuring . +/// public class UmbracoRequestPathsOptions { /// diff --git a/src/Umbraco.Core/Routing/UmbracoRouteResult.cs b/src/Umbraco.Core/Routing/UmbracoRouteResult.cs index 67690e11e8b8..56adae309a29 100644 --- a/src/Umbraco.Core/Routing/UmbracoRouteResult.cs +++ b/src/Umbraco.Core/Routing/UmbracoRouteResult.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Represents the result of routing an Umbraco request. +/// public enum UmbracoRouteResult { /// diff --git a/src/Umbraco.Core/Routing/UriUtility.cs b/src/Umbraco.Core/Routing/UriUtility.cs index c6920d7733e7..34459e34eaae 100644 --- a/src/Umbraco.Core/Routing/UriUtility.cs +++ b/src/Umbraco.Core/Routing/UriUtility.cs @@ -5,11 +5,18 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Provides utilities for manipulating URIs in the Umbraco routing context. +/// public sealed class UriUtility { private static string? _appPath; private static string? _appPathPrefix; + /// + /// Initializes a new instance of the class. + /// + /// The hosting environment. public UriUtility(IHostingEnvironment hostingEnvironment) { if (hostingEnvironment is null) @@ -20,15 +27,21 @@ public UriUtility(IHostingEnvironment hostingEnvironment) ResetAppDomainAppVirtualPath(hostingEnvironment); } - // will be "/" or "/foo" + /// + /// Gets the application path. Will be "/" or "/foo". + /// public string? AppPath => _appPath; - // will be "" or "/foo" + /// + /// Gets the application path prefix. Will be "" or "/foo". + /// public string? AppPathPrefix => _appPathPrefix; - // adds the virtual directory if any - // see also VirtualPathUtility.ToAbsolute - // TODO: Does this do anything differently than IHostingEnvironment.ToAbsolute? Seems it does less, maybe should be removed? + /// + /// Converts a relative URL to an absolute URL by prepending the application path prefix. + /// + /// The relative URL. + /// The absolute URL with the application path prefix. public string ToAbsolute(string url) { // return ResolveUrl(url); @@ -36,7 +49,10 @@ public string ToAbsolute(string url) return _appPathPrefix + url; } - // internal for unit testing only + /// + /// Sets the application virtual path. Internal for unit testing only. + /// + /// The application path to set. internal void SetAppDomainAppVirtualPath(string appPath) { _appPath = appPath ?? "/"; @@ -47,11 +63,18 @@ internal void SetAppDomainAppVirtualPath(string appPath) } } + /// + /// Resets the application virtual path from the hosting environment. + /// + /// The hosting environment. internal void ResetAppDomainAppVirtualPath(IHostingEnvironment hostingEnvironment) => SetAppDomainAppVirtualPath(hostingEnvironment.ApplicationVirtualPath); - // strips the virtual directory if any - // see also VirtualPathUtility.ToAppRelative + /// + /// Converts a virtual path to an application-relative path by stripping the virtual directory if present. + /// + /// The virtual path. + /// The application-relative path. public string ToAppRelative(string virtualPath) { if (_appPathPrefix is not null && virtualPath.InvariantStartsWith(_appPathPrefix) @@ -69,8 +92,12 @@ public string ToAppRelative(string virtualPath) return virtualPath; } - // maps an internal umbraco uri to a public uri - // ie with virtual directory, .aspx if required... + /// + /// Maps an internal Umbraco URI to a public URI with virtual directory and appropriate suffixes. + /// + /// The internal Umbraco URI. + /// The request handler settings. + /// The public URI. public Uri UriFromUmbraco(Uri uri, RequestHandlerSettings requestConfig) { var path = uri.GetSafeAbsolutePath(); @@ -85,8 +112,11 @@ public Uri UriFromUmbraco(Uri uri, RequestHandlerSettings requestConfig) return uri.Rewrite(path); } - // maps a media umbraco uri to a public uri - // ie with virtual directory - that is all for media + /// + /// Maps a media Umbraco URI to a public URI with virtual directory. + /// + /// The media URI. + /// The public media URI. public Uri MediaUriFromUmbraco(Uri uri) { var path = uri.GetSafeAbsolutePath(); @@ -94,8 +124,11 @@ public Uri MediaUriFromUmbraco(Uri uri) return uri.Rewrite(path); } - // maps a public uri to an internal umbraco uri - // ie no virtual directory, no .aspx, lowercase... + /// + /// Maps a public URI to an internal Umbraco URI without virtual directory, lowercased. + /// + /// The public URI. + /// The internal Umbraco URI. public Uri UriToUmbraco(Uri uri) { // TODO: This is critical code that executes on every request, we should @@ -124,11 +157,15 @@ public Uri UriToUmbraco(Uri uri) #region ResolveUrl - // http://www.codeproject.com/Articles/53460/ResolveUrl-in-ASP-NET-The-Perfect-Solution - // note - // if browsing http://example.com/sub/page1.aspx then - // ResolveUrl("page2.aspx") returns "/page2.aspx" - // Page.ResolveUrl("page2.aspx") returns "/sub/page2.aspx" (relative...) + /// + /// Resolves a relative URL to an absolute URL. + /// + /// The relative URL to resolve. + /// The resolved URL. + /// + /// If browsing http://example.com/sub/page1.aspx then + /// ResolveUrl("page2.aspx") returns "/page2.aspx". + /// public string ResolveUrl(string relativeUrl) { if (relativeUrl == null) diff --git a/src/Umbraco.Core/Routing/UrlInfo.cs b/src/Umbraco.Core/Routing/UrlInfo.cs index e9137a3aaa72..d46db647ff6b 100644 --- a/src/Umbraco.Core/Routing/UrlInfo.cs +++ b/src/Umbraco.Core/Routing/UrlInfo.cs @@ -47,12 +47,35 @@ public UrlInfo(string message, string provider, string? culture = null) Culture = culture; } + /// + /// Creates a instance representing an actual URL. + /// + /// The URL string. + /// The name of the URL provider. + /// The optional culture. + /// A value indicating whether the URL is external. + /// A new instance. public static UrlInfo AsUrl(string url, string provider, string? culture = null, bool isExternal = false) => new(new Uri(url, UriKind.RelativeOrAbsolute), provider, culture: culture, isExternal: isExternal); + /// + /// Creates a instance representing a message (not an actual URL). + /// + /// The message. + /// The name of the URL provider. + /// The optional culture. + /// A new instance. public static UrlInfo AsMessage(string message, string provider, string? culture = null) => new(message, provider, culture: culture); + /// + /// Creates a instance from a . + /// + /// The URI. + /// The name of the URL provider. + /// The optional culture. + /// A value indicating whether the URL is external. + /// A new instance. public static UrlInfo FromUri(Uri uri, string provider, string? culture = null, bool isExternal = false) => new(uri, provider, culture: culture, isExternal: isExternal); @@ -68,6 +91,9 @@ public static UrlInfo FromUri(Uri uri, string provider, string? culture = null, [DataMember(Name = "url")] public Uri? Url { get; } + /// + /// Gets the name of the URL provider that generated this URL info. + /// public string Provider { get; } /// @@ -82,6 +108,12 @@ public static UrlInfo FromUri(Uri uri, string provider, string? culture = null, [DataMember(Name = "isExternal")] public bool IsExternal { get; } + /// + /// Determines whether two specified objects have the same value. + /// + /// The first to compare. + /// The second to compare. + /// true if the value of is the same as the value of ; otherwise, false. public static bool operator ==(UrlInfo left, UrlInfo right) => Equals(left, right); /// @@ -107,6 +139,7 @@ public bool Equals(UrlInfo? other) && IsExternal == other.IsExternal; } + /// public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) @@ -127,6 +160,7 @@ public override bool Equals(object? obj) return Equals((UrlInfo)obj); } + /// public override int GetHashCode() { unchecked @@ -141,7 +175,14 @@ public override int GetHashCode() } } + /// + /// Determines whether two specified objects have different values. + /// + /// The first to compare. + /// The second to compare. + /// true if the value of is different from the value of ; otherwise, false. public static bool operator !=(UrlInfo left, UrlInfo right) => !Equals(left, right); + /// public override string ToString() => Url?.ToString() ?? Message ?? "[empty]"; } diff --git a/src/Umbraco.Core/Routing/UrlProvider.cs b/src/Umbraco.Core/Routing/UrlProvider.cs index cdc2584609b2..c52947e4312a 100644 --- a/src/Umbraco.Core/Routing/UrlProvider.cs +++ b/src/Umbraco.Core/Routing/UrlProvider.cs @@ -147,6 +147,7 @@ public string GetUrl(IPublishedContent? content, UrlMode mode = UrlMode.Default, return url?.Url?.ToString() ?? "#"; // legacy wants this } + /// public string GetUrlFromRoute(int id, string? route, string? culture) { IUmbracoContext umbracoContext = _umbracoContextAccessor.GetRequiredUmbracoContext(); diff --git a/src/Umbraco.Core/Routing/UrlProviderCollection.cs b/src/Umbraco.Core/Routing/UrlProviderCollection.cs index 0acb75264d10..8d9ee88fadcc 100644 --- a/src/Umbraco.Core/Routing/UrlProviderCollection.cs +++ b/src/Umbraco.Core/Routing/UrlProviderCollection.cs @@ -2,8 +2,15 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Represents a collection of instances. +/// public class UrlProviderCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the URL providers. public UrlProviderCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/Routing/UrlProviderCollectionBuilder.cs b/src/Umbraco.Core/Routing/UrlProviderCollectionBuilder.cs index fe975272dde3..8cc7ab075852 100644 --- a/src/Umbraco.Core/Routing/UrlProviderCollectionBuilder.cs +++ b/src/Umbraco.Core/Routing/UrlProviderCollectionBuilder.cs @@ -1,8 +1,12 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.Routing; +/// +/// Builds a by registering implementations. +/// public class UrlProviderCollectionBuilder : OrderedCollectionBuilderBase { + /// protected override UrlProviderCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/Routing/UrlProviderExtensions.cs b/src/Umbraco.Core/Routing/UrlProviderExtensions.cs index f98867ae1c11..1a9ea5925653 100644 --- a/src/Umbraco.Core/Routing/UrlProviderExtensions.cs +++ b/src/Umbraco.Core/Routing/UrlProviderExtensions.cs @@ -10,6 +10,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for URL generation and retrieval operations on content. +/// public static class UrlProviderExtensions { private const string UrlProviderAlias = Constants.UrlProviders.Content; diff --git a/src/Umbraco.Core/Routing/WebPath.cs b/src/Umbraco.Core/Routing/WebPath.cs index 47c6b158718d..0aef56844a34 100644 --- a/src/Umbraco.Core/Routing/WebPath.cs +++ b/src/Umbraco.Core/Routing/WebPath.cs @@ -2,10 +2,22 @@ namespace Umbraco.Cms.Core.Routing; +/// +/// Provides utilities for manipulating web paths. +/// public class WebPath { + /// + /// The path separator character. + /// public const char PathSeparator = '/'; + /// + /// Combines multiple path segments into a single path. + /// + /// The path segments to combine. + /// The combined path. + /// Thrown when is null. public static string Combine(params string[]? paths) { if (paths == null) diff --git a/src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs b/src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs index 08672c116446..d981c23470e6 100644 --- a/src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs +++ b/src/Umbraco.Core/Runtime/EssentialDirectoryCreator.cs @@ -7,12 +7,25 @@ namespace Umbraco.Cms.Core.Runtime; +/// +/// Handles the creation of essential directories during application startup. +/// +/// +/// This notification handler ensures that required directories (Data, Media, Views, PartialViews) +/// exist before other components initialize, providing a safe environment for the application to run. +/// public class EssentialDirectoryCreator : INotificationHandler { private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IIOHelper _ioHelper; + /// + /// Initializes a new instance of the class. + /// + /// The I/O helper for directory operations. + /// The hosting environment for path resolution. + /// The global settings options. public EssentialDirectoryCreator(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, IOptions globalSettings) { _ioHelper = ioHelper; @@ -20,6 +33,7 @@ public EssentialDirectoryCreator(IIOHelper ioHelper, IHostingEnvironment hosting _globalSettings = globalSettings.Value; } + /// public void Handle(UmbracoApplicationStartingNotification notification) { // ensure we have some essential directories diff --git a/src/Umbraco.Core/Runtime/IUmbracoBootPermissionChecker.cs b/src/Umbraco.Core/Runtime/IUmbracoBootPermissionChecker.cs index b5c43cde4acf..bb02d9f2516b 100644 --- a/src/Umbraco.Core/Runtime/IUmbracoBootPermissionChecker.cs +++ b/src/Umbraco.Core/Runtime/IUmbracoBootPermissionChecker.cs @@ -1,6 +1,19 @@ namespace Umbraco.Cms.Core.Runtime; +/// +/// Provides permission checking for Umbraco boot operations. +/// +/// +/// Implementations of this interface verify that the application has the necessary +/// permissions to start up correctly, such as file system access. +/// public interface IUmbracoBootPermissionChecker { + /// + /// Throws an exception if the application does not have the required permissions to boot. + /// + /// + /// Thrown when the application lacks required permissions for startup. + /// void ThrowIfNotPermissions(); } diff --git a/src/Umbraco.Core/Runtime/MainDom.cs b/src/Umbraco.Core/Runtime/MainDom.cs index 4d4c7ab2e804..090625045491 100644 --- a/src/Umbraco.Core/Runtime/MainDom.cs +++ b/src/Umbraco.Core/Runtime/MainDom.cs @@ -41,7 +41,11 @@ public class MainDom : IMainDom, IRegisteredObject, IDisposable #region Ctor - // initializes a new instance of MainDom + /// + /// Initializes a new instance of the class. + /// + /// The logger instance. + /// The distributed lock implementation. public MainDom(ILogger logger, IMainDomLock systemLock) { _logger = logger; @@ -62,15 +66,7 @@ public bool Acquire(IApplicationShutdownRegistry hostingEnvironment) })!.Value; } - /// - /// Registers a resource that requires the current AppDomain to be the main domain to function. - /// - /// An action to execute when registering. - /// An action to execute before the AppDomain releases the main domain status. - /// An optional weight (lower goes first). - /// A value indicating whether it was possible to register. - /// If registering is successful, then the action - /// is guaranteed to execute before the AppDomain releases the main domain status. + /// public bool Register(Action? install = null, Action? release = null, int weight = 100) { lock (_locko) @@ -226,12 +222,7 @@ private bool Acquire() return true; } - /// - /// Gets a value indicating whether the current domain is the main domain. - /// - /// - /// Acquire must be called first else this will always return false - /// + /// public bool IsMainDom { get @@ -244,7 +235,7 @@ public bool IsMainDom } } - // IRegisteredObject + /// void IRegisteredObject.Stop(bool immediate) { OnSignal("environment"); // will run once @@ -257,10 +248,12 @@ void IRegisteredObject.Stop(bool immediate) #region IDisposable Support - // This code added to correctly implement the disposable pattern. - private bool _disposedValue; // To detect redundant calls + /// + /// Releases the unmanaged resources used by the and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (!_disposedValue) @@ -274,6 +267,7 @@ protected virtual void Dispose(bool disposing) } } + /// public void Dispose() { Dispose(true); @@ -281,6 +275,15 @@ public void Dispose() #endregion + /// + /// Gets a unique identifier for the main domain based on the hosting environment. + /// + /// The hosting environment. + /// A SHA1 hash that uniquely identifies this application instance. + /// + /// The ID is generated from the application ID and physical path to ensure uniqueness + /// across multiple sites running on the same server. + /// public static string GetMainDomId(IHostingEnvironment hostingEnvironment) { // HostingEnvironment.ApplicationID is null in unit tests, making ReplaceNonAlphanumericChars fail diff --git a/src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs b/src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs index cdfd7b9305fa..03eeab85ebbe 100644 --- a/src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs +++ b/src/Umbraco.Core/Runtime/MainDomSemaphoreLock.cs @@ -18,6 +18,12 @@ public class MainDomSemaphoreLock : IMainDomLock private readonly SystemLock _systemLock; private IDisposable? _lockRelease; + /// + /// Initializes a new instance of the class. + /// + /// The logger instance. + /// The hosting environment for generating lock names. + /// Thrown when not running on Windows. public MainDomSemaphoreLock(ILogger logger, IHostingEnvironment hostingEnvironment) { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -34,9 +40,14 @@ public MainDomSemaphoreLock(ILogger logger, IHostingEnviro _logger = logger; } - // WaitOneAsync (ext method) will wait for a signal without blocking the main thread, the waiting is done on a background thread + /// + /// + /// WaitOneAsync (extension method) will wait for a signal without blocking the main thread; + /// the waiting is done on a background thread. + /// public Task ListenAsync() => _signal.WaitOneAsync(); + /// public Task AcquireLockAsync(int millisecondsTimeout) { // signal other instances that we want the lock, then wait on the lock, @@ -75,6 +86,10 @@ public Task AcquireLockAsync(int millisecondsTimeout) private bool disposedValue; // To detect redundant calls + /// + /// Releases the unmanaged resources used by the and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (!disposedValue) @@ -90,9 +105,8 @@ protected virtual void Dispose(bool disposing) } } - // This code added to correctly implement the disposable pattern. + /// public void Dispose() => - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. Dispose(true); diff --git a/src/Umbraco.Core/Scoping/CoreScope.cs b/src/Umbraco.Core/Scoping/CoreScope.cs index 6d956c050ead..a81f70df2656 100644 --- a/src/Umbraco.Core/Scoping/CoreScope.cs +++ b/src/Umbraco.Core/Scoping/CoreScope.cs @@ -6,9 +6,21 @@ namespace Umbraco.Cms.Core.Scoping; +/// +/// Represents a core scope that manages transactional operations, caching, locking, and notifications. +/// +/// +/// Scopes can be nested; a child scope must be completed before its parent. +/// The scope manages file system scoping, isolated caches, and notification publishing. +/// public class CoreScope : ICoreScope { - // TODO (V18): Rename to _completed to comply with SA1306 (field names should begin with lowercase), or consider converting to a property. + /// + /// Indicates whether the scope has been completed. + /// + /// + /// TODO (V18): Rename to _completed to comply with SA1306 (field names should begin with lowercase), or consider converting to a property. + /// protected bool? Completed; private ICompletable? _scopedFileSystem; private IScopedNotificationPublisher? _notificationPublisher; @@ -21,6 +33,16 @@ public class CoreScope : ICoreScope private bool _disposed; + /// + /// Initializes a new instance of the class as a root scope. + /// + /// The factory for creating distributed locking mechanisms. + /// The logger factory for creating loggers. + /// The file systems to potentially scope. + /// The event aggregator for publishing notifications. + /// The repository cache mode for this scope. + /// A value indicating whether to scope the file systems. + /// An optional scoped notification publisher. protected CoreScope( IDistributedLockingMechanismFactory distributedLockingMechanismFactory, ILoggerFactory loggerFactory, @@ -46,6 +68,22 @@ protected CoreScope( } } + /// + /// Initializes a new instance of the class with an optional parent scope. + /// + /// The parent scope, or null if this is a root scope. + /// The factory for creating distributed locking mechanisms. + /// The logger factory for creating loggers. + /// The file systems to potentially scope. + /// The event aggregator for publishing notifications. + /// The repository cache mode for this scope. + /// A value indicating whether to scope the file systems. + /// An optional scoped notification publisher. + /// + /// Thrown when the repository cache mode is lower than the parent's mode, + /// when a notification publisher is specified on a nested scope, + /// or when the file system scoping differs from the parent. + /// protected CoreScope( ICoreScope? parentScope, IDistributedLockingMechanismFactory distributedLockingMechanismFactory, @@ -104,8 +142,12 @@ protected CoreScope( } } + /// + /// Gets the parent scope as a . + /// private CoreScope? ParentScope => (CoreScope?)_parentScope; + /// public int Depth { get @@ -119,12 +161,16 @@ public int Depth } } + /// public Guid InstanceId { get; } + /// public int CreatedThreadId { get; } + /// public ILockingMechanism Locks { get; } + /// public IScopedNotificationPublisher Notifications { get @@ -139,6 +185,7 @@ public IScopedNotificationPublisher Notifications } } + /// public RepositoryCacheMode RepositoryCacheMode { get @@ -152,6 +199,7 @@ public RepositoryCacheMode RepositoryCacheMode } } + /// public IsolatedCaches IsolatedCaches { get @@ -165,6 +213,9 @@ public IsolatedCaches IsolatedCaches } } + /// + /// Gets a value indicating whether file systems are scoped for this scope. + /// public bool ScopedFileSystems { get @@ -192,22 +243,33 @@ public bool Complete() return Completed.Value; } + /// public void ReadLock(params int[] lockIds) => Locks.ReadLock(InstanceId, null, lockIds); + /// public void WriteLock(params int[] lockIds) => Locks.WriteLock(InstanceId, null, lockIds); + /// public void WriteLock(TimeSpan timeout, int lockId) => Locks.ReadLock(InstanceId, timeout, lockId); + /// public void ReadLock(TimeSpan timeout, int lockId) => Locks.WriteLock(InstanceId, timeout, lockId); + /// public void EagerWriteLock(params int[] lockIds) => Locks.EagerWriteLock(InstanceId, null, lockIds); + /// public void EagerWriteLock(TimeSpan timeout, int lockId) => Locks.EagerWriteLock(InstanceId, timeout, lockId); + /// public void EagerReadLock(TimeSpan timeout, int lockId) => Locks.EagerReadLock(InstanceId, timeout, lockId); + /// public void EagerReadLock(params int[] lockIds) => Locks.EagerReadLock(InstanceId, TimeSpan.Zero, lockIds); + /// + /// Disposes the scope, handling file systems, notifications, and parent scope completion. + /// public virtual void Dispose() { if (ParentScope is null) @@ -223,6 +285,10 @@ public virtual void Dispose() _disposed = true; } + /// + /// Called when a child scope has completed, to update the parent's completion status. + /// + /// A value indicating whether the child completed successfully. protected void ChildCompleted(bool? completed) { // if child did not complete we cannot complete @@ -232,6 +298,9 @@ protected void ChildCompleted(bool? completed) } } + /// + /// Handles the completion and disposal of scoped file systems. + /// protected void HandleScopedFileSystems() { if (_shouldScopeFileSystems == true) @@ -246,15 +315,29 @@ protected void HandleScopedFileSystems() } } + /// + /// Sets the parent scope for this scope. + /// + /// The parent scope to set. protected void SetParentScope(ICoreScope coreScope) { _parentScope = coreScope; } + /// + /// Gets a value indicating whether this scope has a parent scope. + /// protected bool HasParentScope => _parentScope is not null; + /// + /// Handles the scoped notifications when the scope exits. + /// protected void HandleScopedNotifications() => _notificationPublisher?.ScopeExit(Completed.HasValue && Completed.Value); + /// + /// Ensures that this scope and all ancestor scopes have not been disposed. + /// + /// Thrown when the scope has already been disposed. private void EnsureNotDisposed() { // We can't be disposed @@ -270,6 +353,10 @@ private void EnsureNotDisposed() ParentScope?.EnsureNotDisposed(); } + /// + /// Resolves the locking mechanism, traversing up the parent chain if necessary. + /// + /// The locking mechanism for this scope hierarchy. private ILockingMechanism ResolveLockingMechanism() => ParentScope is not null ? ParentScope.ResolveLockingMechanism() : Locks; } diff --git a/src/Umbraco.Core/Scoping/ICoreScope.cs b/src/Umbraco.Core/Scoping/ICoreScope.cs index 713ecc795474..d18bbdb7d1db 100644 --- a/src/Umbraco.Core/Scoping/ICoreScope.cs +++ b/src/Umbraco.Core/Scoping/ICoreScope.cs @@ -16,6 +16,9 @@ public interface ICoreScope : IDisposable, IInstanceIdentifiable /// public int Depth => -1; + /// + /// Gets the locking mechanism for this scope. + /// public ILockingMechanism Locks { get; } /// @@ -66,11 +69,29 @@ public interface ICoreScope : IDisposable, IInstanceIdentifiable /// The lock object identifier. void ReadLock(TimeSpan timeout, int lockId); + /// + /// Eagerly acquires write locks on the specified lock objects. + /// + /// Array of lock object identifiers. void EagerWriteLock(params int[] lockIds); + /// + /// Eagerly acquires a write lock on a lock object with a timeout. + /// + /// The database timeout. + /// The lock object identifier. void EagerWriteLock(TimeSpan timeout, int lockId); + /// + /// Eagerly acquires a read lock on a lock object with a timeout. + /// + /// The database timeout. + /// The lock object identifier. void EagerReadLock(TimeSpan timeout, int lockId); + /// + /// Eagerly acquires read locks on the specified lock objects. + /// + /// Array of lock object identifiers. void EagerReadLock(params int[] lockIds); } diff --git a/src/Umbraco.Core/Scoping/IInstanceIdentifiable.cs b/src/Umbraco.Core/Scoping/IInstanceIdentifiable.cs index 1942ecdc43e2..57ef4fda8567 100644 --- a/src/Umbraco.Core/Scoping/IInstanceIdentifiable.cs +++ b/src/Umbraco.Core/Scoping/IInstanceIdentifiable.cs @@ -10,5 +10,8 @@ public interface IInstanceIdentifiable /// Guid InstanceId { get; } + /// + /// Gets the managed thread ID on which this instance was created. + /// int CreatedThreadId { get; } } diff --git a/src/Umbraco.Core/Scoping/ILockingMechanism.cs b/src/Umbraco.Core/Scoping/ILockingMechanism.cs index 449c4a01edda..ed01faf114b2 100644 --- a/src/Umbraco.Core/Scoping/ILockingMechanism.cs +++ b/src/Umbraco.Core/Scoping/ILockingMechanism.cs @@ -1,5 +1,12 @@ namespace Umbraco.Cms.Core.Scoping; +/// +/// Defines a mechanism for acquiring and managing read and write locks on resources. +/// +/// +/// Locks can be acquired lazily (deferred until actually needed) or eagerly (immediately). +/// The mechanism tracks locks by scope instance ID to support nested scopes. +/// public interface ILockingMechanism : IDisposable { /// @@ -10,16 +17,26 @@ public interface ILockingMechanism : IDisposable /// Array of lock object identifiers. void ReadLock(Guid instanceId, TimeSpan? timeout = null, params int[] lockIds); + /// + /// Read-locks some lock objects lazily using the default timeout. + /// + /// Instance id of the scope who is requesting the lock. + /// Array of lock object identifiers. void ReadLock(Guid instanceId, params int[] lockIds); /// /// Write-locks some lock objects lazily. /// - /// Instance id of the scope who is requesting the lock - /// Timeout for the lock + /// Instance id of the scope who is requesting the lock. + /// Timeout for the lock. /// Array of object identifiers. void WriteLock(Guid instanceId, TimeSpan? timeout = null, params int[] lockIds); + /// + /// Write-locks some lock objects lazily using the default timeout. + /// + /// Instance id of the scope who is requesting the lock. + /// Array of object identifiers. void WriteLock(Guid instanceId, params int[] lockIds); /// @@ -30,33 +47,56 @@ public interface ILockingMechanism : IDisposable /// void EagerReadLock(Guid instanceId, TimeSpan? timeout = null, params int[] lockIds); + /// + /// Eagerly acquires a read-lock using the default timeout. + /// + /// Instance id of the scope who is requesting the lock. + /// Array of lock object identifiers. void EagerReadLock(Guid instanceId, params int[] lockIds); /// - /// Eagerly acquires a write-lock + /// Eagerly acquires a write-lock. /// - /// - /// Timeout for the lock - /// + /// Instance id of the scope who is requesting the lock. + /// Timeout for the lock. + /// Array of lock object identifiers. void EagerWriteLock(Guid instanceId, TimeSpan? timeout = null, params int[] lockIds); + /// + /// Eagerly acquires a write-lock using the default timeout. + /// + /// Instance id of the scope who is requesting the lock. + /// Array of lock object identifiers. void EagerWriteLock(Guid instanceId, params int[] lockIds); /// - /// Clears all the locks held + /// Clears all the locks held by a specific scope instance. /// - /// + /// Instance id of the scope whose locks should be cleared. void ClearLocks(Guid instanceId); /// - /// Acquires all the non-eagerly requested locks. + /// Acquires all the non-eagerly (lazily) requested locks. /// - /// + /// Instance id of the scope whose pending locks should be acquired. void EnsureLocks(Guid scopeInstanceId); + /// + /// Ensures all locks have been cleared for a specific scope instance, throwing if any remain. + /// + /// Instance id of the scope to verify. + /// Thrown when locks have not been properly cleared. void EnsureLocksCleared(Guid instanceId); + /// + /// Gets the dictionary of read locks held by scope instances. + /// + /// A dictionary mapping scope instance IDs to their read lock counts by lock ID, or null if no read locks exist. Dictionary>? GetReadLocks(); + /// + /// Gets the dictionary of write locks held by scope instances. + /// + /// A dictionary mapping scope instance IDs to their write lock counts by lock ID, or null if no write locks exist. Dictionary>? GetWriteLocks(); } diff --git a/src/Umbraco.Core/Scoping/IScopeContext.cs b/src/Umbraco.Core/Scoping/IScopeContext.cs index 26f17b31b03e..13e5fb8865a7 100644 --- a/src/Umbraco.Core/Scoping/IScopeContext.cs +++ b/src/Umbraco.Core/Scoping/IScopeContext.cs @@ -49,5 +49,9 @@ public interface IScopeContext : IInstanceIdentifiable /// The enlisted object, if any, else the default value. T? GetEnlisted(string key); + /// + /// Called when the scope exits to execute enlisted actions. + /// + /// A value indicating whether the scope completed successfully. void ScopeExit(bool completed); } diff --git a/src/Umbraco.Core/Scoping/LockingMechanism.cs b/src/Umbraco.Core/Scoping/LockingMechanism.cs index 00bcc0238346..e7bd633255bc 100644 --- a/src/Umbraco.Core/Scoping/LockingMechanism.cs +++ b/src/Umbraco.Core/Scoping/LockingMechanism.cs @@ -23,10 +23,10 @@ public class LockingMechanism : ILockingMechanism private Queue? _acquiredLocks; /// - /// Constructs an instance of LockingMechanism + /// Initializes a new instance of the class. /// - /// - /// + /// The factory for creating distributed locking mechanisms. + /// The logger for logging lock-related messages. public LockingMechanism(IDistributedLockingMechanismFactory distributedLockingMechanismFactory, ILogger logger) { _distributedLockingMechanismFactory = distributedLockingMechanismFactory; @@ -37,22 +37,26 @@ public LockingMechanism(IDistributedLockingMechanismFactory distributedLockingMe /// public void ReadLock(Guid instanceId, TimeSpan? timeout = null, params int[] lockIds) => LazyReadLockInner(instanceId, timeout, lockIds); + /// public void ReadLock(Guid instanceId, params int[] lockIds) => ReadLock(instanceId, null, lockIds); /// public void WriteLock(Guid instanceId, TimeSpan? timeout = null, params int[] lockIds) => LazyWriteLockInner(instanceId, timeout, lockIds); + /// public void WriteLock(Guid instanceId, params int[] lockIds) => WriteLock(instanceId, null, lockIds); /// public void EagerReadLock(Guid instanceId, TimeSpan? timeout = null, params int[] lockIds) => EagerReadLockInner(instanceId, timeout, lockIds); + /// public void EagerReadLock(Guid instanceId, params int[] lockIds) => EagerReadLock(instanceId, null, lockIds); /// public void EagerWriteLock(Guid instanceId, TimeSpan? timeout = null, params int[] lockIds) => EagerWriteLockInner(instanceId, timeout, lockIds); + /// public void EagerWriteLock(Guid instanceId, params int[] lockIds) => EagerWriteLock(instanceId, null, lockIds); @@ -252,10 +256,7 @@ private void LazyLockInner(DistributedLockType lockType, Guid instanceId, TimeSp } } - /// - /// Clears all lock counters for a given scope instance, signalling that the scope has been disposed. - /// - /// Instance ID of the scope to clear. + /// public void ClearLocks(Guid instanceId) { lock (_locker) @@ -282,6 +283,7 @@ public void ClearLocks(Guid instanceId) } } + /// public void EnsureLocksCleared(Guid instanceId) { while (!_acquiredLocks?.IsCollectionEmpty() ?? false) @@ -301,16 +303,7 @@ public void EnsureLocksCleared(Guid instanceId) throw exception; } - /// - /// When we require a ReadLock or a WriteLock we don't immediately request these locks from the database, - /// instead we only request them when necessary (lazily). - /// To do this, we queue requests for read/write locks. - /// This is so that if there's a request for either of these - /// locks, but the service/repository returns an item from the cache, we don't end up making a DB call to make the - /// read/write lock. - /// This executes the queue of requested locks in order in an efficient way lazily whenever the database instance is - /// resolved. - /// + /// public void EnsureLocks(Guid scopeInstanceId) { lock (_locker) @@ -389,8 +382,10 @@ public void EnsureLocks(Guid scopeInstanceId) } + /// public Dictionary>? GetReadLocks() => _readLocksDictionary; + /// public Dictionary>? GetWriteLocks() => _writeLocksDictionary; /// diff --git a/src/Umbraco.Core/Security/Authorization/ContentPermissionAuthorizer.cs b/src/Umbraco.Core/Security/Authorization/ContentPermissionAuthorizer.cs index 75c189d11ee2..e23bb93fc6bf 100644 --- a/src/Umbraco.Core/Security/Authorization/ContentPermissionAuthorizer.cs +++ b/src/Umbraco.Core/Security/Authorization/ContentPermissionAuthorizer.cs @@ -9,6 +9,10 @@ internal sealed class ContentPermissionAuthorizer : IContentPermissionAuthorizer { private readonly IContentPermissionService _contentPermissionService; + /// + /// Initializes a new instance of the class. + /// + /// The content permission service. public ContentPermissionAuthorizer(IContentPermissionService contentPermissionService) => _contentPermissionService = contentPermissionService; @@ -65,6 +69,7 @@ public async Task IsDeniedAtRecycleBinLevelAsync(IUser currentUser, ISet public async Task IsDeniedForCultures(IUser currentUser, ISet culturesToCheck) { ContentAuthorizationStatus result = diff --git a/src/Umbraco.Core/Security/Authorization/ContentPermissionResource.cs b/src/Umbraco.Core/Security/Authorization/ContentPermissionResource.cs index ee1d6b36d325..35f151252a6c 100644 --- a/src/Umbraco.Core/Security/Authorization/ContentPermissionResource.cs +++ b/src/Umbraco.Core/Security/Authorization/ContentPermissionResource.cs @@ -244,7 +244,8 @@ private ContentPermissionResource( public Guid? ParentKeyForBranch { get; } /// - /// All the cultures need to be accessible when evaluating + /// Gets the cultures to check for access. /// + /// All the cultures need to be accessible when evaluating. public ISet? CulturesToCheck { get; } } diff --git a/src/Umbraco.Core/Security/Authorization/DictionaryPermissionAuthorizer.cs b/src/Umbraco.Core/Security/Authorization/DictionaryPermissionAuthorizer.cs index b49b1c76c73b..18f7f2ba0370 100644 --- a/src/Umbraco.Core/Security/Authorization/DictionaryPermissionAuthorizer.cs +++ b/src/Umbraco.Core/Security/Authorization/DictionaryPermissionAuthorizer.cs @@ -4,13 +4,19 @@ namespace Umbraco.Cms.Core.Security.Authorization; +/// internal sealed class DictionaryPermissionAuthorizer : IDictionaryPermissionAuthorizer { private readonly IDictionaryPermissionService _dictionaryPermissionService; + /// + /// Initializes a new instance of the class. + /// + /// The dictionary permission service. public DictionaryPermissionAuthorizer(IDictionaryPermissionService dictionaryPermissionService) => _dictionaryPermissionService = dictionaryPermissionService; + /// public async Task IsAuthorizedForCultures(IUser currentUser, ISet culturesToCheck) { DictionaryAuthorizationStatus result = diff --git a/src/Umbraco.Core/Security/Authorization/DictionaryPermissionResource.cs b/src/Umbraco.Core/Security/Authorization/DictionaryPermissionResource.cs index 35cda6f718ba..cf9e42fcb4ac 100644 --- a/src/Umbraco.Core/Security/Authorization/DictionaryPermissionResource.cs +++ b/src/Umbraco.Core/Security/Authorization/DictionaryPermissionResource.cs @@ -1,12 +1,20 @@ namespace Umbraco.Cms.Core.Security.Authorization; +/// +/// A resource used for the DictionaryPermissionHandler authorization handler. +/// public class DictionaryPermissionResource : IPermissionResource { + /// + /// Initializes a new instance of the class. + /// + /// The cultures to check authorization for. public DictionaryPermissionResource(IEnumerable cultures) => CulturesToCheck = new HashSet(cultures); /// - /// All the cultures need to be accessible when evaluating + /// Gets the cultures to check for access. /// + /// All the cultures need to be accessible when evaluating. public ISet CulturesToCheck { get; } } diff --git a/src/Umbraco.Core/Security/Authorization/FeatureAuthorizer.cs b/src/Umbraco.Core/Security/Authorization/FeatureAuthorizer.cs index a15cbf501664..d3db2aa7fcdb 100644 --- a/src/Umbraco.Core/Security/Authorization/FeatureAuthorizer.cs +++ b/src/Umbraco.Core/Security/Authorization/FeatureAuthorizer.cs @@ -7,6 +7,10 @@ internal sealed class FeatureAuthorizer : IFeatureAuthorizer { private readonly UmbracoFeatures _umbracoFeatures; + /// + /// Initializes a new instance of the class. + /// + /// The Umbraco features configuration. public FeatureAuthorizer(UmbracoFeatures umbracoFeatures) => _umbracoFeatures = umbracoFeatures; /// diff --git a/src/Umbraco.Core/Security/Authorization/IContentPermissionAuthorizer.cs b/src/Umbraco.Core/Security/Authorization/IContentPermissionAuthorizer.cs index e24e423f7ca2..4df70631e6f4 100644 --- a/src/Umbraco.Core/Security/Authorization/IContentPermissionAuthorizer.cs +++ b/src/Umbraco.Core/Security/Authorization/IContentPermissionAuthorizer.cs @@ -80,5 +80,11 @@ Task IsDeniedAtRecycleBinLevelAsync(IUser currentUser, string permissionTo /// Returns true if authorization is successful, otherwise false. Task IsDeniedAtRecycleBinLevelAsync(IUser currentUser, ISet permissionsToCheck); + /// + /// Authorizes whether the current user has access to the specified cultures. + /// + /// The current user. + /// The collection of cultures to check access for. + /// Returns true if authorization is denied, otherwise false. Task IsDeniedForCultures(IUser currentUser, ISet culturesToCheck); } diff --git a/src/Umbraco.Core/Security/Authorization/IDictionaryPermissionAuthorizer.cs b/src/Umbraco.Core/Security/Authorization/IDictionaryPermissionAuthorizer.cs index f26479d7f1ea..d4d9117146ad 100644 --- a/src/Umbraco.Core/Security/Authorization/IDictionaryPermissionAuthorizer.cs +++ b/src/Umbraco.Core/Security/Authorization/IDictionaryPermissionAuthorizer.cs @@ -2,7 +2,16 @@ namespace Umbraco.Cms.Core.Security.Authorization; +/// +/// Authorizes dictionary access based on cultures. +/// public interface IDictionaryPermissionAuthorizer { + /// + /// Authorizes whether the current user has access to the specified cultures for dictionary operations. + /// + /// The current user. + /// The collection of cultures to check authorization for. + /// Returns true if authorization is successful, otherwise false. Task IsAuthorizedForCultures(IUser currentUser, ISet culturesToCheck); } diff --git a/src/Umbraco.Core/Security/Authorization/IPermissionResource.cs b/src/Umbraco.Core/Security/Authorization/IPermissionResource.cs index 408bfdc26da7..df24e6e650a3 100644 --- a/src/Umbraco.Core/Security/Authorization/IPermissionResource.cs +++ b/src/Umbraco.Core/Security/Authorization/IPermissionResource.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Security.Authorization; +/// +/// Marker interface for permission resources used by authorization handlers. +/// public interface IPermissionResource { } diff --git a/src/Umbraco.Core/Security/Authorization/MediaPermissionAuthorizer.cs b/src/Umbraco.Core/Security/Authorization/MediaPermissionAuthorizer.cs index af71fcf4af83..ffb26e2918c3 100644 --- a/src/Umbraco.Core/Security/Authorization/MediaPermissionAuthorizer.cs +++ b/src/Umbraco.Core/Security/Authorization/MediaPermissionAuthorizer.cs @@ -9,6 +9,10 @@ internal sealed class MediaPermissionAuthorizer : IMediaPermissionAuthorizer { private readonly IMediaPermissionService _mediaPermissionService; + /// + /// Initializes a new instance of the class. + /// + /// The media permission service. public MediaPermissionAuthorizer(IMediaPermissionService mediaPermissionService) => _mediaPermissionService = mediaPermissionService; diff --git a/src/Umbraco.Core/Security/Authorization/UserGroupPermissionAuthorizer.cs b/src/Umbraco.Core/Security/Authorization/UserGroupPermissionAuthorizer.cs index c8becee5d310..93b1004d7de5 100644 --- a/src/Umbraco.Core/Security/Authorization/UserGroupPermissionAuthorizer.cs +++ b/src/Umbraco.Core/Security/Authorization/UserGroupPermissionAuthorizer.cs @@ -9,6 +9,10 @@ internal sealed class UserGroupPermissionAuthorizer : IUserGroupPermissionAuthor { private readonly IUserGroupPermissionService _userGroupPermissionService; + /// + /// Initializes a new instance of the class. + /// + /// The user group permission service. public UserGroupPermissionAuthorizer(IUserGroupPermissionService userGroupPermissionService) => _userGroupPermissionService = userGroupPermissionService; diff --git a/src/Umbraco.Core/Security/Authorization/UserPermissionAuthorizer.cs b/src/Umbraco.Core/Security/Authorization/UserPermissionAuthorizer.cs index 513d317dc9ed..5550eb729aa0 100644 --- a/src/Umbraco.Core/Security/Authorization/UserPermissionAuthorizer.cs +++ b/src/Umbraco.Core/Security/Authorization/UserPermissionAuthorizer.cs @@ -9,6 +9,10 @@ internal sealed class UserPermissionAuthorizer : IUserPermissionAuthorizer { private readonly IUserPermissionService _userPermissionService; + /// + /// Initializes a new instance of the class. + /// + /// The user permission service. public UserPermissionAuthorizer(IUserPermissionService userPermissionService) => _userPermissionService = userPermissionService; diff --git a/src/Umbraco.Core/Security/BackOfficeAuthenticationTypeSettings.cs b/src/Umbraco.Core/Security/BackOfficeAuthenticationTypeSettings.cs index fc102ce95e01..0f0a6f4d6176 100644 --- a/src/Umbraco.Core/Security/BackOfficeAuthenticationTypeSettings.cs +++ b/src/Umbraco.Core/Security/BackOfficeAuthenticationTypeSettings.cs @@ -2,10 +2,28 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Configuration settings for back office authentication types. +/// public class BackOfficeAuthenticationTypeSettings { + /// + /// Gets or sets the authentication type for the back office. + /// public string AuthenticationType { get; set; } = Constants.Security.BackOfficeAuthenticationType; + + /// + /// Gets or sets the authentication type for external back office authentication. + /// public string ExternalAuthenticationType { get; set; } = Constants.Security.BackOfficeExternalAuthenticationType; + + /// + /// Gets or sets the authentication type for back office two-factor authentication. + /// public string TwoFactorAuthenticationType { get; set; } = Constants.Security.BackOfficeTwoFactorAuthenticationType; + + /// + /// Gets or sets the authentication type for back office two-factor remember me authentication. + /// public string TwoFactorRememberMeAuthenticationType { get; set; } = Constants.Security.BackOfficeTwoFactorRememberMeAuthenticationType; } diff --git a/src/Umbraco.Core/Security/BackOfficeExternalLoginProviderErrors.cs b/src/Umbraco.Core/Security/BackOfficeExternalLoginProviderErrors.cs index cece444588c6..4309cb70c5db 100644 --- a/src/Umbraco.Core/Security/BackOfficeExternalLoginProviderErrors.cs +++ b/src/Umbraco.Core/Security/BackOfficeExternalLoginProviderErrors.cs @@ -1,19 +1,36 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Represents errors from an external login provider for the back office. +/// public class BackOfficeExternalLoginProviderErrors { - // required for deserialization + /// + /// Initializes a new instance of the class. + /// + /// Required for deserialization. public BackOfficeExternalLoginProviderErrors() { } + /// + /// Initializes a new instance of the class. + /// + /// The authentication type of the external provider. + /// The collection of error messages. public BackOfficeExternalLoginProviderErrors(string? authenticationType, IEnumerable errors) { AuthenticationType = authenticationType; Errors = errors ?? Enumerable.Empty(); } + /// + /// Gets or sets the authentication type of the external login provider. + /// public string? AuthenticationType { get; set; } + /// + /// Gets or sets the collection of error messages from the external login provider. + /// public IEnumerable? Errors { get; set; } } diff --git a/src/Umbraco.Core/Security/BackOfficeUserPasswordCheckerResult.cs b/src/Umbraco.Core/Security/BackOfficeUserPasswordCheckerResult.cs index 5466642a1406..2d8847392665 100644 --- a/src/Umbraco.Core/Security/BackOfficeUserPasswordCheckerResult.cs +++ b/src/Umbraco.Core/Security/BackOfficeUserPasswordCheckerResult.cs @@ -1,11 +1,22 @@ namespace Umbraco.Cms.Core.Security; /// -/// The result returned from the IBackOfficeUserPasswordChecker +/// The result returned from the IBackOfficeUserPasswordChecker. /// public enum BackOfficeUserPasswordCheckerResult { + /// + /// The credentials are valid. + /// ValidCredentials, + + /// + /// The credentials are invalid. + /// InvalidCredentials, + + /// + /// The checker cannot validate the credentials and should fall back to the default checker. + /// FallbackToDefaultChecker, } diff --git a/src/Umbraco.Core/Security/ClaimsPrincipalExtensions.cs b/src/Umbraco.Core/Security/ClaimsPrincipalExtensions.cs index 4cb9e20dac42..5d079d4d8193 100644 --- a/src/Umbraco.Core/Security/ClaimsPrincipalExtensions.cs +++ b/src/Umbraco.Core/Security/ClaimsPrincipalExtensions.cs @@ -8,8 +8,16 @@ namespace Umbraco.Extensions; +/// +/// Extension methods for and related types. +/// public static class ClaimsPrincipalExtensions { + /// + /// Determines whether the specified claims identity is a back office authentication type. + /// + /// The claims identity to check. + /// true if the identity is authenticated with the back office authentication type; otherwise, false. public static bool IsBackOfficeAuthenticationType(this ClaimsIdentity? claimsIdentity) { if (claimsIdentity is null) diff --git a/src/Umbraco.Core/Security/ContentPermissions.cs b/src/Umbraco.Core/Security/ContentPermissions.cs index 4a7aceda2718..17db984d77f6 100644 --- a/src/Umbraco.Core/Security/ContentPermissions.cs +++ b/src/Umbraco.Core/Security/ContentPermissions.cs @@ -14,10 +14,24 @@ public class ContentPermissions { private readonly AppCaches _appCaches; + /// + /// Represents the result of a content access check. + /// public enum ContentAccess { + /// + /// Access to the content is granted. + /// Granted, + + /// + /// Access to the content is denied. + /// Denied, + + /// + /// The content was not found. + /// NotFound, } @@ -25,6 +39,13 @@ public enum ContentAccess private readonly IEntityService _entityService; private readonly IUserService _userService; + /// + /// Initializes a new instance of the class. + /// + /// The user service. + /// The content service. + /// The entity service. + /// The application caches. public ContentPermissions( IUserService userService, IContentService contentService, @@ -37,6 +58,13 @@ public ContentPermissions( _appCaches = appCaches; } + /// + /// Checks if the user has path access to a content item. + /// + /// The path of the content item. + /// The user's start node IDs. + /// The recycle bin ID. + /// true if the user has access; otherwise, false. public static bool HasPathAccess(string? path, int[]? startNodeIds, int recycleBinId) { if (string.IsNullOrWhiteSpace(path)) @@ -214,6 +242,14 @@ private bool CheckPermissionsPath(string? path, IUser user, IReadOnlySet return allowed; } + /// + /// Determines if a path is within the branch of the user's start node. + /// + /// The path to check. + /// The user's start node IDs. + /// The user's start node paths. + /// Outputs whether the user has direct path access. + /// true if the path is in the branch of the start node; otherwise, false. public static bool IsInBranchOfStartNode(string path, int[]? startNodeIds, string[]? startNodePaths, out bool hasPathAccess) { if (string.IsNullOrWhiteSpace(path)) diff --git a/src/Umbraco.Core/Security/ExternalLoginToken.cs b/src/Umbraco.Core/Security/ExternalLoginToken.cs index c2b93caa845c..fc267401ee60 100644 --- a/src/Umbraco.Core/Security/ExternalLoginToken.cs +++ b/src/Umbraco.Core/Security/ExternalLoginToken.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Security; /// public class ExternalLoginToken : IExternalLoginToken { + /// + /// The database table name for external login tokens. + /// public const string TableName = Constants.DatabaseSchema.Tables.ExternalLoginToken; /// diff --git a/src/Umbraco.Core/Security/FileStreamSecurityValidator.cs b/src/Umbraco.Core/Security/FileStreamSecurityValidator.cs index 764ea37d3dc9..3c0546953656 100644 --- a/src/Umbraco.Core/Security/FileStreamSecurityValidator.cs +++ b/src/Umbraco.Core/Security/FileStreamSecurityValidator.cs @@ -1,9 +1,17 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Default implementation of that validates file streams +/// using registered instances. +/// public class FileStreamSecurityValidator : IFileStreamSecurityValidator { private readonly IEnumerable _fileAnalyzers; + /// + /// Initializes a new instance of the class. + /// + /// The collection of file stream security analyzers to use for validation. public FileStreamSecurityValidator(IEnumerable fileAnalyzers) { _fileAnalyzers = fileAnalyzers; diff --git a/src/Umbraco.Core/Security/IBackOfficePasswordChanger.cs b/src/Umbraco.Core/Security/IBackOfficePasswordChanger.cs index 2bb1ac5a493a..95f0c399345e 100644 --- a/src/Umbraco.Core/Security/IBackOfficePasswordChanger.cs +++ b/src/Umbraco.Core/Security/IBackOfficePasswordChanger.cs @@ -1,9 +1,18 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Membership; namespace Umbraco.Cms.Core.Security; +/// +/// Provides functionality to change back office user passwords. +/// public interface IBackOfficePasswordChanger { + /// + /// Changes the password for a back office user. + /// + /// The password change model containing the user and new password details. + /// The user performing the password change operation. + /// An containing the result of the password change operation. Task> ChangeBackOfficePassword(ChangeBackOfficeUserPasswordModel model, IUser? performingUser); } diff --git a/src/Umbraco.Core/Security/IBackOfficeUserStore.cs b/src/Umbraco.Core/Security/IBackOfficeUserStore.cs index a89c97c75db3..e58e8e6bb61c 100644 --- a/src/Umbraco.Core/Security/IBackOfficeUserStore.cs +++ b/src/Umbraco.Core/Security/IBackOfficeUserStore.cs @@ -1,4 +1,4 @@ -using Umbraco.Cms.Core.Models.Membership; +using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Security; @@ -56,8 +56,18 @@ public interface IBackOfficeUserStore /// Task resolving into an . Task GetAsync(Guid key); + /// + /// Gets users by their keys. + /// + /// The keys of the users to retrieve. + /// A task resolving into an . Task> GetUsersAsync(params Guid[]? keys); + /// + /// Gets users by their IDs. + /// + /// The IDs of the users to retrieve. + /// A task resolving into an . Task> GetUsersAsync(params int[]? ids); diff --git a/src/Umbraco.Core/Security/IBackofficeSecurity.cs b/src/Umbraco.Core/Security/IBackofficeSecurity.cs index ba880ff9e50c..3ea4ae1e24e0 100644 --- a/src/Umbraco.Core/Security/IBackofficeSecurity.cs +++ b/src/Umbraco.Core/Security/IBackofficeSecurity.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Provides methods for backoffice security operations including authentication and authorization. +/// public interface IBackOfficeSecurity { /// diff --git a/src/Umbraco.Core/Security/IBackofficeSecurityAccessor.cs b/src/Umbraco.Core/Security/IBackofficeSecurityAccessor.cs index 11ed86971ee5..33cbc8c927a1 100644 --- a/src/Umbraco.Core/Security/IBackofficeSecurityAccessor.cs +++ b/src/Umbraco.Core/Security/IBackofficeSecurityAccessor.cs @@ -1,6 +1,12 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Provides access to the instance for the current request. +/// public interface IBackOfficeSecurityAccessor { + /// + /// Gets the instance for the current request. + /// IBackOfficeSecurity? BackOfficeSecurity { get; } } diff --git a/src/Umbraco.Core/Security/ICoreBackOfficeSignInManager.cs b/src/Umbraco.Core/Security/ICoreBackOfficeSignInManager.cs index e2ec297608c7..30712288cf17 100644 --- a/src/Umbraco.Core/Security/ICoreBackOfficeSignInManager.cs +++ b/src/Umbraco.Core/Security/ICoreBackOfficeSignInManager.cs @@ -2,7 +2,15 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Provides core sign-in functionality for back office users. +/// public interface ICoreBackOfficeSignInManager { + /// + /// Creates a for the specified user. + /// + /// The unique key of the user. + /// A task that resolves to the for the user, or null if the user is not found. Task CreateUserPrincipalAsync(Guid userKey); } diff --git a/src/Umbraco.Core/Security/ICoreBackOfficeUserManager.cs b/src/Umbraco.Core/Security/ICoreBackOfficeUserManager.cs index 4456d7b6c028..fcdf2afb682e 100644 --- a/src/Umbraco.Core/Security/ICoreBackOfficeUserManager.cs +++ b/src/Umbraco.Core/Security/ICoreBackOfficeUserManager.cs @@ -1,34 +1,83 @@ -using System.Security.Principal; +using System.Security.Principal; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Security; +/// +/// Provides core user management functionality for back office users. +/// public interface ICoreBackOfficeUserManager { + /// + /// Creates a new back office user. + /// + /// The model containing the user creation details. + /// A task that resolves to the result of the user creation operation. Task CreateAsync(UserCreateModel createModel); /// - /// Creates a user for an invite. This means that the password will not be populated with + /// Creates a user for an invite. This means that the password will not be populated. /// - /// - /// + /// The model containing the user creation details. + /// A task that resolves to the result of the user creation operation. Task CreateForInvite(UserCreateModel createModel); + /// + /// Generates an email confirmation token for the specified user. + /// + /// The user to generate the token for. + /// An attempt containing the generated token or an error status. Task> GenerateEmailConfirmationTokenAsync(IUser user); + /// + /// Generates a password reset token for the specified user. + /// + /// The user to generate the token for. + /// An attempt containing the generated token or an error status. Task> GeneratePasswordResetTokenAsync(IUser user); + /// + /// Unlocks the specified user account. + /// + /// The user to unlock. + /// An attempt containing the unlock result or an error status. Task> UnlockUser(IUser user); + /// + /// Gets all external logins associated with the specified user. + /// + /// The user to get logins for. + /// An attempt containing the collection of logins or an error status. Task, UserOperationStatus>> GetLoginsAsync(IUser user); + /// + /// Validates whether the email confirmation token is valid for the specified user. + /// + /// The user to validate the token for. + /// The token to validate. + /// true if the token is valid; otherwise, false. Task IsEmailConfirmationTokenValidAsync(IUser user, string token); + /// + /// Validates whether the password reset token is valid for the specified user. + /// + /// The user to validate the token for. + /// The token to validate. + /// true if the token is valid; otherwise, false. Task IsResetPasswordTokenValidAsync(IUser user, string token); + /// + /// Notifies that a forgot password request was made. + /// + /// The principal of the user who requested the password reset. + /// Additional information about the request. void NotifyForgotPasswordRequested(IPrincipal user, string toString); + /// + /// Generates a random password that meets the configured password requirements. + /// + /// A randomly generated password. public string GeneratePassword(); } diff --git a/src/Umbraco.Core/Security/IFileStreamSecurityAnalyzer.cs b/src/Umbraco.Core/Security/IFileStreamSecurityAnalyzer.cs index 408f161f21a1..fd6bc0b6f7bc 100644 --- a/src/Umbraco.Core/Security/IFileStreamSecurityAnalyzer.cs +++ b/src/Umbraco.Core/Security/IFileStreamSecurityAnalyzer.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Analyzes file streams for potential security threats. +/// public interface IFileStreamSecurityAnalyzer { diff --git a/src/Umbraco.Core/Security/IFileStreamSecurityValidator.cs b/src/Umbraco.Core/Security/IFileStreamSecurityValidator.cs index 9dc60507ac13..f3c8b90accf2 100644 --- a/src/Umbraco.Core/Security/IFileStreamSecurityValidator.cs +++ b/src/Umbraco.Core/Security/IFileStreamSecurityValidator.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Validates file streams for security using registered implementations. +/// public interface IFileStreamSecurityValidator { /// diff --git a/src/Umbraco.Core/Security/IForgotPasswordUriProvider.cs b/src/Umbraco.Core/Security/IForgotPasswordUriProvider.cs index 76c4527ad008..87a931331c53 100644 --- a/src/Umbraco.Core/Security/IForgotPasswordUriProvider.cs +++ b/src/Umbraco.Core/Security/IForgotPasswordUriProvider.cs @@ -3,7 +3,15 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Provides functionality to create forgot password URIs for users. +/// public interface IForgotPasswordUriProvider { + /// + /// Creates a forgot password URI for the specified user. + /// + /// The user to create the forgot password URI for. + /// An attempt containing the generated URI or an error status. Task> CreateForgotPasswordUriAsync(IUser user); } diff --git a/src/Umbraco.Core/Security/IHtmlSanitizer.cs b/src/Umbraco.Core/Security/IHtmlSanitizer.cs index 3faf3cfd4d2a..2af09474f0da 100644 --- a/src/Umbraco.Core/Security/IHtmlSanitizer.cs +++ b/src/Umbraco.Core/Security/IHtmlSanitizer.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Provides HTML sanitization functionality to prevent XSS attacks. +/// public interface IHtmlSanitizer { /// diff --git a/src/Umbraco.Core/Security/IInviteUriProvider.cs b/src/Umbraco.Core/Security/IInviteUriProvider.cs index 52e5525a985b..87ad73742fe8 100644 --- a/src/Umbraco.Core/Security/IInviteUriProvider.cs +++ b/src/Umbraco.Core/Security/IInviteUriProvider.cs @@ -1,10 +1,18 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Security; +/// +/// Provides functionality to create invite URIs for users. +/// public interface IInviteUriProvider { + /// + /// Creates an invite URI for the specified user. + /// + /// The user being invited. + /// An attempt containing the generated invite URI or an error status. Task> CreateInviteUriAsync(IUser invitee); } diff --git a/src/Umbraco.Core/Security/ILocalLoginSettingProvider.cs b/src/Umbraco.Core/Security/ILocalLoginSettingProvider.cs index 60709553fdfc..02e17e58ffd5 100644 --- a/src/Umbraco.Core/Security/ILocalLoginSettingProvider.cs +++ b/src/Umbraco.Core/Security/ILocalLoginSettingProvider.cs @@ -1,12 +1,16 @@ -namespace Umbraco.Cms.Core.Security; +namespace Umbraco.Cms.Core.Security; /// -/// A setting provider local logins. +/// A setting provider for local logins. +/// /// -/// This cannot be an app setting since it's specified the external login providers. +/// This cannot be an app setting since it's specified by the external login providers. /// -/// public interface ILocalLoginSettingProvider { + /// + /// Determines whether local login should be denied. + /// + /// true if local login is denied; otherwise, false. bool HasDenyLocalLogin(); } diff --git a/src/Umbraco.Core/Security/IPasswordHasher.cs b/src/Umbraco.Core/Security/IPasswordHasher.cs index 5f3345ea73e0..bc783c0d623c 100644 --- a/src/Umbraco.Core/Security/IPasswordHasher.cs +++ b/src/Umbraco.Core/Security/IPasswordHasher.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Provides password hashing functionality. +/// public interface IPasswordHasher { /// diff --git a/src/Umbraco.Core/Security/IPublicAccessChecker.cs b/src/Umbraco.Core/Security/IPublicAccessChecker.cs index 82957b37ded0..fcee1f0675ba 100644 --- a/src/Umbraco.Core/Security/IPublicAccessChecker.cs +++ b/src/Umbraco.Core/Security/IPublicAccessChecker.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Provides functionality to check public access rules for content items. +/// public interface IPublicAccessChecker { /// diff --git a/src/Umbraco.Core/Security/IUserForgotPasswordSender.cs b/src/Umbraco.Core/Security/IUserForgotPasswordSender.cs index 8ab3a05082d7..55a5089b94a5 100644 --- a/src/Umbraco.Core/Security/IUserForgotPasswordSender.cs +++ b/src/Umbraco.Core/Security/IUserForgotPasswordSender.cs @@ -2,9 +2,21 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Provides functionality to send forgot password messages to users. +/// public interface IUserForgotPasswordSender { + /// + /// Sends a forgot password message to the user. + /// + /// The forgot password message containing user and reset details. + /// A task representing the asynchronous operation. Task SendForgotPassword(UserForgotPasswordMessage message); + /// + /// Determines whether the sender is configured and able to send messages. + /// + /// true if the sender can send messages; otherwise, false. bool CanSend(); } diff --git a/src/Umbraco.Core/Security/IUserInviteSender.cs b/src/Umbraco.Core/Security/IUserInviteSender.cs index 6bfe49326eb8..aa031bd08ca0 100644 --- a/src/Umbraco.Core/Security/IUserInviteSender.cs +++ b/src/Umbraco.Core/Security/IUserInviteSender.cs @@ -1,10 +1,22 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Security; +/// +/// Provides functionality to send user invitation messages. +/// public interface IUserInviteSender { + /// + /// Sends an invitation to the user. + /// + /// The invitation message containing user and invite details. + /// A task representing the asynchronous operation. Task InviteUser(UserInvitationMessage invite); + /// + /// Determines whether the sender is configured and able to send invites. + /// + /// true if the sender can send invites; otherwise, false. bool CanSendInvites(); } diff --git a/src/Umbraco.Core/Security/IdentityAuditEventArgs.cs b/src/Umbraco.Core/Security/IdentityAuditEventArgs.cs index 83c11916b163..e6919a88b738 100644 --- a/src/Umbraco.Core/Security/IdentityAuditEventArgs.cs +++ b/src/Umbraco.Core/Security/IdentityAuditEventArgs.cs @@ -1,18 +1,68 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Specifies the type of audit event that occurred. +/// public enum AuditEvent { + /// + /// The user account was locked due to too many failed login attempts. + /// AccountLocked, + + /// + /// The user account was unlocked. + /// AccountUnlocked, + + /// + /// A forgot password request was made. + /// ForgotPasswordRequested, + + /// + /// The password was successfully changed via the forgot password flow. + /// ForgotPasswordChangedSuccess, + + /// + /// A login attempt failed. + /// LoginFailed, + + /// + /// The login requires additional verification (e.g., two-factor authentication). + /// LoginRequiresVerification, + + /// + /// The login was successful. + /// LoginSucces, + + /// + /// The user logged out successfully. + /// LogoutSuccess, + + /// + /// The user's password was changed. + /// PasswordChanged, + + /// + /// The user's password was reset. + /// PasswordReset, + + /// + /// The failed access count was reset for the user. + /// ResetAccessFailedCount, + + /// + /// A user invite is being sent. + /// SendingUserInvite, } @@ -35,6 +85,15 @@ public IdentityAuditEventArgs(AuditEvent action, string ipAddress, string perfor AffectedUser = affectedUser; } + /// + /// Initializes a new instance of the class + /// with the affected user defaulting to the super user. + /// + /// The audit action that was triggered. + /// The source IP address of the user performing the action. + /// The identifier of the user performing the action. + /// An optional comment about the action being logged. + /// The username of the affected user. public IdentityAuditEventArgs(AuditEvent action, string ipAddress, string performingUser, string comment, string affectedUsername) : this(action, ipAddress, performingUser, comment, Constants.Security.SuperUserIdAsString, affectedUsername) { diff --git a/src/Umbraco.Core/Security/IdentityUserToken.cs b/src/Umbraco.Core/Security/IdentityUserToken.cs index f4fcd46ace25..d1ea7632ccba 100644 --- a/src/Umbraco.Core/Security/IdentityUserToken.cs +++ b/src/Umbraco.Core/Security/IdentityUserToken.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Entity type for a user's external login token. +/// public class IdentityUserToken : EntityBase, IIdentityUserToken { /// diff --git a/src/Umbraco.Core/Security/MediaPermissions.cs b/src/Umbraco.Core/Security/MediaPermissions.cs index 6a79b91b358d..08088cc497c0 100644 --- a/src/Umbraco.Core/Security/MediaPermissions.cs +++ b/src/Umbraco.Core/Security/MediaPermissions.cs @@ -13,16 +13,36 @@ public class MediaPermissions { private readonly AppCaches _appCaches; + /// + /// Represents the result of a media access check. + /// public enum MediaAccess { + /// + /// Access to the media is granted. + /// Granted, + + /// + /// Access to the media is denied. + /// Denied, + + /// + /// The media was not found. + /// NotFound, } private readonly IEntityService _entityService; private readonly IMediaService _mediaService; + /// + /// Initializes a new instance of the class. + /// + /// The media service. + /// The entity service. + /// The application caches. public MediaPermissions(IMediaService mediaService, IEntityService entityService, AppCaches appCaches) { _mediaService = mediaService; @@ -66,6 +86,12 @@ public MediaAccess CheckPermissions(IUser? user, int nodeId, out IMedia? media) return hasPathAccess ? MediaAccess.Granted : MediaAccess.Denied; } + /// + /// Performs a permissions check for the user to check if it has access to the media item. + /// + /// The media item to check. + /// The user to check permissions for. + /// The result of the media access check. public MediaAccess CheckPermissions(IMedia? media, IUser? user) { if (user == null) diff --git a/src/Umbraco.Core/Security/NoopHtmlSanitizer.cs b/src/Umbraco.Core/Security/NoopHtmlSanitizer.cs index 5892f786a747..7ba6c87e09e8 100644 --- a/src/Umbraco.Core/Security/NoopHtmlSanitizer.cs +++ b/src/Umbraco.Core/Security/NoopHtmlSanitizer.cs @@ -1,6 +1,14 @@ namespace Umbraco.Cms.Core.Security; +/// +/// A no-operation implementation of that returns HTML unchanged. +/// +/// +/// This implementation does not perform any sanitization and should only be used when HTML +/// sanitization is not required or is handled elsewhere. +/// public class NoopHtmlSanitizer : IHtmlSanitizer { + /// public string Sanitize(string html) => html; } diff --git a/src/Umbraco.Core/Security/PasswordGenerator.cs b/src/Umbraco.Core/Security/PasswordGenerator.cs index d7f258d9fa3a..6cefa50842d6 100644 --- a/src/Umbraco.Core/Security/PasswordGenerator.cs +++ b/src/Umbraco.Core/Security/PasswordGenerator.cs @@ -14,9 +14,17 @@ public class PasswordGenerator { private readonly IPasswordConfiguration _passwordConfiguration; + /// + /// Initializes a new instance of the class. + /// + /// The password configuration settings. public PasswordGenerator(IPasswordConfiguration passwordConfiguration) => _passwordConfiguration = passwordConfiguration; + /// + /// Generates a password that meets the configured password requirements. + /// + /// A randomly generated password. public string GeneratePassword() { var password = PasswordStore.GeneratePassword( diff --git a/src/Umbraco.Core/Security/PublicAccessStatus.cs b/src/Umbraco.Core/Security/PublicAccessStatus.cs index 9026b11fd5fc..3f670d8f165a 100644 --- a/src/Umbraco.Core/Security/PublicAccessStatus.cs +++ b/src/Umbraco.Core/Security/PublicAccessStatus.cs @@ -1,10 +1,32 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Represents the result of a public access check for protected content. +/// public enum PublicAccessStatus { + /// + /// The user is not logged in. + /// NotLoggedIn, + + /// + /// The user does not have access to the content. + /// AccessDenied, + + /// + /// The member account has not been approved. + /// NotApproved, + + /// + /// The member account is locked out. + /// LockedOut, + + /// + /// The user has access to the content. + /// AccessAccepted, } diff --git a/src/Umbraco.Core/Security/UpdateMemberProfileResult.cs b/src/Umbraco.Core/Security/UpdateMemberProfileResult.cs index 0809f6c5018c..2a175c2569ad 100644 --- a/src/Umbraco.Core/Security/UpdateMemberProfileResult.cs +++ b/src/Umbraco.Core/Security/UpdateMemberProfileResult.cs @@ -1,18 +1,39 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Represents the result of a member profile update operation. +/// public class UpdateMemberProfileResult { + /// + /// Initializes a new instance of the class. + /// private UpdateMemberProfileResult() { } + /// + /// Gets the status of the update operation. + /// public UpdateMemberProfileStatus Status { get; private set; } + /// + /// Gets the error message if the operation failed. + /// public string? ErrorMessage { get; private set; } + /// + /// Creates a successful result. + /// + /// A new indicating success. public static UpdateMemberProfileResult Success() => new UpdateMemberProfileResult { Status = UpdateMemberProfileStatus.Success }; + /// + /// Creates an error result with the specified message. + /// + /// The error message describing the failure. + /// A new indicating an error. public static UpdateMemberProfileResult Error(string message) => new UpdateMemberProfileResult { Status = UpdateMemberProfileStatus.Error, ErrorMessage = message }; } diff --git a/src/Umbraco.Core/Security/UpdateMemberProfileStatus.cs b/src/Umbraco.Core/Security/UpdateMemberProfileStatus.cs index 74fb52e6971c..5eb4ec4a127c 100644 --- a/src/Umbraco.Core/Security/UpdateMemberProfileStatus.cs +++ b/src/Umbraco.Core/Security/UpdateMemberProfileStatus.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Security; +/// +/// Represents the status of a member profile update operation. +/// public enum UpdateMemberProfileStatus { + /// + /// The profile update was successful. + /// Success, + + /// + /// The profile update failed with an error. + /// Error, } diff --git a/src/Umbraco.Core/Semver/SemVersion.cs b/src/Umbraco.Core/Semver/SemVersion.cs index 8d47ed4630ca..3c61d7d58fed 100644 --- a/src/Umbraco.Core/Semver/SemVersion.cs +++ b/src/Umbraco.Core/Semver/SemVersion.cs @@ -501,6 +501,12 @@ public override int GetHashCode() } #if !NETSTANDARD + /// + /// Populates a with the data needed to serialize this instance. + /// + /// The to populate with data. + /// The destination for this serialization. + /// Thrown when is null. public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) diff --git a/src/Umbraco.Core/Serialization/IWebhookJsonSerializer.cs b/src/Umbraco.Core/Serialization/IWebhookJsonSerializer.cs index ba8d1ce68612..4282fdd1c514 100644 --- a/src/Umbraco.Core/Serialization/IWebhookJsonSerializer.cs +++ b/src/Umbraco.Core/Serialization/IWebhookJsonSerializer.cs @@ -1,4 +1,11 @@ -namespace Umbraco.Cms.Core.Serialization; +namespace Umbraco.Cms.Core.Serialization; +/// +/// Defines a JSON serializer specifically for webhook payloads. +/// +/// +/// This interface extends to provide specialized +/// serialization for webhook data with appropriate formatting and options. +/// public interface IWebhookJsonSerializer : IJsonSerializer { } diff --git a/src/Umbraco.Core/ServerEvents/EventSourceAuthorizerCollection.cs b/src/Umbraco.Core/ServerEvents/EventSourceAuthorizerCollection.cs index b62db65df8b6..185025f1d76e 100644 --- a/src/Umbraco.Core/ServerEvents/EventSourceAuthorizerCollection.cs +++ b/src/Umbraco.Core/ServerEvents/EventSourceAuthorizerCollection.cs @@ -1,9 +1,20 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.ServerEvents; +/// +/// Represents a collection of instances. +/// +/// +/// This collection contains all registered event source authorizers that determine +/// whether users have permission to subscribe to specific server-sent event sources. +/// public class EventSourceAuthorizerCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that provides the event source authorizers. public EventSourceAuthorizerCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/ServerEvents/EventSourceAuthorizerCollectionBuilder.cs b/src/Umbraco.Core/ServerEvents/EventSourceAuthorizerCollectionBuilder.cs index 36fdd432c8af..a9ac7fb4cbad 100644 --- a/src/Umbraco.Core/ServerEvents/EventSourceAuthorizerCollectionBuilder.cs +++ b/src/Umbraco.Core/ServerEvents/EventSourceAuthorizerCollectionBuilder.cs @@ -1,8 +1,16 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.ServerEvents; +/// +/// Builds the by allowing registration of instances. +/// +/// +/// Use this builder to register custom event source authorizers that control access to server-sent event sources. +/// The authorizers are executed in order, allowing for priority-based authorization logic. +/// public class EventSourceAuthorizerCollectionBuilder : OrderedCollectionBuilderBase { + /// protected override EventSourceAuthorizerCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/ServerEvents/IServerEventAuthorizationService.cs b/src/Umbraco.Core/ServerEvents/IServerEventAuthorizationService.cs index 3dd19cef4b84..ea0feff19f0d 100644 --- a/src/Umbraco.Core/ServerEvents/IServerEventAuthorizationService.cs +++ b/src/Umbraco.Core/ServerEvents/IServerEventAuthorizationService.cs @@ -1,14 +1,21 @@ -using System.Security.Claims; +using System.Security.Claims; using Umbraco.Cms.Core.Models.ServerEvents; namespace Umbraco.Cms.Core.ServerEvents; +/// +/// Provides authorization services for server-sent events. +/// +/// +/// This service determines which event sources a user is authorized to subscribe to +/// based on their claims and the registered instances. +/// public interface IServerEventAuthorizationService { /// /// Authorizes a user to listen to server events. /// /// The user to authorize. - /// The authorization result, containing all authorized event sources, and unauthorized event sources. + /// The authorization result, containing all authorized event sources and unauthorized event sources. Task AuthorizeAsync(ClaimsPrincipal user); } diff --git a/src/Umbraco.Core/ServerEvents/IServerEventHub.cs b/src/Umbraco.Core/ServerEvents/IServerEventHub.cs index 77892c541891..207f4991d194 100644 --- a/src/Umbraco.Core/ServerEvents/IServerEventHub.cs +++ b/src/Umbraco.Core/ServerEvents/IServerEventHub.cs @@ -1,9 +1,24 @@ -using Umbraco.Cms.Core.Models.ServerEvents; +using Umbraco.Cms.Core.Models.ServerEvents; namespace Umbraco.Cms.Core.ServerEvents; +/// +/// Defines the server event hub contract for real-time communication with clients. +/// +/// +/// This interface is implemented by SignalR hubs and defines the methods +/// that can be invoked on connected clients to push server events. +/// public interface IServerEventHub { + /// + /// Notifies connected clients of a server event. + /// + /// The server event payload to send to clients. + /// A task representing the asynchronous notification operation. + /// + /// The method name is lowercase to match SignalR client-side conventions. + /// #pragma warning disable SA1300 Task notify(ServerEvent payload); #pragma warning restore SA1300 diff --git a/src/Umbraco.Core/Services/AuditEntryService.cs b/src/Umbraco.Core/Services/AuditEntryService.cs index 8cc8d5441dc3..b8065ea94496 100644 --- a/src/Umbraco.Core/Services/AuditEntryService.cs +++ b/src/Umbraco.Core/Services/AuditEntryService.cs @@ -15,6 +15,11 @@ public class AuditEntryService : RepositoryService, IAuditEntryService /// /// Initializes a new instance of the class. /// + /// The audit entry repository. + /// The user ID key resolver. + /// The core scope provider. + /// The logger factory. + /// The event messages factory. public AuditEntryService( IAuditEntryRepository auditEntryRepository, IUserIdKeyResolver userIdKeyResolver, @@ -54,7 +59,19 @@ public async Task WriteAsync( eventDetails); } - // This method is used by the AuditService while the AuditService.Write() method is not removed. + /// + /// Writes an audit entry using user IDs instead of keys. + /// + /// The ID of the user performing the action. + /// Details about the performing user. + /// The IP address of the performing user. + /// The UTC date and time of the event. + /// The ID of the affected user, if any. + /// Details about the affected user. + /// The type of event. + /// Details about the event. + /// The created audit entry. + /// This method is used by the AuditService while the AuditService.Write() method is not removed. internal async Task WriteInner( int? performingUserId, string performingDetails, @@ -81,6 +98,20 @@ internal async Task WriteInner( eventDetails); } + /// + /// Internal implementation that writes an audit entry with all required data. + /// + /// The ID of the user performing the action. + /// The key of the user performing the action. + /// Details about the performing user. + /// The IP address of the performing user. + /// The UTC date and time of the event. + /// The ID of the affected user, if any. + /// The key of the affected user, if any. + /// Details about the affected user. + /// The type of event. + /// Details about the event. + /// The created audit entry. private IAuditEntry WriteInner( int? performingUserId, Guid? performingUserKey, @@ -160,17 +191,31 @@ private IAuditEntry WriteInner( return entry; } + /// + /// Gets the user ID for a given user key. + /// + /// The user key to resolve. + /// The user ID if found; otherwise, null. internal async Task GetUserId(Guid? key) => key is not null && await _userIdKeyResolver.TryGetAsync(key.Value) is { Success: true } attempt ? attempt.Result : null; + /// + /// Gets the user key for a given user ID. + /// + /// The user ID to resolve. + /// The user key if found; otherwise, null. internal async Task GetUserKey(int? id) => id is not null && await _userIdKeyResolver.TryGetAsync(id.Value) is { Success: true } attempt ? attempt.Result : null; - // TODO: Currently used in testing only, not part of the interface, need to add queryable methods to the interface instead + /// + /// Gets all audit entries. + /// + /// A collection of all audit entries. + /// Currently used in testing only. This is not part of the interface; queryable methods should be added to the interface instead. internal IEnumerable GetAll() { using (ScopeProvider.CreateCoreScope(autoComplete: true)) diff --git a/src/Umbraco.Core/Services/AuthorizationStatus/ContentAuthorizationStatus.cs b/src/Umbraco.Core/Services/AuthorizationStatus/ContentAuthorizationStatus.cs index dc6f6bad958b..bd868aeb3c10 100644 --- a/src/Umbraco.Core/Services/AuthorizationStatus/ContentAuthorizationStatus.cs +++ b/src/Umbraco.Core/Services/AuthorizationStatus/ContentAuthorizationStatus.cs @@ -1,13 +1,47 @@ namespace Umbraco.Cms.Core.Services.AuthorizationStatus; +/// +/// Represents the result of a content authorization check. +/// public enum ContentAuthorizationStatus { + /// + /// The authorization check succeeded. + /// Success, + + /// + /// The content item was not found. + /// NotFound, + + /// + /// The user does not have access to the recycle bin. + /// UnauthorizedMissingBinAccess, + + /// + /// The user does not have access to one or more descendant items. + /// UnauthorizedMissingDescendantAccess, + + /// + /// The user does not have access to the content path. + /// UnauthorizedMissingPathAccess, + + /// + /// The user does not have access to root-level content. + /// UnauthorizedMissingRootAccess, + + /// + /// The user does not have access to the specified culture. + /// UnauthorizedMissingCulture, + + /// + /// The user does not have the required permission for this operation. + /// UnauthorizedMissingPermissionAccess } diff --git a/src/Umbraco.Core/Services/AuthorizationStatus/DictionaryAuthorizationStatus.cs b/src/Umbraco.Core/Services/AuthorizationStatus/DictionaryAuthorizationStatus.cs index 5cb420e17bf8..c8885186fe58 100644 --- a/src/Umbraco.Core/Services/AuthorizationStatus/DictionaryAuthorizationStatus.cs +++ b/src/Umbraco.Core/Services/AuthorizationStatus/DictionaryAuthorizationStatus.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Services.AuthorizationStatus; +/// +/// Represents the result of a dictionary authorization check. +/// public enum DictionaryAuthorizationStatus { + /// + /// The authorization check succeeded. + /// Success, + + /// + /// The user does not have access to the specified culture. + /// UnauthorizedMissingCulture } diff --git a/src/Umbraco.Core/Services/AuthorizationStatus/MediaAuthorizationStatus.cs b/src/Umbraco.Core/Services/AuthorizationStatus/MediaAuthorizationStatus.cs index 191c5e285020..130a7b8a3d34 100644 --- a/src/Umbraco.Core/Services/AuthorizationStatus/MediaAuthorizationStatus.cs +++ b/src/Umbraco.Core/Services/AuthorizationStatus/MediaAuthorizationStatus.cs @@ -1,10 +1,32 @@ namespace Umbraco.Cms.Core.Services.AuthorizationStatus; +/// +/// Represents the result of a media authorization check. +/// public enum MediaAuthorizationStatus { + /// + /// The authorization check succeeded. + /// Success, + + /// + /// The media item was not found. + /// NotFound, + + /// + /// The user does not have access to the recycle bin. + /// UnauthorizedMissingBinAccess, + + /// + /// The user does not have access to the media path. + /// UnauthorizedMissingPathAccess, + + /// + /// The user does not have access to root-level media. + /// UnauthorizedMissingRootAccess } diff --git a/src/Umbraco.Core/Services/AuthorizationStatus/UserAuthorizationStatus.cs b/src/Umbraco.Core/Services/AuthorizationStatus/UserAuthorizationStatus.cs index ec49560fcf38..4b38e4cb787b 100644 --- a/src/Umbraco.Core/Services/AuthorizationStatus/UserAuthorizationStatus.cs +++ b/src/Umbraco.Core/Services/AuthorizationStatus/UserAuthorizationStatus.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Services.AuthorizationStatus; +/// +/// Represents the result of a user authorization check. +/// public enum UserAuthorizationStatus { + /// + /// The authorization check succeeded. + /// Success, + + /// + /// The user does not have administrator access. + /// UnauthorizedMissingAdminAccess } diff --git a/src/Umbraco.Core/Services/AuthorizationStatus/UserGroupAuthorizationStatus.cs b/src/Umbraco.Core/Services/AuthorizationStatus/UserGroupAuthorizationStatus.cs index d4f4b4720d16..fd43749044a5 100644 --- a/src/Umbraco.Core/Services/AuthorizationStatus/UserGroupAuthorizationStatus.cs +++ b/src/Umbraco.Core/Services/AuthorizationStatus/UserGroupAuthorizationStatus.cs @@ -1,11 +1,37 @@ namespace Umbraco.Cms.Core.Services.AuthorizationStatus; +/// +/// Represents the result of a user group authorization check. +/// public enum UserGroupAuthorizationStatus { + /// + /// The authorization check succeeded. + /// Success, + + /// + /// The user does not have access to the allowed sections of the user group. + /// UnauthorizedMissingAllowedSectionAccess, + + /// + /// The user does not have access to the content start node of the user group. + /// UnauthorizedMissingContentStartNodeAccess, + + /// + /// The user does not have access to the media start node of the user group. + /// UnauthorizedMissingMediaStartNodeAccess, + + /// + /// The user does not have access to the user group. + /// UnauthorizedMissingUserGroupAccess, + + /// + /// The user does not have access to the Users section. + /// UnauthorizedMissingUsersSectionAccess } diff --git a/src/Umbraco.Core/Services/BasicAuthService.cs b/src/Umbraco.Core/Services/BasicAuthService.cs index 121ff86eb847..dd24df278986 100644 --- a/src/Umbraco.Core/Services/BasicAuthService.cs +++ b/src/Umbraco.Core/Services/BasicAuthService.cs @@ -5,11 +5,19 @@ namespace Umbraco.Cms.Core.Services.Implement; +/// +/// Provides functionality for basic authentication operations including IP allow-listing and shared secret validation. +/// public class BasicAuthService : IBasicAuthService { private readonly IIpAddressUtilities _ipAddressUtilities; private BasicAuthSettings _basicAuthSettings; + /// + /// Initializes a new instance of the class. + /// + /// The options monitor for basic authentication settings. + /// The IP address utilities for checking allow-listed addresses. public BasicAuthService(IOptionsMonitor optionsMonitor, IIpAddressUtilities ipAddressUtilities) { _ipAddressUtilities = ipAddressUtilities; @@ -18,9 +26,13 @@ public BasicAuthService(IOptionsMonitor optionsMonitor, IIpAd optionsMonitor.OnChange(basicAuthSettings => _basicAuthSettings = basicAuthSettings); } + /// public bool IsBasicAuthEnabled() => _basicAuthSettings.Enabled; + + /// public bool IsRedirectToLoginPageEnabled() => _basicAuthSettings.RedirectToLoginPage; + /// public bool IsIpAllowListed(IPAddress clientIpAddress) { foreach (var allowedIpString in _basicAuthSettings.AllowedIPs) @@ -34,6 +46,7 @@ public bool IsIpAllowListed(IPAddress clientIpAddress) return false; } + /// public bool HasCorrectSharedSecret(IDictionary headers) { var headerName = _basicAuthSettings.SharedSecret.HeaderName; diff --git a/src/Umbraco.Core/Services/Changes/ContentTypeChange.cs b/src/Umbraco.Core/Services/Changes/ContentTypeChange.cs index f3fe533373aa..e53d5292c954 100644 --- a/src/Umbraco.Core/Services/Changes/ContentTypeChange.cs +++ b/src/Umbraco.Core/Services/Changes/ContentTypeChange.cs @@ -2,16 +2,31 @@ namespace Umbraco.Cms.Core.Services.Changes; +/// +/// Represents a change to a content type. +/// +/// The type of content type that changed. public class ContentTypeChange where TItem : class, IContentTypeComposition { + /// + /// Initializes a new instance of the class. + /// + /// The content type that changed. + /// The types of changes that occurred. public ContentTypeChange(TItem item, ContentTypeChangeTypes changeTypes) { Item = item; ChangeTypes = changeTypes; } + /// + /// Gets the content type that changed. + /// public TItem Item { get; } + /// + /// Gets or sets the types of changes that occurred. + /// public ContentTypeChangeTypes ChangeTypes { get; set; } } diff --git a/src/Umbraco.Core/Services/Changes/ContentTypeChangeExtensions.cs b/src/Umbraco.Core/Services/Changes/ContentTypeChangeExtensions.cs index d45a2267bc89..76c2576a0f05 100644 --- a/src/Umbraco.Core/Services/Changes/ContentTypeChangeExtensions.cs +++ b/src/Umbraco.Core/Services/Changes/ContentTypeChangeExtensions.cs @@ -5,17 +5,44 @@ namespace Umbraco.Extensions; +/// +/// Extension methods for content type changes. +/// public static class ContentTypeChangeExtensions { + /// + /// Determines whether the change includes the specified type. + /// + /// The change to check. + /// The type to look for. + /// true if the change includes the type; otherwise, false. public static bool HasType(this ContentTypeChangeTypes change, ContentTypeChangeTypes type) => (change & type) != ContentTypeChangeTypes.None; + /// + /// Determines whether the change includes all of the specified types. + /// + /// The change to check. + /// The types to look for. + /// true if the change includes all types; otherwise, false. public static bool HasTypesAll(this ContentTypeChangeTypes change, ContentTypeChangeTypes types) => (change & types) == types; + /// + /// Determines whether the change includes any of the specified types. + /// + /// The change to check. + /// The types to look for. + /// true if the change includes any of the types; otherwise, false. public static bool HasTypesAny(this ContentTypeChangeTypes change, ContentTypeChangeTypes types) => (change & types) != ContentTypeChangeTypes.None; + /// + /// Determines whether the change includes none of the specified types. + /// + /// The change to check. + /// The types to look for. + /// true if the change includes none of the types; otherwise, false. public static bool HasTypesNone(this ContentTypeChangeTypes change, ContentTypeChangeTypes types) => (change & types) == ContentTypeChangeTypes.None; } diff --git a/src/Umbraco.Core/Services/Changes/ContentTypeChangeTypes.cs b/src/Umbraco.Core/Services/Changes/ContentTypeChangeTypes.cs index 4346a278cc28..7b9c0a456aee 100644 --- a/src/Umbraco.Core/Services/Changes/ContentTypeChangeTypes.cs +++ b/src/Umbraco.Core/Services/Changes/ContentTypeChangeTypes.cs @@ -1,8 +1,14 @@ namespace Umbraco.Cms.Core.Services.Changes; +/// +/// Represents the types of changes that can occur on a content type. +/// [Flags] public enum ContentTypeChangeTypes : byte { + /// + /// No change has occurred. + /// None = 0, /// diff --git a/src/Umbraco.Core/Services/Changes/DomainChangeTypes.cs b/src/Umbraco.Core/Services/Changes/DomainChangeTypes.cs index 303461f48f89..cfed3fc25f5e 100644 --- a/src/Umbraco.Core/Services/Changes/DomainChangeTypes.cs +++ b/src/Umbraco.Core/Services/Changes/DomainChangeTypes.cs @@ -1,9 +1,27 @@ namespace Umbraco.Cms.Core.Services.Changes; +/// +/// Represents the types of changes that can occur on a domain. +/// public enum DomainChangeTypes : byte { + /// + /// No change has occurred. + /// None = 0, + + /// + /// All domains have been refreshed. + /// RefreshAll = 1, + + /// + /// A single domain has been refreshed. + /// Refresh = 2, + + /// + /// A domain has been removed. + /// Remove = 3, } diff --git a/src/Umbraco.Core/Services/Changes/TreeChange.cs b/src/Umbraco.Core/Services/Changes/TreeChange.cs index 70adf1e005ee..32bcef792cc2 100644 --- a/src/Umbraco.Core/Services/Changes/TreeChange.cs +++ b/src/Umbraco.Core/Services/Changes/TreeChange.cs @@ -1,13 +1,29 @@ namespace Umbraco.Cms.Core.Services.Changes; +/// +/// Represents a change to a tree item. +/// +/// The type of the item that changed. public class TreeChange { + /// + /// Initializes a new instance of the class. + /// + /// The item that changed. + /// The types of changes that occurred. public TreeChange(TItem changedItem, TreeChangeTypes changeTypes) { Item = changedItem; ChangeTypes = changeTypes; } + /// + /// Initializes a new instance of the class with culture information. + /// + /// The item that changed. + /// The types of changes that occurred. + /// The cultures that were published. + /// The cultures that were unpublished. public TreeChange(TItem changedItem, TreeChangeTypes changeTypes, IEnumerable? publishedCultures, IEnumerable? unpublishedCultures) { Item = changedItem; @@ -16,25 +32,55 @@ public TreeChange(TItem changedItem, TreeChangeTypes changeTypes, IEnumerable + /// Gets the item that changed. + /// public TItem Item { get; } + /// + /// Gets the types of changes that occurred. + /// public TreeChangeTypes ChangeTypes { get; } + /// + /// Gets the cultures that were published, if any. + /// public IEnumerable? PublishedCultures { get; } + /// + /// Gets the cultures that were unpublished, if any. + /// public IEnumerable? UnpublishedCultures { get; } + /// + /// Converts this change to event arguments. + /// + /// Event arguments containing this change. public EventArgs ToEventArgs() => new EventArgs(this); + /// + /// Event arguments for tree changes. + /// public class EventArgs : System.EventArgs { + /// + /// Initializes a new instance of the class with multiple changes. + /// + /// The changes that occurred. public EventArgs(IEnumerable> changes) => Changes = changes.ToArray(); + /// + /// Initializes a new instance of the class with a single change. + /// + /// The change that occurred. public EventArgs(TreeChange change) : this(new[] { change }) { } + /// + /// Gets the changes that occurred. + /// public IEnumerable> Changes { get; } } } diff --git a/src/Umbraco.Core/Services/Changes/TreeChangeExtensions.cs b/src/Umbraco.Core/Services/Changes/TreeChangeExtensions.cs index 1dc972eb7a35..000a9c7fcb21 100644 --- a/src/Umbraco.Core/Services/Changes/TreeChangeExtensions.cs +++ b/src/Umbraco.Core/Services/Changes/TreeChangeExtensions.cs @@ -5,19 +5,52 @@ namespace Umbraco.Extensions; +/// +/// Extension methods for tree changes. +/// public static class TreeChangeExtensions { + /// + /// Converts a collection of tree changes to event arguments. + /// + /// The type of the item that changed. + /// The changes to convert. + /// Event arguments containing the changes. public static TreeChange.EventArgs ToEventArgs(this IEnumerable> changes) => new TreeChange.EventArgs(changes); + /// + /// Determines whether the change includes the specified type. + /// + /// The change to check. + /// The type to look for. + /// true if the change includes the type; otherwise, false. public static bool HasType(this TreeChangeTypes change, TreeChangeTypes type) => (change & type) != TreeChangeTypes.None; + /// + /// Determines whether the change includes all of the specified types. + /// + /// The change to check. + /// The types to look for. + /// true if the change includes all types; otherwise, false. public static bool HasTypesAll(this TreeChangeTypes change, TreeChangeTypes types) => (change & types) == types; + /// + /// Determines whether the change includes any of the specified types. + /// + /// The change to check. + /// The types to look for. + /// true if the change includes any of the types; otherwise, false. public static bool HasTypesAny(this TreeChangeTypes change, TreeChangeTypes types) => (change & types) != TreeChangeTypes.None; + /// + /// Determines whether the change includes none of the specified types. + /// + /// The change to check. + /// The types to look for. + /// true if the change includes none of the types; otherwise, false. public static bool HasTypesNone(this TreeChangeTypes change, TreeChangeTypes types) => (change & types) == TreeChangeTypes.None; } diff --git a/src/Umbraco.Core/Services/Changes/TreeChangeTypes.cs b/src/Umbraco.Core/Services/Changes/TreeChangeTypes.cs index 85db740a56ee..322ef5c35f88 100644 --- a/src/Umbraco.Core/Services/Changes/TreeChangeTypes.cs +++ b/src/Umbraco.Core/Services/Changes/TreeChangeTypes.cs @@ -1,21 +1,39 @@ namespace Umbraco.Cms.Core.Services.Changes; +/// +/// Represents the types of changes that can occur on a tree item. +/// [Flags] public enum TreeChangeTypes : byte { + /// + /// No change has occurred. + /// None = 0, + /// + /// All items have been refreshed. + /// // all items have been refreshed RefreshAll = 1, + /// + /// An item node has been refreshed with only local impact. + /// // an item node has been refreshed // with only local impact RefreshNode = 2, + /// + /// An item node has been refreshed with branch impact. + /// // an item node has been refreshed // with branch impact RefreshBranch = 4, + /// + /// An item node has been removed permanently. + /// // an item node has been removed // never to return Remove = 8, diff --git a/src/Umbraco.Core/Services/ContentBlueprintContainerService.cs b/src/Umbraco.Core/Services/ContentBlueprintContainerService.cs index 046c4756324e..aef9acea1468 100644 --- a/src/Umbraco.Core/Services/ContentBlueprintContainerService.cs +++ b/src/Umbraco.Core/Services/ContentBlueprintContainerService.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence.Repositories; @@ -6,8 +6,21 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing content blueprint containers (folders). +/// internal sealed class ContentBlueprintContainerService : EntityTypeContainerService, IContentBlueprintContainerService { + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The document blueprint container repository. + /// The audit service. + /// The entity repository. + /// The user ID key resolver. public ContentBlueprintContainerService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -20,11 +33,15 @@ public ContentBlueprintContainerService( { } + /// protected override Guid ContainedObjectType => Constants.ObjectTypes.DocumentBlueprint; + /// protected override UmbracoObjectTypes ContainerObjectType => UmbracoObjectTypes.DocumentBlueprintContainer; + /// protected override int[] ReadLockIds => new [] { Constants.Locks.ContentTree }; + /// protected override int[] WriteLockIds => ReadLockIds; } diff --git a/src/Umbraco.Core/Services/ContentBlueprintEditingService.cs b/src/Umbraco.Core/Services/ContentBlueprintEditingService.cs index f40aafc30193..6b297ab1cab2 100644 --- a/src/Umbraco.Core/Services/ContentBlueprintEditingService.cs +++ b/src/Umbraco.Core/Services/ContentBlueprintEditingService.cs @@ -12,11 +12,29 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for creating, updating, and managing content blueprints (templates for content). +/// internal sealed class ContentBlueprintEditingService : ContentEditingServiceBase, IContentBlueprintEditingService { private readonly IContentBlueprintContainerService _containerService; + /// + /// Initializes a new instance of the class. + /// + /// The content service. + /// The content type service. + /// The collection of property editors. + /// The data type service. + /// The logger. + /// The scope provider. + /// The user ID key resolver. + /// The content validation service. + /// The content blueprint container service. + /// The content settings options monitor. + /// The relation service. + /// The content type filter collection. public ContentBlueprintEditingService( IContentService contentService, IContentTypeService contentTypeService, @@ -33,12 +51,14 @@ public ContentBlueprintEditingService( : base(contentService, contentTypeService, propertyEditorCollection, dataTypeService, logger, scopeProvider, userIdKeyResolver, validationService, optionsMonitor, relationService, contentTypeFilters) => _containerService = containerService; + /// public Task GetAsync(Guid key) { IContent? blueprint = ContentService.GetBlueprintById(key); return Task.FromResult(blueprint); } + /// public Task GetScaffoldedAsync(Guid key) { IContent? blueprint = ContentService.GetBlueprintById(key); @@ -56,6 +76,7 @@ public ContentBlueprintEditingService( return Task.FromResult(scaffold); } + /// public async Task?, ContentEditingOperationStatus>> GetPagedByContentTypeAsync(Guid contentTypeKey, int skip, int take) { IContentType? contentType = await ContentTypeService.GetAsync(contentTypeKey); @@ -75,6 +96,7 @@ public ContentBlueprintEditingService( return Attempt.SucceedWithStatus?, ContentEditingOperationStatus>(ContentEditingOperationStatus.Success, result); } + /// public async Task> CreateAsync(ContentBlueprintCreateModel createModel, Guid userKey) { if (await ValidateCulturesAsync(createModel) is false) @@ -101,6 +123,7 @@ public async Task> C return Attempt.SucceedWithStatus(ContentEditingOperationStatus.Success, new ContentCreateResult { Content = blueprint, ValidationResult = result.Result.ValidationResult }); } + /// public async Task> CreateFromContentAsync(Guid contentKey, string name, Guid? key, Guid userKey) { IContent? content = ContentService.GetById(contentKey); @@ -129,6 +152,7 @@ public async Task> C return Attempt.SucceedWithStatus(ContentEditingOperationStatus.Success, new ContentCreateResult { Content = blueprint }); } + /// public async Task> UpdateAsync(Guid key, ContentBlueprintUpdateModel updateModel, Guid userKey) { IContent? blueprint = await GetAsync(key); @@ -159,6 +183,7 @@ public async Task> U return Attempt.SucceedWithStatus(ContentEditingOperationStatus.Success, new ContentUpdateResult { Content = blueprint, ValidationResult = result.Result.ValidationResult }); } + /// public async Task> DeleteAsync(Guid key, Guid userKey) { using ICoreScope scope = CoreScopeProvider.CreateCoreScope(); @@ -176,6 +201,7 @@ public async Task> U return Attempt.SucceedWithStatus(ContentEditingOperationStatus.Success, blueprint); } + /// public async Task> MoveAsync(Guid key, Guid? containerKey, Guid userKey) { using ICoreScope scope = CoreScopeProvider.CreateCoreScope(); @@ -214,9 +240,11 @@ public async Task> MoveAsync(Guid key, Gu return Attempt.Succeed(ContentEditingOperationStatus.Success); } + /// protected override IContent New(string? name, int parentId, IContentType contentType) => new Content(name, parentId, contentType); + /// protected override async Task<(int? ParentId, ContentEditingOperationStatus OperationStatus)> TryGetAndValidateParentIdAsync(Guid? parentKey, IContentType contentType) { if (parentKey.HasValue is false) @@ -231,29 +259,79 @@ protected override IContent New(string? name, int parentId, IContentType content } /// - /// NB: Some methods from ContentEditingServiceBase are needed, so we need to inherit from it - /// but there are others that are not required to be implemented in the case of blueprints, therefore they throw NotImplementedException as default. + /// Moves the specified content to a new parent. Not supported for blueprints. /// + /// The content to move. + /// The ID of the new parent. + /// The ID of the user performing the operation. + /// Not supported for blueprints. + /// Always thrown as this operation is not supported for blueprints. + /// + /// Some methods from ContentEditingServiceBase are needed, so we need to inherit from it + /// but there are others that are not required to be implemented in the case of blueprints. + /// protected override OperationResult? Move(IContent content, int newParentId, int userId) => throw new NotImplementedException(); + /// + /// Copies the specified content to a new parent. Not supported for blueprints. + /// + /// The content to copy. + /// The ID of the new parent. + /// Whether to relate the copy to the original. + /// Whether to include descendants in the copy. + /// The ID of the user performing the operation. + /// Not supported for blueprints. + /// Always thrown as this operation is not supported for blueprints. protected override IContent? Copy(IContent content, int newParentId, bool relateToOriginal, bool includeDescendants, int userId) => throw new NotImplementedException(); + /// + /// Moves the specified content to the recycle bin. Not supported for blueprints. + /// + /// The content to move to recycle bin. + /// The ID of the user performing the operation. + /// Not supported for blueprints. + /// Always thrown as this operation is not supported for blueprints. protected override OperationResult? MoveToRecycleBin(IContent content, int userId) => throw new NotImplementedException(); + /// + /// Deletes the specified content. Not supported for blueprints. + /// + /// The content to delete. + /// The ID of the user performing the operation. + /// Not supported for blueprints. + /// Always thrown as this operation is not supported for blueprints. protected override OperationResult? Delete(IContent content, int userId) => throw new NotImplementedException(); + /// + /// Saves a blueprint with the specified user key. + /// + /// The blueprint to save. + /// The unique identifier of the user performing the save. + /// The optional content item the blueprint was created from. private async Task SaveAsync(IContent blueprint, Guid userKey, IContent? createdFromContent = null) { var currentUserId = await GetUserIdAsync(userKey); ContentService.SaveBlueprint(blueprint, createdFromContent, currentUserId); } + /// + /// Validates that the specified name is unique among blueprints of the same content type. + /// + /// The name to validate. + /// The content item to check against. + /// true if the name is unique; otherwise, false. private bool ValidateUniqueName(string name, IContent content) { IEnumerable existing = ContentService.GetBlueprintsForContentTypes(content.ContentTypeId); return existing.Any(c => c.Name == name && c.Id != content.Id) is false; } + /// + /// Validates that all variant names are unique among blueprints of the same content type. + /// + /// The variants containing names to validate. + /// The content item to check against. + /// true if all names are unique; otherwise, false. private bool ValidateUniqueNames(IEnumerable variants, IContent content) { IContent[] existing = ContentService.GetBlueprintsForContentTypes(content.ContentTypeId).ToArray(); diff --git a/src/Umbraco.Core/Services/ContentEditingService.cs b/src/Umbraco.Core/Services/ContentEditingService.cs index 375821ab5fa4..2f3f4f76a028 100644 --- a/src/Umbraco.Core/Services/ContentEditingService.cs +++ b/src/Umbraco.Core/Services/ContentEditingService.cs @@ -13,6 +13,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for creating, updating, and managing content (documents). +/// internal sealed class ContentEditingService : ContentEditingServiceWithSortingBase, IContentEditingService { @@ -23,6 +26,25 @@ internal sealed class ContentEditingService private readonly ILocalizationService _localizationService; private readonly ILanguageService _languageService; + /// + /// Initializes a new instance of the class. + /// + /// The content service. + /// The content type service. + /// The property editor collection. + /// The data type service. + /// The template service. + /// The logger. + /// The scope provider. + /// The user ID key resolver. + /// The tree entity sorting service. + /// The content validation service. + /// The user service. + /// The localization service. + /// The language service. + /// The content settings options monitor. + /// The relation service. + /// The content type filter collection. public ContentEditingService( IContentService contentService, IContentTypeService contentTypeService, @@ -65,12 +87,14 @@ public ContentEditingService( /// protected override string? RelateParentOnDeleteAlias => Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias; + /// public Task GetAsync(Guid key) { IContent? content = ContentService.GetById(key); return Task.FromResult(content); } + /// public async Task> ValidateUpdateAsync(Guid key, ValidateContentUpdateModel updateModel, Guid userKey) { IContent? content = ContentService.GetById(key); @@ -79,6 +103,7 @@ public async Task public async Task> ValidateCreateAsync(ContentCreateModel createModel, Guid userKey) => await ValidateCulturesAndPropertiesAsync(createModel, createModel.ContentTypeKey, await GetCulturesToValidate(createModel.Variants.Select(variant => variant.Culture), userKey)); @@ -108,6 +133,7 @@ public async Task !string.IsNullOrEmpty(x) && allowedCultures.Contains(x)).ToList(); } + /// public async Task> CreateAsync(ContentCreateModel createModel, Guid userKey) { if (await ValidateCulturesAsync(createModel) is false) @@ -236,6 +262,7 @@ private async Task> GetAllowedCulturesForEditingUser(Guid userKe return (await _languageService.GetIsoCodesByIdsAsync(allowedLanguageIds)).ToHashSet(); } + /// public async Task> UpdateAsync(Guid key, ContentUpdateModel updateModel, Guid userKey) { IContent? content = ContentService.GetById(key); @@ -274,24 +301,31 @@ public async Task> U : Attempt.FailWithStatus(saveStatus, new ContentUpdateResult { Content = content }); } + /// public async Task> MoveToRecycleBinAsync(Guid key, Guid userKey) => await HandleMoveToRecycleBinAsync(key, userKey); + /// public async Task> DeleteFromRecycleBinAsync(Guid key, Guid userKey) => await HandleDeleteAsync(key, userKey,true); + /// public async Task> DeleteAsync(Guid key, Guid userKey) => await HandleDeleteAsync(key, userKey,false); + /// public async Task> MoveAsync(Guid key, Guid? parentKey, Guid userKey) => await HandleMoveAsync(key, parentKey, userKey); + /// public async Task> RestoreAsync(Guid key, Guid? parentKey, Guid userKey) => await HandleMoveAsync(key, parentKey, userKey, true); + /// public async Task> CopyAsync(Guid key, Guid? parentKey, bool relateToOriginal, bool includeDescendants, Guid userKey) => await HandleCopyAsync(key, parentKey, relateToOriginal, includeDescendants, userKey); + /// public async Task SortAsync( Guid? parentKey, IEnumerable sortingModels, @@ -331,22 +365,29 @@ private async Task UpdateTemplateAsync(IContent c return ContentEditingOperationStatus.Success; } + /// protected override IContent New(string? name, int parentId, IContentType contentType) => new Content(name, parentId, contentType); + /// protected override OperationResult? Move(IContent content, int newParentId, int userId) => ContentService.Move(content, newParentId, userId); + /// protected override IContent? Copy(IContent content, int newParentId, bool relateToOriginal, bool includeDescendants, int userId) => ContentService.Copy(content, newParentId, relateToOriginal, includeDescendants, userId); + /// protected override OperationResult? MoveToRecycleBin(IContent content, int userId) => ContentService.MoveToRecycleBin(content, userId); + /// protected override OperationResult? Delete(IContent content, int userId) => ContentService.Delete(content, userId); + /// protected override IEnumerable GetPagedChildren(int parentId, int pageIndex, int pageSize, out long total) => ContentService.GetPagedChildren(parentId, pageIndex, pageSize, out total); + /// protected override ContentEditingOperationStatus Sort(IEnumerable items, int userId) { OperationResult result = ContentService.Sort(items, userId); diff --git a/src/Umbraco.Core/Services/ContentEditingServiceBase.cs b/src/Umbraco.Core/Services/ContentEditingServiceBase.cs index 5f7347d26997..df0b02c1b8cc 100644 --- a/src/Umbraco.Core/Services/ContentEditingServiceBase.cs +++ b/src/Umbraco.Core/Services/ContentEditingServiceBase.cs @@ -12,6 +12,14 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Base class for content editing services that provides common functionality for creating, updating, +/// and managing content entities (documents, media, members). +/// +/// The type of content entity. +/// The type of content type. +/// The type of content service. +/// The type of content type service. internal abstract class ContentEditingServiceBase where TContent : class, IContentBase where TContentType : class, IContentTypeComposition @@ -26,6 +34,20 @@ internal abstract class ContentEditingServiceBase + /// Initializes a new instance of the class. + /// + /// The content service. + /// The content type service. + /// The property editor collection. + /// The data type service. + /// The logger. + /// The scope provider. + /// The user ID key resolver. + /// The validation service. + /// The content settings options monitor. + /// The relation service. + /// The content type filter collection. protected ContentEditingServiceBase( TContentService contentService, TContentTypeService contentTypeService, @@ -57,22 +79,69 @@ protected ContentEditingServiceBase( _contentTypeFilters = contentTypeFilters; } + /// + /// Creates a new content entity. + /// + /// The name of the content. + /// The parent identifier. + /// The content type. + /// A new content entity. protected abstract TContent New(string? name, int parentId, TContentType contentType); + /// + /// Moves content to a new parent. + /// + /// The content to move. + /// The new parent identifier. + /// The user performing the operation. + /// The operation result. protected abstract OperationResult? Move(TContent content, int newParentId, int userId); + /// + /// Copies content to a new parent. + /// + /// The content to copy. + /// The new parent identifier. + /// Whether to create a relation to the original. + /// Whether to include descendants in the copy. + /// The user performing the operation. + /// The copied content, or null if the operation failed. protected abstract TContent? Copy(TContent content, int newParentId, bool relateToOriginal, bool includeDescendants, int userId); + /// + /// Moves content to the recycle bin. + /// + /// The content to move to recycle bin. + /// The user performing the operation. + /// The operation result. protected abstract OperationResult? MoveToRecycleBin(TContent content, int userId); + /// + /// Deletes content. + /// + /// The content to delete. + /// The user performing the operation. + /// The operation result. protected abstract OperationResult? Delete(TContent content, int userId); + /// + /// Gets the current content settings. + /// protected ContentSettings ContentSettings { get; private set; } + /// + /// Gets the core scope provider. + /// protected ICoreScopeProvider CoreScopeProvider { get; } + /// + /// Gets the content service. + /// protected TContentService ContentService { get; } + /// + /// Gets the content type service. + /// protected TContentTypeService ContentTypeService { get; } /// @@ -80,6 +149,12 @@ protected ContentEditingServiceBase( /// protected virtual string? RelateParentOnDeleteAlias => null; + /// + /// Maps a content creation model to a new content entity. + /// + /// The type of the creation result. + /// The content creation model. + /// An attempt containing the creation result and operation status. protected async Task> MapCreate(ContentCreationModelBase contentCreationModelBase) where TContentCreateResult : ContentCreateResultBase, new() { @@ -111,6 +186,13 @@ protected async Task + /// Maps a content editing model to an existing content entity for update. + /// + /// The type of the update result. + /// The existing content entity to update. + /// The content editing model. + /// An attempt containing the update result and operation status. protected async Task> MapUpdate(TContent content, ContentEditingModelBase contentEditingModelBase) where TContentUpdateResult : ContentUpdateResultBase, new() { @@ -131,9 +213,21 @@ protected async Task + /// Validates the cultures in the content editing model. + /// + /// The content editing model to validate. + /// true if all cultures are valid; otherwise, false. protected async Task ValidateCulturesAsync(ContentEditingModelBase contentEditingModelBase) => await _validationService.ValidateCulturesAsync(contentEditingModelBase); + /// + /// Validates the properties in the content editing model against the content type. + /// + /// The content editing model to validate. + /// The content type key. + /// Optional cultures to restrict validation to. + /// An attempt containing the validation result and operation status. protected async Task> ValidatePropertiesAsync( ContentEditingModelBase contentEditingModelBase, Guid contentTypeKey, @@ -159,6 +253,12 @@ private async Task + /// Handles moving content to the recycle bin. + /// + /// The content key. + /// The user key performing the operation. + /// An attempt containing the content and operation status. protected async Task> HandleMoveToRecycleBinAsync(Guid key, Guid userKey) => await HandleDeletionAsync( key, @@ -168,6 +268,13 @@ private async Task + /// Handles deleting content. + /// + /// The content key. + /// The user key performing the operation. + /// Whether the content must be in the recycle bin to be deleted. + /// An attempt containing the content and operation status. protected async Task> HandleDeleteAsync(Guid key, Guid userKey, bool mustBeTrashed = true) => await HandleDeletionAsync( key, @@ -240,6 +347,14 @@ private async Task + /// Handles moving content to a new parent. + /// + /// The content key. + /// The new parent key, or null for root. + /// The user key performing the operation. + /// Whether the content must be in the recycle bin (for restore operations). + /// An attempt containing the content and operation status. protected async Task> HandleMoveAsync(Guid key, Guid? parentKey, Guid userKey, bool mustBeInRecycleBin = false) { using ICoreScope scope = CoreScopeProvider.CreateCoreScope(); @@ -288,6 +403,15 @@ private async Task + /// Handles copying content to a new parent. + /// + /// The content key to copy. + /// The new parent key, or null for root. + /// Whether to create a relation to the original. + /// Whether to include descendants in the copy. + /// The user key performing the operation. + /// An attempt containing the copied content and operation status. protected async Task> HandleCopyAsync(Guid key, Guid? parentKey, bool relateToOriginal, bool includeDescendants, Guid userKey) { using ICoreScope scope = CoreScopeProvider.CreateCoreScope(); @@ -324,6 +448,11 @@ private async Task + /// Converts an operation result to a content editing operation status. + /// + /// The operation result to convert. + /// The corresponding content editing operation status. protected ContentEditingOperationStatus OperationResultToOperationStatus(OperationResult? operationResult) => operationResult?.Result switch { @@ -336,6 +465,11 @@ protected ContentEditingOperationStatus OperationResultToOperationStatus(Operati _ => ContentEditingOperationStatus.Unknown }; + /// + /// Gets the user ID from the user key. + /// + /// The user key. + /// The user ID. protected async Task GetUserIdAsync(Guid userKey) => await _userIdKeyResolver.GetAsync(userKey); private TContentType? TryGetAndValidateContentType(Guid contentTypeKey, ContentEditingModelBase contentEditingModelBase, out ContentEditingOperationStatus operationStatus) @@ -402,6 +536,12 @@ protected ContentEditingOperationStatus OperationResultToOperationStatus(Operati return contentType; } + /// + /// Attempts to get and validate the parent ID for content creation or move operations. + /// + /// The parent key, or null for root. + /// The content type being created or moved. + /// A tuple containing the parent ID (if valid) and the operation status. protected virtual async Task<(int? ParentId, ContentEditingOperationStatus OperationStatus)> TryGetAndValidateParentIdAsync(Guid? parentKey, TContentType contentType) { TContent? parent = parentKey.HasValue diff --git a/src/Umbraco.Core/Services/ContentEditingServiceWithSortingBase.cs b/src/Umbraco.Core/Services/ContentEditingServiceWithSortingBase.cs index 56dcba4613fb..b1732b3617d5 100644 --- a/src/Umbraco.Core/Services/ContentEditingServiceWithSortingBase.cs +++ b/src/Umbraco.Core/Services/ContentEditingServiceWithSortingBase.cs @@ -10,6 +10,13 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Base class for content editing services that support sorting operations. +/// +/// The type of content (e.g., IContent, IMedia). +/// The type of content type. +/// The type of content service. +/// The type of content type service. internal abstract class ContentEditingServiceWithSortingBase : ContentEditingServiceBase where TContent : class, IContentBase @@ -20,6 +27,21 @@ internal abstract class ContentEditingServiceWithSortingBase> _logger; private readonly ITreeEntitySortingService _treeEntitySortingService; + /// + /// Initializes a new instance of the class. + /// + /// The content service. + /// The content type service. + /// The property editor collection. + /// The data type service. + /// The logger. + /// The scope provider. + /// The user ID key resolver. + /// The validation service. + /// The tree entity sorting service. + /// The content settings options monitor. + /// The relation service. + /// The content type filter collection. protected ContentEditingServiceWithSortingBase( TContentService contentService, TContentTypeService contentTypeService, @@ -50,10 +72,31 @@ protected ContentEditingServiceWithSortingBase( _treeEntitySortingService = treeEntitySortingService; } + /// + /// Sorts the specified items. + /// + /// The items to sort. + /// The user performing the sort operation. + /// The operation status. protected abstract ContentEditingOperationStatus Sort(IEnumerable items, int userId); + /// + /// Gets the paged children of the specified parent. + /// + /// The parent identifier. + /// The zero-based page index. + /// The page size. + /// The total number of children. + /// The paged children. protected abstract IEnumerable GetPagedChildren(int parentId, int pageIndex, int pageSize, out long total); + /// + /// Handles the sorting operation asynchronously. + /// + /// The optional parent key. + /// The sorting models. + /// The user key performing the operation. + /// The operation status. protected async Task HandleSortAsync( Guid? parentKey, IEnumerable sortingModels, diff --git a/src/Umbraco.Core/Services/ContentPermissionService.cs b/src/Umbraco.Core/Services/ContentPermissionService.cs index 71ac02d62c18..0f7f8c40c246 100644 --- a/src/Umbraco.Core/Services/ContentPermissionService.cs +++ b/src/Umbraco.Core/Services/ContentPermissionService.cs @@ -17,6 +17,14 @@ internal sealed class ContentPermissionService : IContentPermissionService private readonly AppCaches _appCaches; private readonly ILanguageService _languageService; + /// + /// Initializes a new instance of the class. + /// + /// The content service. + /// The entity service. + /// The user service. + /// The application caches. + /// The language service. public ContentPermissionService( IContentService contentService, IEntityService entityService, diff --git a/src/Umbraco.Core/Services/ContentPublishingService.cs b/src/Umbraco.Core/Services/ContentPublishingService.cs index baba993ccf97..26978151804d 100644 --- a/src/Umbraco.Core/Services/ContentPublishingService.cs +++ b/src/Umbraco.Core/Services/ContentPublishingService.cs @@ -13,6 +13,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for publishing and unpublishing content, including scheduled publishing and branch publishing. +/// internal sealed class ContentPublishingService : IContentPublishingService { private const string PublishBranchOperationType = "ContentPublishBranch"; @@ -29,6 +32,20 @@ internal sealed class ContentPublishingService : IContentPublishingService private readonly ILongRunningOperationService _longRunningOperationService; private readonly IUmbracoContextFactory _umbracoContextFactory; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The content service. + /// The user ID key resolver. + /// The content validation service. + /// The content type service. + /// The language service. + /// The content settings options monitor. + /// The relation service. + /// The logger. + /// The long running operation service. + /// The Umbraco context factory. public ContentPublishingService( ICoreScopeProvider coreScopeProvider, IContentService contentService, diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index accdc84712de..230a5dd1f2bb 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -47,6 +47,26 @@ public class ContentService : RepositoryService, IContentService #region Constructors + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The document repository. + /// The entity repository. + /// The audit service. + /// The content type repository. + /// The document blueprint repository. + /// The language repository. + /// The property validation service. + /// The short string helper. + /// The culture impact factory. + /// The user ID key resolver. + /// The property editor collection. + /// The ID key map. + /// The content settings options monitor. + /// The relation service. public ContentService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -88,6 +108,26 @@ public ContentService( _logger = loggerFactory.CreateLogger(); } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The document repository. + /// The entity repository. + /// The audit repository. + /// The content type repository. + /// The document blueprint repository. + /// The language repository. + /// The property validation service. + /// The short string helper. + /// The culture impact factory. + /// The user ID key resolver. + /// The property editor collection. + /// The ID key map. + /// The content settings options monitor. + /// The relation service. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public ContentService( ICoreScopeProvider provider, @@ -128,6 +168,27 @@ public ContentService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The document repository. + /// The entity repository. + /// The audit repository. + /// The audit service. + /// The content type repository. + /// The document blueprint repository. + /// The language repository. + /// The property validation service. + /// The short string helper. + /// The culture impact factory. + /// The user ID key resolver. + /// The property editor collection. + /// The ID key map. + /// The content settings options monitor. + /// The relation service. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public ContentService( ICoreScopeProvider provider, @@ -181,6 +242,14 @@ public ContentService( #region Rollback + /// + /// Rolls back an item to a previous version. + /// + /// The ID of the content to roll back. + /// The version ID to roll back to. + /// The culture to roll back, or "*" for all cultures. + /// The optional ID of the user performing the rollback. + /// An indicating the result of the operation. public OperationResult Rollback(int id, int versionId, string culture = "*", int userId = Constants.Security.SuperUserId) { EventMessages evtMsgs = EventMessagesFactory.Get(); @@ -242,6 +311,11 @@ public OperationResult Rollback(int id, int versionId, string culture = "*", int #region Count + /// + /// Gets the count of published items. + /// + /// The optional content type alias to filter by. + /// The count of published content items. public int CountPublished(string? contentTypeAlias = null) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -251,6 +325,11 @@ public int CountPublished(string? contentTypeAlias = null) } } + /// + /// Gets the count of all items. + /// + /// The optional content type alias to filter by. + /// The count of content items. public int Count(string? contentTypeAlias = null) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -260,6 +339,12 @@ public int Count(string? contentTypeAlias = null) } } + /// + /// Gets the count of child items under a specified parent. + /// + /// The ID of the parent content. + /// The optional content type alias to filter by. + /// The count of child content items. public int CountChildren(int parentId, string? contentTypeAlias = null) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -269,6 +354,12 @@ public int CountChildren(int parentId, string? contentTypeAlias = null) } } + /// + /// Gets the count of descendant items under a specified parent. + /// + /// The ID of the parent content. + /// The optional content type alias to filter by. + /// The count of descendant content items. public int CountDescendants(int parentId, string? contentTypeAlias = null) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -583,6 +674,11 @@ public ContentScheduleCollection GetContentScheduleByContentId(int contentId) } } + /// + /// Gets the content schedule collection for the specified content key. + /// + /// The unique key of the content to retrieve the schedule for. + /// The for the specified content, or an empty collection if not found. public ContentScheduleCollection GetContentScheduleByContentId(Guid contentId) { Attempt idAttempt = _idKeyMap.GetIdForKey(contentId, UmbracoObjectTypes.Document); @@ -605,11 +701,7 @@ public void PersistContentSchedule(IContent content, ContentScheduleCollection c } } - /// - /// - /// - /// - /// + /// Attempt IContentServiceBase.Save(IEnumerable contents, int userId) => Attempt.Succeed(Save(contents, userId)); @@ -1071,6 +1163,11 @@ public bool IsPathPublishable(IContent content) return parent == null || IsPathPublished(parent); } + /// + /// Checks if the and all its ancestors are published. + /// + /// The content to check. + /// true if the content and all its ancestors are published; otherwise, false. public bool IsPathPublished(IContent? content) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -2105,6 +2202,14 @@ private static string[] EnsureCultures(IContent content, string[] cultures) private static bool ProvidedCulturesIndicatePublishAll(string[] cultures) => cultures.Length == 0 || (cultures.Length == 1 && cultures[0] == "invariant"); + /// + /// Publishes a branch of content items starting from the specified document. + /// + /// The content item to start publishing from. + /// A function that determines which cultures should be published for each content item. Returns null if the item should not be published. + /// A function that handles the actual publishing of cultures for each content item. + /// The identifier of the user performing the publish operation. + /// A collection of representing the results of publishing each content item in the branch. internal IEnumerable PublishBranch( IContent document, Func?> shouldPublish, @@ -2629,6 +2734,11 @@ private void PerformMoveContentLocked(IContent content, int userId, bool? trash) _documentRepository.Save(content); } + /// + /// Empties the Recycle Bin by deleting all items that reside in the bin asynchronously. + /// + /// The unique key of the user performing the operation. + /// An indicating the result of the operation. public async Task EmptyRecycleBinAsync(Guid userId) => EmptyRecycleBin(await _userIdKeyResolver.GetAsync(userId)); @@ -2683,6 +2793,10 @@ public OperationResult EmptyRecycleBin(int userId = Constants.Security.SuperUser return OperationResult.Succeed(eventMessages); } + /// + /// Checks if there are any items in the Recycle Bin. + /// + /// true if there are items in the Recycle Bin; otherwise, false. public bool RecycleBinSmells() { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -3051,6 +3165,11 @@ private OperationResult Sort(ICoreScope scope, IContent[] itemsA, int userId, Ev private static bool HasUnsavedChanges(IContent content) => content.HasIdentity is false || content.IsDirty(); + /// + /// Checks the data integrity of the content tree and optionally fixes issues. + /// + /// The options for the data integrity check. + /// A containing the results of the integrity check. public ContentDataIntegrityReport CheckDataIntegrity(ContentDataIntegrityReportOptions options) { using (ICoreScope scope = ScopeProvider.CreateCoreScope()) @@ -3090,6 +3209,16 @@ internal IEnumerable GetPublishedDescendants(IContent content) } } + /// + /// Gets the published descendants of the specified content item while holding the content tree lock. + /// + /// The content item to retrieve published descendants from. + /// An enumerable of published descendants. + /// + /// This method should only be called within a scope that already holds the content tree read lock. + /// The returned contents include all published versions below the content, but are filtered to exclude + /// items that are not directly published because they are below an unpublished content. + /// internal IEnumerable GetPublishedDescendantsLocked(IContent content) { var pathMatch = content.Path + ","; @@ -3628,6 +3757,11 @@ private IContentType GetContentType(string contentTypeAlias) #region Blueprints + /// + /// Gets a content blueprint by its integer ID. + /// + /// The ID of the blueprint to retrieve. + /// The blueprint, or null if not found. public IContent? GetBlueprintById(int id) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -3643,6 +3777,11 @@ private IContentType GetContentType(string contentTypeAlias) } } + /// + /// Gets a content blueprint by its unique key. + /// + /// The unique key of the blueprint to retrieve. + /// The blueprint, or null if not found. public IContent? GetBlueprintById(Guid id) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -3658,9 +3797,20 @@ private IContentType GetContentType(string contentTypeAlias) } } + /// + /// Saves a content blueprint. + /// + /// The blueprint content to save. + /// The optional ID of the user saving the blueprint. public void SaveBlueprint(IContent content, int userId = Constants.Security.SuperUserId) => SaveBlueprint(content, null, userId); + /// + /// Saves a content blueprint with reference to the source content it was created from. + /// + /// The blueprint content to save. + /// The original content the blueprint was created from, or null. + /// The optional ID of the user saving the blueprint. public void SaveBlueprint(IContent content, IContent? createdFromContent, int userId = Constants.Security.SuperUserId) { EventMessages evtMsgs = EventMessagesFactory.Get(); @@ -3689,6 +3839,11 @@ public void SaveBlueprint(IContent content, IContent? createdFromContent, int us } } + /// + /// Deletes a content blueprint. + /// + /// The blueprint content to delete. + /// The optional ID of the user deleting the blueprint. public void DeleteBlueprint(IContent content, int userId = Constants.Security.SuperUserId) { EventMessages evtMsgs = EventMessagesFactory.Get(); @@ -3705,6 +3860,13 @@ public void DeleteBlueprint(IContent content, int userId = Constants.Security.Su private static readonly string?[] ArrayOfOneNullString = { null }; + /// + /// Creates a new from a blueprint. + /// + /// The blueprint to create the content from. + /// The name for the new content. + /// The optional ID of the user creating the content. + /// The newly created based on the blueprint. public IContent CreateBlueprintFromContent( IContent blueprint, string name, @@ -3755,6 +3917,11 @@ public IContent CreateBlueprintFromContent( public IContent CreateContentFromBlueprint(IContent blueprint, string name, int userId = Constants.Security.SuperUserId) => CreateBlueprintFromContent(blueprint, name, userId); + /// + /// Gets all content blueprints for the specified content type IDs. + /// + /// The content type IDs to get blueprints for, or empty to get all blueprints. + /// A collection of blueprints. public IEnumerable GetBlueprintsForContentTypes(params int[] contentTypeId) { using (ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -3776,6 +3943,11 @@ public IEnumerable GetBlueprintsForContentTypes(params int[] contentTy } } + /// + /// Deletes all content blueprints of the specified content type IDs. + /// + /// The content type IDs whose blueprints should be deleted. + /// The optional ID of the user deleting the blueprints. public void DeleteBlueprintsOfTypes(IEnumerable contentTypeIds, int userId = Constants.Security.SuperUserId) { EventMessages evtMsgs = EventMessagesFactory.Get(); @@ -3814,6 +3986,11 @@ public void DeleteBlueprintsOfTypes(IEnumerable contentTypeIds, int userId } } + /// + /// Deletes all content blueprints of the specified content type ID. + /// + /// The content type ID whose blueprints should be deleted. + /// The optional ID of the user deleting the blueprints. public void DeleteBlueprintsOfType(int contentTypeId, int userId = Constants.Security.SuperUserId) => DeleteBlueprintsOfTypes(new[] { contentTypeId }, userId); diff --git a/src/Umbraco.Core/Services/ContentServiceExtensions.cs b/src/Umbraco.Core/Services/ContentServiceExtensions.cs index cac93c2426c7..206879867c71 100644 --- a/src/Umbraco.Core/Services/ContentServiceExtensions.cs +++ b/src/Umbraco.Core/Services/ContentServiceExtensions.cs @@ -19,6 +19,13 @@ public static class ContentServiceExtensions private static readonly Regex AnchorRegex = new(@"", RegexOptions.Compiled); private static readonly string[] _propertyTypesWithRte = new[] { Constants.PropertyEditors.Aliases.RichText, Constants.PropertyEditors.Aliases.BlockList, Constants.PropertyEditors.Aliases.BlockGrid }; + /// + /// Gets content items by their UDI identifiers. + /// + /// The content service. + /// The UDI identifiers of the content items to retrieve. + /// A collection of content items matching the specified UDIs. + /// Thrown when any UDI is not a . public static IEnumerable GetByIds(this IContentService contentService, IEnumerable ids) { var guids = new List(); @@ -65,6 +72,13 @@ public static IContent CreateContent(this IContentService contentService, string public static void RemoveContentPermissions(this IContentService contentService, int contentId) => contentService.SetPermissions(new EntityPermissionSet(contentId, new EntityPermissionCollection())); + /// + /// Gets all anchor values from Rich Text Editor properties of a content item. + /// + /// The content service. + /// The content item identifier. + /// The culture to use, or "*" for all cultures. Defaults to "*". + /// A collection of anchor values found in the RTE properties. public static IEnumerable GetAnchorValuesFromRTEs(this IContentService contentService, int id, string? culture = "*") { var result = new List(); @@ -90,6 +104,12 @@ public static IEnumerable GetAnchorValuesFromRTEs(this IContentService c return result; } + /// + /// Extracts anchor values from Rich Text Editor content. + /// + /// The content service. + /// The RTE content to extract anchors from. + /// A collection of anchor values found in the content. public static IEnumerable GetAnchorValuesFromRTEContent( this IContentService contentService, string rteContent) diff --git a/src/Umbraco.Core/Services/ContentTypeBaseServiceProvider.cs b/src/Umbraco.Core/Services/ContentTypeBaseServiceProvider.cs index 36a790b9f689..206932a650fe 100644 --- a/src/Umbraco.Core/Services/ContentTypeBaseServiceProvider.cs +++ b/src/Umbraco.Core/Services/ContentTypeBaseServiceProvider.cs @@ -2,12 +2,21 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides the appropriate content type service based on the type of content base entity. +/// public class ContentTypeBaseServiceProvider : IContentTypeBaseServiceProvider { private readonly IContentTypeService _contentTypeService; private readonly IMediaTypeService _mediaTypeService; private readonly IMemberTypeService _memberTypeService; + /// + /// Initializes a new instance of the class. + /// + /// The content type service. + /// The media type service. + /// The member type service. public ContentTypeBaseServiceProvider(IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService) { _contentTypeService = contentTypeService; @@ -15,6 +24,7 @@ public ContentTypeBaseServiceProvider(IContentTypeService contentTypeService, IM _memberTypeService = memberTypeService; } + /// public IContentTypeBaseService For(IContentBase contentBase) { if (contentBase == null) @@ -37,6 +47,7 @@ public IContentTypeBaseService For(IContentBase contentBase) } } + /// // note: this should be a default interface method with C# 8 public IContentTypeComposition? GetContentTypeOf(IContentBase contentBase) { diff --git a/src/Umbraco.Core/Services/ContentTypeContainerService.cs b/src/Umbraco.Core/Services/ContentTypeContainerService.cs index 6258216c8e9c..fa7829006904 100644 --- a/src/Umbraco.Core/Services/ContentTypeContainerService.cs +++ b/src/Umbraco.Core/Services/ContentTypeContainerService.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence.Repositories; @@ -7,8 +7,21 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing content type containers (folders). +/// internal sealed class ContentTypeContainerService : EntityTypeContainerService, IContentTypeContainerService { + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The document type container repository. + /// The audit service. + /// The entity repository. + /// The user ID key resolver. public ContentTypeContainerService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -21,11 +34,15 @@ public ContentTypeContainerService( { } + /// protected override Guid ContainedObjectType => Constants.ObjectTypes.DocumentType; + /// protected override UmbracoObjectTypes ContainerObjectType => UmbracoObjectTypes.DocumentTypeContainer; + /// protected override int[] ReadLockIds => ContentTypeLocks.ReadLockIds; + /// protected override int[] WriteLockIds => ContentTypeLocks.WriteLockIds; } diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingService.cs b/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingService.cs index c8fe7fe775bb..7510e902b941 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingService.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingService.cs @@ -11,6 +11,15 @@ namespace Umbraco.Cms.Core.Services.ContentTypeEditing; // NOTE: this is the implementation for document types. in the code we refer to document types as content types // at core level, so it has to be named ContentTypeEditingService instead of DocumentTypeEditingService. + +/// +/// Implementation of for managing document types (content types). +/// +/// +/// In Umbraco Core, document types are referred to as content types. This service handles +/// creating and updating document types including their properties, templates, compositions, +/// and history cleanup settings. +/// internal sealed class ContentTypeEditingService : ContentTypeEditingServiceBase, IContentTypeEditingService { private readonly ITemplateService _templateService; @@ -18,6 +27,16 @@ internal sealed class ContentTypeEditingService : ContentTypeEditingServiceBase< private readonly IReservedFieldNamesService _reservedFieldNamesService; private readonly IContentTypeService _contentTypeService; + /// + /// Initializes a new instance of the class. + /// + /// The content type service for managing content types. + /// The template service for managing templates. + /// The data type service for validating property data types. + /// The entity service for resolving entity relationships. + /// The helper for generating safe aliases. + /// The validator for element type switching operations. + /// The service providing reserved field names. public ContentTypeEditingService( IContentTypeService contentTypeService, ITemplateService templateService, @@ -34,6 +53,7 @@ public ContentTypeEditingService( _reservedFieldNamesService = reservedFieldNamesService; } + /// public async Task> CreateAsync(ContentTypeCreateModel model, Guid userKey) { Attempt result = await ValidateAndMapForCreationAsync(model, model.Key, model.ContainerKey); @@ -58,6 +78,7 @@ public ContentTypeEditingService( return Attempt.SucceedWithStatus(ContentTypeOperationStatus.Success, contentType); } + /// public async Task> UpdateAsync(IContentType contentType, ContentTypeUpdateModel model, Guid userKey) { // this needs to happen before the base call as that one is not a pure function @@ -85,6 +106,7 @@ public ContentTypeEditingService( : Attempt.FailWithStatus(attempt.Result, null); } + /// public async Task> GetAvailableCompositionsAsync( Guid? key, IEnumerable currentCompositeKeys, @@ -92,6 +114,7 @@ public async Task> GetAvaila bool isElement) => await FindAvailableCompositionsAsync(key, currentCompositeKeys, currentPropertyAliases, isElement); + /// protected override async Task AdditionalCreateValidationAsync( ContentTypeEditingModelBase model) { @@ -122,6 +145,15 @@ private void UpdateTemplates(IContentType contentType, ContentTypeModelBase mode contentType.SetDefaultTemplate(allowedTemplates.FirstOrDefault(t => t.Key == model.DefaultTemplateKey)); } + /// + /// Validates element status changes when updating a content type. + /// + /// The existing content type being updated. + /// The update model containing the new element status. + /// + /// if validation passes; + /// otherwise, an error status indicating why the element status change is not allowed. + /// private async Task ValidateElementStatusForUpdateAsync(IContentTypeBase contentType, ContentTypeModelBase model) { // no change, ignore rest of validation @@ -164,14 +196,19 @@ private async Task ValidateCreateParentElementStatus : ContentTypeOperationStatus.InvalidElementFlagComparedToParent; } + /// protected override IContentType CreateContentType(IShortStringHelper shortStringHelper, int parentId) => new ContentType(shortStringHelper, parentId); + /// protected override bool SupportsPublishing => true; + /// protected override UmbracoObjectTypes ContentTypeObjectType => UmbracoObjectTypes.DocumentType; + /// protected override UmbracoObjectTypes ContainerObjectType => UmbracoObjectTypes.DocumentTypeContainer; + /// protected override ISet GetReservedFieldNames() => _reservedFieldNamesService.GetDocumentReservedFieldNames(); } diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingServiceBase.cs b/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingServiceBase.cs index b1847c80da0f..c00d1bf9ff8f 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingServiceBase.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/ContentTypeEditingServiceBase.cs @@ -6,6 +6,17 @@ namespace Umbraco.Cms.Core.Services.ContentTypeEditing; +/// +/// Abstract base class providing common functionality for content type editing services. +/// +/// The type of content type being edited (e.g., , , ). +/// The service type for managing the content type. +/// The model type for property type definitions. +/// The model type for property type containers (groups/tabs). +/// +/// This base class provides shared validation, mapping, and update logic for all content type +/// editing services including document types, media types, and member types. +/// internal abstract class ContentTypeEditingServiceBase where TContentType : class, IContentTypeComposition where TContentTypeService : IContentTypeBaseService @@ -17,6 +28,15 @@ internal abstract class ContentTypeEditingServiceBase + /// Initializes a new instance of the class. + /// + /// The content type service for cross-type operations. + /// The specific content type service for the type being edited. + /// The data type service for validating property data types. + /// The entity service for resolving entity relationships. + /// The helper for generating safe aliases. protected ContentTypeEditingServiceBase( IContentTypeService contentTypeService, TContentTypeService concreteContentTypeService, @@ -31,14 +51,38 @@ protected ContentTypeEditingServiceBase( _shortStringHelper = shortStringHelper; } + /// + /// Creates a new content type instance. + /// + /// The helper for generating safe aliases. + /// The ID of the parent content type or container. + /// A new instance of the content type. protected abstract TContentType CreateContentType(IShortStringHelper shortStringHelper, int parentId); + /// + /// Gets a value indicating whether this content type supports publishing workflow. + /// + /// true for document types; false for media and member types. protected abstract bool SupportsPublishing { get; } + /// + /// Gets the Umbraco object type for this content type. + /// protected abstract UmbracoObjectTypes ContentTypeObjectType { get; } + /// + /// Gets the Umbraco object type for containers (folders) of this content type. + /// protected abstract UmbracoObjectTypes ContainerObjectType { get; } + /// + /// Finds available compositions for a content type. + /// + /// The unique identifier of the content type, or null for a new content type. + /// The keys of currently selected compositions. + /// The aliases of properties currently defined on the content type. + /// Whether the content type is configured as an element type. + /// A collection of available composition results. protected async Task> FindAvailableCompositionsAsync( Guid? key, IEnumerable currentCompositeKeys, @@ -62,6 +106,16 @@ protected async Task> FindAv return availableCompositions.Results; } + /// + /// Validates and maps a model for creating a new content type. + /// + /// The creation model to validate and map. + /// The optional explicit key for the new content type. + /// The optional key of the container (folder) to create the content type in. + /// + /// An containing the mapped content type on success, + /// or a indicating the validation failure reason. + /// protected async Task> ValidateAndMapForCreationAsync(ContentTypeEditingModelBase model, Guid? key, Guid? containerKey) { SanitizeModelAliases(model); @@ -111,6 +165,15 @@ protected async Task> FindAv return Attempt.SucceedWithStatus(ContentTypeOperationStatus.Success, contentType); } + /// + /// Validates and maps a model for updating an existing content type. + /// + /// The existing content type to update. + /// The update model to validate and map. + /// + /// An containing the updated content type on success, + /// or a indicating the validation failure reason. + /// protected async Task> ValidateAndMapForUpdateAsync(TContentType contentType, ContentTypeEditingModelBase model) { SanitizeModelAliases(model); @@ -142,12 +205,22 @@ protected async Task> FindAv return Attempt.SucceedWithStatus(ContentTypeOperationStatus.Success, contentType); } + /// + /// Performs additional validation specific to the content type being created. + /// + /// The model to validate. + /// The validation status. + /// Override this method to add content-type-specific creation validation. protected virtual Task AdditionalCreateValidationAsync( ContentTypeEditingModelBase model) => Task.FromResult(ContentTypeOperationStatus.Success); #region Sanitization + /// + /// Sanitizes all aliases in the model to ensure they are safe for use. + /// + /// The model containing aliases to sanitize. private void SanitizeModelAliases(ContentTypeEditingModelBase model) { model.Alias = model.Alias.ToSafeAlias(_shortStringHelper); @@ -161,6 +234,13 @@ private void SanitizeModelAliases(ContentTypeEditingModelBase + /// Performs comprehensive validation on the content type model. + /// + /// The model to validate. + /// The existing content type (for updates) or null (for creates). + /// All existing content type compositions for validation. + /// The validation status. private async Task ValidateAsync(ContentTypeEditingModelBase model, TContentType? contentType, IContentTypeComposition[] allContentTypeCompositions) { // validate all model aliases (content type alias, property type aliases) @@ -201,6 +281,11 @@ private async Task ValidateAsync(ContentTypeEditingM return ContentTypeOperationStatus.Success; } + /// + /// Validates all aliases in the model for correctness and uniqueness. + /// + /// The model to validate. + /// The validation status. private ContentTypeOperationStatus ValidateModelAliases(ContentTypeEditingModelBase model) { // Validate model alias is not reserved. @@ -236,6 +321,11 @@ private ContentTypeOperationStatus ValidateModelAliases(ContentTypeEditingModelB return ContentTypeOperationStatus.Success; } + /// + /// Validates that all data types referenced by properties exist. + /// + /// The model to validate. + /// The validation status. private async Task ValidateDataTypesAsync(ContentTypeEditingModelBase model) { Guid[] dataTypeKeys = GetDataTypeKeys(model); @@ -249,6 +339,12 @@ private async Task ValidateDataTypesAsync(ContentTyp return ContentTypeOperationStatus.Success; } + /// + /// Validates inheritance and parent container relationships for a new content type. + /// + /// The model to validate. + /// The optional container key. + /// The validation status. private ContentTypeOperationStatus ValidateInheritanceAndParent(ContentTypeEditingModelBase model, Guid? containerKey) { Guid[] inheritedKeys = KeysForCompositionTypes(model, CompositionType.Inheritance); @@ -278,6 +374,12 @@ private ContentTypeOperationStatus ValidateInheritanceAndParent(ContentTypeEditi : ContentTypeOperationStatus.InvalidParent; } + /// + /// Validates inheritance and parent relationships for an existing content type. + /// + /// The existing content type. + /// The update model to validate. + /// The validation status. private ContentTypeOperationStatus ValidateInheritanceAndParent(TContentType contentType, ContentTypeEditingModelBase model) { Guid[] inheritedKeys = KeysForCompositionTypes(model, CompositionType.Inheritance); @@ -317,6 +419,13 @@ private ContentTypeOperationStatus ValidateInheritanceAndParent(TContentType con throw new ArgumentException("The content type parent ID does not match another content type, nor a container", nameof(contentType)); } + /// + /// Validates that the requested compositions are allowed. + /// + /// The existing content type (for updates) or null (for creates). + /// The model to validate. + /// All existing content type compositions. + /// The validation status. private ContentTypeOperationStatus ValidateCompositions(TContentType? contentType, ContentTypeEditingModelBase model, IContentTypeComposition[] allContentTypeCompositions) { // get the content type keys we want to use for compositions @@ -346,6 +455,12 @@ private ContentTypeOperationStatus ValidateCompositions(TContentType? contentTyp return ContentTypeOperationStatus.Success; } + /// + /// Validates that all properties have unique aliases and don't conflict with compositions. + /// + /// The model to validate. + /// All existing content type compositions. + /// The validation status. private static ContentTypeOperationStatus ValidateProperties(ContentTypeEditingModelBase model, IContentTypeComposition[] allContentTypeCompositions) { // grab all content types used for composition and/or inheritance @@ -365,6 +480,12 @@ private static ContentTypeOperationStatus ValidateProperties(ContentTypeEditingM return ContentTypeOperationStatus.Success; } + /// + /// Validates that all containers (property groups/tabs) are properly configured. + /// + /// The model to validate. + /// All existing content type compositions. + /// The validation status. private static ContentTypeOperationStatus ValidateContainers(ContentTypeEditingModelBase model, IContentTypeComposition[] allContentTypeCompositions) { if (model.Containers.Any(container => Enum.TryParse(container.Type, out _) is false)) @@ -409,6 +530,12 @@ private static ContentTypeOperationStatus ValidateContainers(ContentTypeEditingM // This this method gets aliases across documents, members, and media, so it covers it all private bool ContentTypeAliasIsInUse(string alias) => _contentTypeService.GetAllContentTypeAliases().InvariantContains(alias); + /// + /// Checks if an alias can be used for a specific content type. + /// + /// The alias to check. + /// The key of the content type that wants to use the alias. + /// true if the alias can be used; otherwise, false. private bool ContentTypeAliasCanBeUsedFor(string alias, Guid key) { IContentType? existingContentType = _contentTypeService.Get(alias); @@ -420,14 +547,28 @@ private bool ContentTypeAliasCanBeUsedFor(string alias, Guid key) return ContentTypeAliasIsInUse(alias) is false; } + /// + /// Checks if an alias is reserved and cannot be used for content types. + /// + /// The alias to check. + /// true if the alias is reserved; otherwise, false. private static bool IsReservedContentTypeAlias(string alias) { var reservedAliases = new[] { "system" }; return reservedAliases.InvariantContains(alias); } + /// + /// Gets the set of reserved field names that cannot be used as property aliases. + /// + /// The set of reserved field names. protected abstract ISet GetReservedFieldNames(); + /// + /// Checks if the model contains any reserved property type aliases. + /// + /// The model to check. + /// true if any property uses a reserved alias; otherwise, false. private bool ContainsReservedPropertyTypeAlias(ContentTypeEditingModelBase model) { // Because of models builder you cannot have an alias that already exists in IPublishedContent, for instance Path. @@ -437,6 +578,11 @@ private bool ContainsReservedPropertyTypeAlias(ContentTypeEditingModelBase reservedPropertyTypeNames.InvariantContains(propertyType.Alias)); } + /// + /// Checks if an alias is unsafe (empty, whitespace, or contains invalid characters). + /// + /// The alias to check. + /// true if the alias is unsafe; otherwise, false. private bool IsUnsafeAlias(string alias) => alias.IsNullOrWhiteSpace() || alias.Length != alias.ToSafeAlias(_shortStringHelper).Length; @@ -444,6 +590,13 @@ private bool IsUnsafeAlias(string alias) => alias.IsNullOrWhiteSpace() #region Model update + /// + /// Updates a content type with values from the model. + /// + /// The content type to update. + /// The model containing the new values. + /// All existing content type compositions. + /// The updated content type. private async Task UpdateAsync( TContentType contentType, ContentTypeEditingModelBase model, @@ -474,6 +627,12 @@ private async Task UpdateAsync( return contentType; } + /// + /// Updates the allowed child content types for a content type. + /// + /// The content type to update. + /// The model containing the allowed content types. + /// All existing content type compositions. private static void UpdateAllowedContentTypes( TContentType contentType, ContentTypeEditingModelBase model, @@ -502,6 +661,11 @@ private static void UpdateAllowedContentTypes( .ToArray(); } + /// + /// Updates the properties and property groups for a content type. + /// + /// The content type to update. + /// The model containing the property definitions. private async Task UpdatePropertiesAsync( TContentType contentType, ContentTypeEditingModelBase model) @@ -577,6 +741,11 @@ private async Task UpdatePropertiesAsync( } } + /// + /// Generates a property group alias from a container name. + /// + /// The container name to convert. + /// The generated alias in camelCase format. private static string PropertyGroupAlias(string? containerName) { if (containerName.IsNullOrWhiteSpace()) @@ -588,6 +757,15 @@ private static string PropertyGroupAlias(string? containerName) return $"{parts.First().ToFirstLowerInvariant()}{string.Join(string.Empty, parts.Skip(1).Select(part => part.ToFirstUpperInvariant()))}"; } + /// + /// Maps a property model to an . + /// + /// The content type the property belongs to. + /// The property model to map. + /// The property group the property belongs to, or null for ungrouped properties. + /// Existing property types for reference. + /// Dictionary of data types keyed by their unique identifier. + /// The mapped property type. private IPropertyType MapProperty( TContentType contentType, TPropertyTypeModel property, @@ -629,6 +807,12 @@ private IPropertyType MapProperty( return propertyType; } + /// + /// Updates the compositions for a content type. + /// + /// The content type to update. + /// The model containing the composition definitions. + /// All existing content type compositions. private static void UpdateCompositions( TContentType contentType, ContentTypeEditingModelBase model, @@ -662,6 +846,12 @@ private static void UpdateCompositions( } } + /// + /// Updates the parent content type (inheritance) for a content type. + /// + /// The content type to update. + /// The model containing the inheritance definition. + /// All existing content type compositions. private static void UpdateParentContentType( TContentType contentType, ContentTypeEditingModelBase model, @@ -681,9 +871,19 @@ private static void UpdateParentContentType( #region Shared between model validation and model update + /// + /// Gets the unique data type keys from a model. + /// + /// The model to extract keys from. + /// An array of unique data type keys. private static Guid[] GetDataTypeKeys(ContentTypeEditingModelBase model) => model.Properties.Select(property => property.DataTypeKey).Distinct().ToArray(); + /// + /// Gets the data types referenced by properties in the model. + /// + /// The model containing property definitions. + /// An array of data types. private async Task GetDataTypesAsync(ContentTypeEditingModelBase model) { Guid[] dataTypeKeys = GetDataTypeKeys(model); @@ -692,6 +892,12 @@ private async Task GetDataTypesAsync(ContentTypeEditingModelBase + /// Gets the parent ID for a content type based on inheritance or container placement. + /// + /// The model containing composition definitions. + /// The optional container key. + /// The parent ID, or null if no valid parent could be determined. private int? GetParentId(ContentTypeEditingModelBase model, Guid? containerKey) { Guid[] inheritedKeys = KeysForCompositionTypes(model, CompositionType.Inheritance); @@ -715,12 +921,22 @@ private async Task GetDataTypesAsync(ContentTypeEditingModelBase + /// Gets the keys of compositions matching the specified composition types. + /// + /// The model containing composition definitions. + /// The composition types to filter by. + /// An array of composition keys. private static Guid[] KeysForCompositionTypes(ContentTypeEditingModelBase model, params CompositionType[] compositionTypes) => model.Compositions .Where(c => compositionTypes.Contains(c.CompositionType)) .Select(c => c.Key) .ToArray(); + /// + /// Gets all content type compositions from the service. + /// + /// An array of all content type compositions. private IContentTypeComposition[] GetAllContentTypeCompositions() // NOTE: using Cast here is OK, because we implicitly enforce the constraint TContentType : IContentTypeComposition => _concreteContentTypeService.GetAll().Cast().ToArray(); diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/ElementSwitchValidator.cs b/src/Umbraco.Core/Services/ContentTypeEditing/ElementSwitchValidator.cs index 4d41e78b1e32..63561eb056ea 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/ElementSwitchValidator.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/ElementSwitchValidator.cs @@ -4,12 +4,25 @@ namespace Umbraco.Cms.Core.Services.ContentTypeEditing; +/// +/// Implementation of for validating element type switching operations. +/// +/// +/// This validator checks constraints when switching content types between document and element modes, +/// ensuring data integrity and preventing invalid configurations. +/// public class ElementSwitchValidator : IElementSwitchValidator { private readonly IContentTypeService _contentTypeService; private readonly PropertyEditorCollection _propertyEditorCollection; private readonly IDataTypeService _dataTypeService; + /// + /// Initializes a new instance of the class. + /// + /// The content type service for querying content type hierarchies. + /// The collection of property editors to check for block structure support. + /// The data type service for querying data type configurations. public ElementSwitchValidator( IContentTypeService contentTypeService, PropertyEditorCollection propertyEditorCollection, @@ -20,6 +33,7 @@ public ElementSwitchValidator( _dataTypeService = dataTypeService; } + /// public Task AncestorsAreAlignedAsync(IContentType contentType) { // this call does not return the system roots @@ -35,6 +49,7 @@ public Task AncestorsAreAlignedAsync(IContentType contentType) .Any(ancestor => ancestor.IsElement != contentType.IsElement) is false); } + /// public Task DescendantsAreAlignedAsync(IContentType contentType) { IEnumerable descendants = _contentTypeService.GetDescendants(contentType.Id, false); @@ -43,6 +58,7 @@ public Task DescendantsAreAlignedAsync(IContentType contentType) return Task.FromResult(descendants.Any(descendant => descendant.IsElement != contentType.IsElement) is false); } + /// public async Task ElementToDocumentNotUsedInBlockStructuresAsync(IContentTypeBase contentType) { // get all propertyEditors that support block usage @@ -59,6 +75,7 @@ public async Task ElementToDocumentNotUsedInBlockStructuresAsync(IContentT .ConfiguredElementTypeKeys().Contains(contentType.Key)) is false; } + /// public Task DocumentToElementHasNoContentAsync(IContentTypeBase contentType) => // if any content for the content type exists, the validation fails. diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/IContentTypeEditingService.cs b/src/Umbraco.Core/Services/ContentTypeEditing/IContentTypeEditingService.cs index 672bc00f7a17..aa7e3bbb5d75 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/IContentTypeEditingService.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/IContentTypeEditingService.cs @@ -1,15 +1,52 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentTypeEditing; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services.ContentTypeEditing; +/// +/// Service interface for creating and managing document types (content types) in the Umbraco backoffice. +/// +/// +/// This service provides operations for creating, updating, and querying document types, +/// including support for compositions and inheritance hierarchies. +/// public interface IContentTypeEditingService { + /// + /// Creates a new document type based on the provided model. + /// + /// The model containing the document type definition including properties, compositions, and templates. + /// The unique identifier of the user performing the operation. + /// + /// An containing the created on success, + /// or a indicating the reason for failure. + /// Task> CreateAsync(ContentTypeCreateModel model, Guid userKey); + /// + /// Updates an existing document type with the provided model data. + /// + /// The existing document type to update. + /// The model containing the updated document type definition. + /// The unique identifier of the user performing the operation. + /// + /// An containing the updated on success, + /// or a indicating the reason for failure. + /// Task> UpdateAsync(IContentType contentType, ContentTypeUpdateModel model, Guid userKey); + /// + /// Gets the available compositions for a document type. + /// + /// The unique identifier of the document type, or null for a new document type. + /// The keys of currently selected compositions. + /// The aliases of properties currently defined on the document type. + /// Whether the document type is configured as an element type. + /// + /// A collection of indicating which compositions + /// are available and which are not allowed due to conflicts. + /// Task> GetAvailableCompositionsAsync( Guid? key, IEnumerable currentCompositeKeys, diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/IElementSwitchValidator.cs b/src/Umbraco.Core/Services/ContentTypeEditing/IElementSwitchValidator.cs index 8816f99ec812..51d000d6c718 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/IElementSwitchValidator.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/IElementSwitchValidator.cs @@ -2,13 +2,71 @@ namespace Umbraco.Cms.Core.Services.ContentTypeEditing; +/// +/// Validator interface for checking constraints when switching a content type between document and element type modes. +/// +/// +/// Element types are content types that can only be used within block-based property editors +/// (like Block List or Block Grid) and cannot have content nodes created directly. +/// This validator ensures that switching between document and element modes is safe. +/// public interface IElementSwitchValidator { + /// + /// Validates whether all ancestor content types have the same element flag as the specified content type. + /// + /// The content type to validate. + /// + /// true if all ancestors have the same value + /// as the specified content type; otherwise, false. + /// + /// + /// This validation ensures consistency in inheritance hierarchies where all types + /// should be either document types or element types. + /// Task AncestorsAreAlignedAsync(IContentType contentType); + /// + /// Validates whether all descendant content types have the same element flag as the specified content type. + /// + /// The content type to validate. + /// + /// true if all descendants have the same value + /// as the specified content type; otherwise, false. + /// + /// + /// This validation ensures consistency in inheritance hierarchies where all types + /// should be either document types or element types. + /// Task DescendantsAreAlignedAsync(IContentType contentType); + /// + /// Validates whether an element type can be converted to a document type by checking + /// if it is used in any block structure configurations. + /// + /// The content type to validate. + /// + /// true if the element type is not used in any block structure configurations + /// and can safely be converted to a document type; otherwise, false. + /// + /// + /// Element types used in Block List, Block Grid, or other block-based property editors + /// cannot be converted to document types while they are still referenced. + /// Task ElementToDocumentNotUsedInBlockStructuresAsync(IContentTypeBase contentType); + /// + /// Validates whether a document type can be converted to an element type by checking + /// if any content nodes exist for the content type. + /// + /// The content type to validate. + /// + /// true if no content nodes exist for the content type and it can safely + /// be converted to an element type; otherwise, false. + /// + /// + /// Document types with existing content cannot be converted to element types + /// because element types cannot have directly created content nodes. + /// Task DocumentToElementHasNoContentAsync(IContentTypeBase contentType); } diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/IMediaTypeEditingService.cs b/src/Umbraco.Core/Services/ContentTypeEditing/IMediaTypeEditingService.cs index e712fc66a2c1..76e4897fb477 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/IMediaTypeEditingService.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/IMediaTypeEditingService.cs @@ -1,21 +1,82 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentTypeEditing; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services.ContentTypeEditing; +/// +/// Service interface for creating and managing media types in the Umbraco backoffice. +/// +/// +/// This service provides operations for creating, updating, and querying media types, +/// including support for compositions and file extension filtering. +/// public interface IMediaTypeEditingService { + /// + /// Creates a new media type based on the provided model. + /// + /// The model containing the media type definition including properties and compositions. + /// The unique identifier of the user performing the operation. + /// + /// An containing the created on success, + /// or a indicating the reason for failure. + /// Task> CreateAsync(MediaTypeCreateModel model, Guid userKey); + /// + /// Updates an existing media type with the provided model data. + /// + /// The existing media type to update. + /// The model containing the updated media type definition. + /// The unique identifier of the user performing the operation. + /// + /// An containing the updated on success, + /// or a indicating the reason for failure. + /// Task> UpdateAsync(IMediaType mediaType, MediaTypeUpdateModel model, Guid userKey); + /// + /// Gets the available compositions for a media type. + /// + /// The unique identifier of the media type, or null for a new media type. + /// The keys of currently selected compositions. + /// The aliases of properties currently defined on the media type. + /// + /// A collection of indicating which compositions + /// are available and which are not allowed due to conflicts. + /// Task> GetAvailableCompositionsAsync( Guid? key, IEnumerable currentCompositeKeys, IEnumerable currentPropertyAliases); + /// + /// Gets media types that support a specific file extension. + /// + /// The file extension to filter by (with or without the leading period). + /// The number of items to skip for pagination. + /// The number of items to return for pagination. + /// + /// A containing media types that can handle the specified file extension. + /// + /// + /// This method checks media types with an umbracoFile property and filters based on + /// the configured allowed file extensions in the file upload data type configuration. + /// Task> GetMediaTypesForFileExtensionAsync(string fileExtension, int skip, int take); + /// + /// Gets media types that are considered folder types. + /// + /// The number of items to skip for pagination. + /// The number of items to return for pagination. + /// + /// A containing media types that function as folders. + /// + /// + /// A media type is considered a folder type if it does not have an umbracoFile property + /// and has allowed child types configured. + /// Task> GetFolderMediaTypes(int skip, int take); } diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/IMemberTypeEditingService.cs b/src/Umbraco.Core/Services/ContentTypeEditing/IMemberTypeEditingService.cs index 9309e4c45a8e..021cd35412db 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/IMemberTypeEditingService.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/IMemberTypeEditingService.cs @@ -4,12 +4,49 @@ namespace Umbraco.Cms.Core.Services.ContentTypeEditing; +/// +/// Service interface for creating and managing member types in the Umbraco backoffice. +/// +/// +/// This service provides operations for creating, updating, and querying member types, +/// including support for compositions and member-specific property configurations +/// such as sensitivity and visibility settings. +/// public interface IMemberTypeEditingService { + /// + /// Creates a new member type based on the provided model. + /// + /// The model containing the member type definition including properties and compositions. + /// The unique identifier of the user performing the operation. + /// + /// An containing the created on success, + /// or a indicating the reason for failure. + /// Task> CreateAsync(MemberTypeCreateModel model, Guid userKey); + /// + /// Updates an existing member type with the provided model data. + /// + /// The existing member type to update. + /// The model containing the updated member type definition. + /// The unique identifier of the user performing the operation. + /// + /// An containing the updated on success, + /// or a indicating the reason for failure. + /// Task> UpdateAsync(IMemberType memberType, MemberTypeUpdateModel model, Guid userKey); + /// + /// Gets the available compositions for a member type. + /// + /// The unique identifier of the member type, or null for a new member type. + /// The keys of currently selected compositions. + /// The aliases of properties currently defined on the member type. + /// + /// A collection of indicating which compositions + /// are available and which are not allowed due to conflicts. + /// Task> GetAvailableCompositionsAsync( Guid? key, IEnumerable currentCompositeKeys, diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/MediaTypeEditingService.cs b/src/Umbraco.Core/Services/ContentTypeEditing/MediaTypeEditingService.cs index 4955eeec9cd1..46e2f0699f8b 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/MediaTypeEditingService.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/MediaTypeEditingService.cs @@ -8,6 +8,13 @@ namespace Umbraco.Cms.Core.Services.ContentTypeEditing; +/// +/// Implementation of for managing media types. +/// +/// +/// This service handles creating and updating media types including their properties, +/// compositions, and file extension configurations for upload property editors. +/// internal sealed class MediaTypeEditingService : ContentTypeEditingServiceBase, IMediaTypeEditingService { private readonly IMediaTypeService _mediaTypeService; @@ -15,6 +22,16 @@ internal sealed class MediaTypeEditingService : ContentTypeEditingServiceBase + /// Initializes a new instance of the class. + /// + /// The content type service for composition validation. + /// The media type service for managing media types. + /// The data type service for validating property data types. + /// The entity service for resolving entity relationships. + /// The helper for generating safe aliases. + /// The image URL generator for determining supported image formats. + /// The service providing reserved field names. public MediaTypeEditingService( IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, @@ -31,6 +48,7 @@ public MediaTypeEditingService( _reservedFieldNamesService = reservedFieldNamesService; } + /// public async Task> CreateAsync(MediaTypeCreateModel model, Guid userKey) { Attempt result = await ValidateAndMapForCreationAsync(model, model.Key, model.ContainerKey); @@ -43,6 +61,7 @@ public MediaTypeEditingService( return result; } + /// public async Task> UpdateAsync(IMediaType mediaType, MediaTypeUpdateModel model, Guid userKey) { if (mediaType.IsSystemMediaType() && mediaType.Alias != model.Alias) @@ -60,12 +79,14 @@ public MediaTypeEditingService( return result; } + /// public async Task> GetAvailableCompositionsAsync( Guid? key, IEnumerable currentCompositeKeys, IEnumerable currentPropertyAliases) => await FindAvailableCompositionsAsync(key, currentCompositeKeys, currentPropertyAliases); + /// public async Task> GetMediaTypesForFileExtensionAsync(string fileExtension, int skip, int take) { fileExtension = fileExtension.TrimStart(Constants.CharArrays.Period); @@ -110,6 +131,7 @@ public async Task> GetMediaTypesForFileExtensionAsync(str } + /// public Task> GetFolderMediaTypes(int skip, int take) { // we'll consider it a "folder" media type if it: @@ -139,17 +161,30 @@ public Task> GetFolderMediaTypes(int skip, int take) }); } + /// protected override IMediaType CreateContentType(IShortStringHelper shortStringHelper, int parentId) => new MediaType(shortStringHelper, parentId); + /// protected override bool SupportsPublishing => false; + /// protected override UmbracoObjectTypes ContentTypeObjectType => UmbracoObjectTypes.MediaType; + /// protected override UmbracoObjectTypes ContainerObjectType => UmbracoObjectTypes.MediaTypeContainer; + /// protected override ISet GetReservedFieldNames() => _reservedFieldNamesService.GetMediaReservedFieldNames(); + /// + /// Fetches the allowed file extensions for each media type based on their upload field configuration. + /// + /// The media types to check. + /// + /// A dictionary mapping each media type to its allowed file extensions. + /// An empty collection indicates all file extensions are allowed. + /// private async Task>> FetchAllowedFileExtensionsByMediaTypeAsync(IEnumerable mediaTypes) { var allowedFileExtensionsByMediaType = new Dictionary>(); diff --git a/src/Umbraco.Core/Services/ContentTypeEditing/MemberTypeEditingService.cs b/src/Umbraco.Core/Services/ContentTypeEditing/MemberTypeEditingService.cs index f1d38d3dd6dc..651ffda1666c 100644 --- a/src/Umbraco.Core/Services/ContentTypeEditing/MemberTypeEditingService.cs +++ b/src/Umbraco.Core/Services/ContentTypeEditing/MemberTypeEditingService.cs @@ -6,12 +6,29 @@ namespace Umbraco.Cms.Core.Services.ContentTypeEditing; +/// +/// Implementation of for managing member types. +/// +/// +/// This service handles creating and updating member types including their properties, +/// compositions, and member-specific settings such as property sensitivity and visibility. +/// internal sealed class MemberTypeEditingService : ContentTypeEditingServiceBase, IMemberTypeEditingService { private readonly IMemberTypeService _memberTypeService; private readonly IUserService _userService; private readonly IReservedFieldNamesService _reservedFieldNamesService; + /// + /// Initializes a new instance of the class. + /// + /// The content type service for composition validation. + /// The member type service for managing member types. + /// The data type service for validating property data types. + /// The entity service for resolving entity relationships. + /// The helper for generating safe aliases. + /// The user service for validating user permissions. + /// The service providing reserved field names. public MemberTypeEditingService( IContentTypeService contentTypeService, IMemberTypeService memberTypeService, @@ -27,6 +44,7 @@ public MemberTypeEditingService( _reservedFieldNamesService = reservedFieldNamesService; } + /// public async Task> CreateAsync(MemberTypeCreateModel model, Guid userKey) { Attempt result = await ValidateAndMapForCreationAsync(model, model.Key, model.ContainerKey); @@ -47,6 +65,7 @@ public MemberTypeEditingService( return result; } + /// public async Task> UpdateAsync(IMemberType memberType, MemberTypeUpdateModel model, Guid userKey) { Attempt result = await ValidateAndMapForUpdateAsync(memberType, model); @@ -67,23 +86,34 @@ public MemberTypeEditingService( return result; } + /// public async Task> GetAvailableCompositionsAsync( Guid? key, IEnumerable currentCompositeKeys, IEnumerable currentPropertyAliases) => await FindAvailableCompositionsAsync(key, currentCompositeKeys, currentPropertyAliases); + /// protected override IMemberType CreateContentType(IShortStringHelper shortStringHelper, int parentId) => new MemberType(shortStringHelper, parentId); + /// protected override bool SupportsPublishing => false; + /// protected override UmbracoObjectTypes ContentTypeObjectType => UmbracoObjectTypes.MemberType; + /// protected override UmbracoObjectTypes ContainerObjectType => UmbracoObjectTypes.MemberTypeContainer; + /// protected override ISet GetReservedFieldNames() => _reservedFieldNamesService.GetMemberReservedFieldNames(); + /// + /// Updates the visibility settings for member type properties. + /// + /// The member type to update. + /// The model containing property visibility settings. private void UpdatePropertyTypeVisibility(IMemberType memberType, MemberTypeModelBase model) { foreach (MemberTypePropertyTypeModel propertyType in model.Properties) @@ -93,6 +123,19 @@ private void UpdatePropertyTypeVisibility(IMemberType memberType, MemberTypeMode } } + /// + /// Updates the sensitivity settings for member type properties. + /// + /// The member type to update. + /// The model containing property sensitivity settings. + /// The unique identifier of the user performing the operation. + /// + /// true if the sensitivity settings were updated successfully; + /// false if the user does not have permission to change sensitivity settings. + /// + /// + /// Only users with access to sensitive data can modify the sensitivity flag on properties. + /// private async Task UpdatePropertyTypeSensitivity(IMemberType memberType, MemberTypeModelBase model, Guid userKey) { IUser user = await _userService.GetAsync(userKey) diff --git a/src/Umbraco.Core/Services/ContentTypeService.cs b/src/Umbraco.Core/Services/ContentTypeService.cs index dcd79468c929..cd70a27d3187 100644 --- a/src/Umbraco.Core/Services/ContentTypeService.cs +++ b/src/Umbraco.Core/Services/ContentTypeService.cs @@ -21,6 +21,21 @@ public class ContentTypeService : ContentTypeServiceBase + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The content service. + /// The content type repository. + /// The audit service. + /// The document type container repository. + /// The entity repository. + /// The event aggregator. + /// The user ID key resolver. + /// The content type filter collection. + /// The template service. public ContentTypeService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -50,6 +65,20 @@ public ContentTypeService( ContentService = contentService; } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The content service. + /// The content type repository. + /// The audit service. + /// The document type container repository. + /// The entity repository. + /// The event aggregator. + /// The user ID key resolver. + /// The content type filter collection. [Obsolete("Use the non-obsolete constructor. Scheduled for removal in Umbraco 19.")] public ContentTypeService( ICoreScopeProvider provider, @@ -79,6 +108,20 @@ public ContentTypeService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The content service. + /// The content type repository. + /// The audit repository (obsolete). + /// The document type container repository. + /// The entity repository. + /// The event aggregator. + /// The user ID key resolver. + /// The content type filter collection. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public ContentTypeService( ICoreScopeProvider provider, @@ -108,6 +151,21 @@ public ContentTypeService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The content service. + /// The content type repository. + /// The audit repository (obsolete). + /// The audit service. + /// The document type container repository. + /// The entity repository. + /// The event aggregator. + /// The user ID key resolver. + /// The content type filter collection. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public ContentTypeService( ICoreScopeProvider provider, @@ -138,6 +196,22 @@ public ContentTypeService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The content service. + /// The content type repository. + /// The audit repository (obsolete). + /// The audit service. + /// The document type container repository. + /// The entity repository. + /// The event aggregator. + /// The user ID key resolver. + /// The content type filter collection. + /// The template service. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public ContentTypeService( ICoreScopeProvider provider, @@ -169,12 +243,18 @@ public ContentTypeService( { } + /// protected override int[] ReadLockIds => ContentTypeLocks.ReadLockIds; + /// protected override int[] WriteLockIds => ContentTypeLocks.WriteLockIds; + /// protected override Guid ContainedObjectType => Constants.ObjectTypes.DocumentType; + /// + /// Gets the content service. + /// private IContentService ContentService { get; } /// @@ -224,6 +304,12 @@ public IEnumerable GetAllContentTypeIds(string[] aliases) } } + /// + /// Gets content types by query. + /// + /// The query to filter content types. + /// The cancellation token. + /// A collection of content types matching the query. public async Task> GetByQueryAsync(IQuery query, CancellationToken cancellationToken) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -276,6 +362,7 @@ public async Task> GetByQueryAsync(IQuery.Fail(updateContentTypeResult.Result); } + /// protected override void DeleteItemsOfTypes(IEnumerable typeIds) { using (ICoreScope scope = ScopeProvider.CreateCoreScope()) @@ -289,46 +376,57 @@ protected override void DeleteItemsOfTypes(IEnumerable typeIds) #region Notifications + /// protected override SavingNotification GetSavingNotification( IContentType item, EventMessages eventMessages) => new ContentTypeSavingNotification(item, eventMessages); + /// protected override SavingNotification GetSavingNotification( IEnumerable items, EventMessages eventMessages) => new ContentTypeSavingNotification(items, eventMessages); + /// protected override SavedNotification GetSavedNotification( IContentType item, EventMessages eventMessages) => new ContentTypeSavedNotification(item, eventMessages); + /// protected override SavedNotification GetSavedNotification( IEnumerable items, EventMessages eventMessages) => new ContentTypeSavedNotification(items, eventMessages); + /// protected override DeletingNotification GetDeletingNotification( IContentType item, EventMessages eventMessages) => new ContentTypeDeletingNotification(item, eventMessages); + /// protected override DeletingNotification GetDeletingNotification( IEnumerable items, EventMessages eventMessages) => new ContentTypeDeletingNotification(items, eventMessages); + /// protected override DeletedNotification GetDeletedNotification( IEnumerable items, EventMessages eventMessages) => new ContentTypeDeletedNotification(items, eventMessages); + /// protected override MovingNotification GetMovingNotification( MoveEventInfo moveInfo, EventMessages eventMessages) => new ContentTypeMovingNotification(moveInfo, eventMessages); + /// protected override MovedNotification GetMovedNotification( IEnumerable> moveInfo, EventMessages eventMessages) => new ContentTypeMovedNotification(moveInfo, eventMessages); + /// protected override ContentTypeChangeNotification GetContentTypeChangedNotification( IEnumerable> changes, EventMessages eventMessages) => new ContentTypeChangedNotification(changes, eventMessages); + /// protected override ContentTypeRefreshNotification GetContentTypeRefreshedNotification( IEnumerable> changes, EventMessages eventMessages) => new ContentTypeRefreshedNotification(changes, eventMessages); diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBase.cs b/src/Umbraco.Core/Services/ContentTypeServiceBase.cs index 7549cd849c65..839c907ede0b 100644 --- a/src/Umbraco.Core/Services/ContentTypeServiceBase.cs +++ b/src/Umbraco.Core/Services/ContentTypeServiceBase.cs @@ -4,8 +4,17 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Base class for content type services, providing common repository service functionality. +/// public abstract class ContentTypeServiceBase : RepositoryService { + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. protected ContentTypeServiceBase(ICoreScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory) : base(provider, loggerFactory, eventMessagesFactory) { diff --git a/src/Umbraco.Core/Services/ContentTypeServiceBase{TRepository,TItem}.cs b/src/Umbraco.Core/Services/ContentTypeServiceBase{TRepository,TItem}.cs index 8de37e38fd7e..5a3314702c59 100644 --- a/src/Umbraco.Core/Services/ContentTypeServiceBase{TRepository,TItem}.cs +++ b/src/Umbraco.Core/Services/ContentTypeServiceBase{TRepository,TItem}.cs @@ -18,6 +18,12 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Generic base class for content type services that provides CRUD operations, validation, +/// composition handling, and container management for content types. +/// +/// The type of the content type repository. +/// The type of content type. public abstract class ContentTypeServiceBase : ContentTypeServiceBase, IContentTypeBaseService where TRepository : IContentTypeRepositoryBase where TItem : class, IContentTypeComposition @@ -29,6 +35,19 @@ public abstract class ContentTypeServiceBase : ContentTypeSe private readonly IUserIdKeyResolver _userIdKeyResolver; private readonly ContentTypeFilterCollection _contentTypeFilters; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The content type repository. + /// The audit service. + /// The entity container repository. + /// The entity repository. + /// The event aggregator. + /// The user ID key resolver. + /// The content type filter collection. protected ContentTypeServiceBase( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -51,6 +70,19 @@ protected ContentTypeServiceBase( _contentTypeFilters = contentTypeFilters; } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The content type repository. + /// The audit repository. + /// The entity container repository. + /// The entity repository. + /// The event aggregator. + /// The user ID key resolver. + /// The content type filter collection. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] protected ContentTypeServiceBase( ICoreScopeProvider provider, @@ -77,39 +109,122 @@ protected ContentTypeServiceBase( { } + /// + /// Gets the content type repository. + /// protected TRepository Repository { get; } + + /// + /// Gets the write lock IDs for this content type. + /// protected abstract int[] WriteLockIds { get; } + + /// + /// Gets the read lock IDs for this content type. + /// protected abstract int[] ReadLockIds { get; } #region Notifications + /// + /// Gets a saving notification for a single content type item. + /// + /// The content type item being saved. + /// The event messages. + /// The saving notification. protected abstract SavingNotification GetSavingNotification(TItem item, EventMessages eventMessages); + + /// + /// Gets a saving notification for multiple content type items. + /// + /// The content type items being saved. + /// The event messages. + /// The saving notification. protected abstract SavingNotification GetSavingNotification(IEnumerable items, EventMessages eventMessages); + /// + /// Gets a saved notification for a single content type item. + /// + /// The content type item that was saved. + /// The event messages. + /// The saved notification. protected abstract SavedNotification GetSavedNotification(TItem item, EventMessages eventMessages); + + /// + /// Gets a saved notification for multiple content type items. + /// + /// The content type items that were saved. + /// The event messages. + /// The saved notification. protected abstract SavedNotification GetSavedNotification(IEnumerable items, EventMessages eventMessages); + /// + /// Gets a deleting notification for a single content type item. + /// + /// The content type item being deleted. + /// The event messages. + /// The deleting notification. protected abstract DeletingNotification GetDeletingNotification(TItem item, EventMessages eventMessages); + + /// + /// Gets a deleting notification for multiple content type items. + /// + /// The content type items being deleted. + /// The event messages. + /// The deleting notification. protected abstract DeletingNotification GetDeletingNotification(IEnumerable items, EventMessages eventMessages); + /// + /// Gets a deleted notification for multiple content type items. + /// + /// The content type items that were deleted. + /// The event messages. + /// The deleted notification. protected abstract DeletedNotification GetDeletedNotification(IEnumerable items, EventMessages eventMessages); + /// + /// Gets a moving notification for a content type item. + /// + /// The move event information. + /// The event messages. + /// The moving notification. protected abstract MovingNotification GetMovingNotification(MoveEventInfo moveInfo, EventMessages eventMessages); + /// + /// Gets a moved notification for multiple content type items. + /// + /// The collection of move event information. + /// The event messages. + /// The moved notification. protected abstract MovedNotification GetMovedNotification(IEnumerable> moveInfo, EventMessages eventMessages); + /// + /// Gets a content type changed notification. + /// + /// The collection of content type changes. + /// The event messages. + /// The content type changed notification. protected abstract ContentTypeChangeNotification GetContentTypeChangedNotification(IEnumerable> changes, EventMessages eventMessages); - // This notification is identical to GetTypeChangeNotification, however it needs to be a different notification type because it's published within the transaction - /// The purpose of this notification being published within the transaction is so that listeners can perform database - /// operations from within the same transaction and guarantee data consistency so that if anything goes wrong - /// the entire transaction can be rolled back. This is used by Nucache. + /// + /// Gets a content type refreshed notification that is published within the transaction. + /// + /// The collection of content type changes. + /// The event messages. + /// The content type refreshed notification. + /// + /// This notification is identical to GetContentTypeChangedNotification, however it needs to be a different notification type + /// because it's published within the transaction. The purpose of this notification being published within the transaction + /// is so that listeners can perform database operations from within the same transaction and guarantee data consistency + /// so that if anything goes wrong the entire transaction can be rolled back. This is used by Nucache. + /// protected abstract ContentTypeRefreshNotification GetContentTypeRefreshedNotification(IEnumerable> changes, EventMessages eventMessages); #endregion #region Validation + /// public Attempt ValidateComposition(TItem? compo) { try @@ -128,6 +243,11 @@ protected ContentTypeServiceBase( } } + /// + /// Validates a content type composition for conflicts within a lock context. + /// + /// The content type to validate. + /// Thrown when the composition is invalid. protected void ValidateLocked(TItem compositionContentType) { // performs business-level validation of the composition @@ -214,6 +334,12 @@ protected void ValidateLocked(TItem compositionContentType) #region Composition + /// + /// Composes the content type changes for the specified content types by analyzing what properties + /// have changed and determining the impact on related content types. + /// + /// The content types to analyze for changes. + /// A collection of content type changes indicating which types were affected and how. internal IEnumerable> ComposeContentTypeChanges(params TItem[] contentTypes) { // find all content types impacted by the changes, @@ -301,7 +427,13 @@ internal IEnumerable> ComposeContentTypeChanges(params return changes; } - // ensures changes contains no duplicates + /// + /// Adds a content type change to the collection, merging change types if the content type already exists in the collection. + /// + /// The collection of changes to add to. + /// The content type that changed. + /// The types of changes that occurred. + /// Ensures the changes collection contains no duplicates by merging change types. private static void AddChange(ICollection> changes, TItem contentType, ContentTypeChangeTypes changeTypes) { ContentTypeChange? change = changes.FirstOrDefault(x => x.Item == contentType); @@ -318,11 +450,13 @@ private static void AddChange(ICollection> changes, TIt #region Get, Has, Is, Count + /// IContentTypeComposition? IContentTypeBaseService.Get(int id) { return Get(id); } + /// public TItem? Get(int id) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -330,6 +464,7 @@ private static void AddChange(ICollection> changes, TIt return Repository.Get(id); } + /// public TItem? Get(string alias) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -337,6 +472,7 @@ private static void AddChange(ICollection> changes, TIt return Repository.Get(alias); } + /// public TItem? Get(Guid id) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -347,6 +483,7 @@ private static void AddChange(ICollection> changes, TIt /// public Task GetAsync(Guid guid) => Task.FromResult(Get(guid)); + /// public IEnumerable GetAll() { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -354,6 +491,7 @@ public IEnumerable GetAll() return Repository.GetMany(Array.Empty()); } + /// public IEnumerable GetMany(params int[] ids) { if (ids.Any() is false) @@ -366,6 +504,7 @@ public IEnumerable GetMany(params int[] ids) return Repository.GetMany(ids); } + /// public IEnumerable GetMany(IEnumerable? ids) { if (ids is null || ids.Any() is false) @@ -380,6 +519,7 @@ public IEnumerable GetMany(IEnumerable? ids) } } + /// public IEnumerable GetChildren(int id) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -388,6 +528,7 @@ public IEnumerable GetChildren(int id) return Repository.Get(query); } + /// public IEnumerable GetChildren(Guid id) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -402,6 +543,7 @@ public IEnumerable GetChildren(Guid id) return Repository.Get(query); } + /// public bool HasChildren(int id) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -411,6 +553,7 @@ public bool HasChildren(int id) return count > 0; } + /// public bool HasChildren(Guid id) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -429,10 +572,10 @@ public bool HasChildren(Guid id) } /// - /// Given the path of a content item, this will return true if the content item exists underneath a list view content item + /// Determines whether the content item with the specified path exists underneath a list view content item. /// - /// - /// + /// The path of the content item to check. + /// true if the content item exists underneath a list view; otherwise, false. public bool HasContainerInPath(string contentPath) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -440,6 +583,11 @@ public bool HasContainerInPath(string contentPath) return Repository.HasContainerInPath(contentPath); } + /// + /// Checks whether any of the specified content items exist underneath a list view content item. + /// + /// The IDs of the content items to check. + /// true if any of the content items exist underneath a list view; otherwise, false. public bool HasContainerInPath(params int[] ids) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -447,6 +595,7 @@ public bool HasContainerInPath(params int[] ids) return Repository.HasContainerInPath(ids); } + /// public IEnumerable GetDescendants(int id, bool andSelf) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -484,9 +633,11 @@ public IEnumerable GetDescendants(int id, bool andSelf) return descendants.ToArray(); } + /// public IEnumerable GetComposedOf(int id, IEnumerable all) => all.Where(x => x.ContentTypeComposition.Any(y => y.Id == id)); + /// public IEnumerable GetComposedOf(int id) { // GetAll is cheap, repository has a full dataset cache policy @@ -495,6 +646,7 @@ public IEnumerable GetComposedOf(int id) return GetComposedOf(id, allContentTypes); } + /// public int Count() { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -502,6 +654,7 @@ public int Count() return Repository.Count(Query()); } + /// public bool HasContentNodes(int id) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -513,12 +666,14 @@ public bool HasContentNodes(int id) #region Save + /// public async Task SaveAsync(TItem item, Guid performingUserKey) { var userId = await _userIdKeyResolver.GetAsync(performingUserKey); Save(item, userId); } + /// public void Save(TItem? item, int userId = Constants.Security.SuperUserId) { if (item is null) @@ -574,6 +729,7 @@ public void Save(TItem? item, int userId = Constants.Security.SuperUserId) scope.Complete(); } + /// public void Save(IEnumerable items, int userId = Constants.Security.SuperUserId) { TItem[] itemsA = items.ToArray(); @@ -623,10 +779,18 @@ public void Save(IEnumerable items, int userId = Constants.Security.Super } } + /// public async Task> CreateAsync(TItem item, Guid performingUserKey) => await InternalSaveAsync(item, performingUserKey); + /// public async Task> UpdateAsync(TItem item, Guid performingUserKey) => await InternalSaveAsync(item, performingUserKey); + /// + /// Internal implementation of the save operation with validation and notifications. + /// + /// The content type to save. + /// The unique identifier of the user performing the operation. + /// An attempt indicating the operation status. private async Task> InternalSaveAsync(TItem item, Guid performingUserKey) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -677,6 +841,11 @@ private async Task> InternalSaveAsync(TItem return Attempt.Succeed(ContentTypeOperationStatus.Success); } + /// + /// Validates common properties of a content type. + /// + /// The content type to validate. + /// An attempt indicating the validation result. private Attempt ValidateCommon(TItem item) { if (string.IsNullOrWhiteSpace(item.Name)) @@ -696,6 +865,7 @@ private Attempt ValidateCommon(TItem item) #region Delete + /// public async Task DeleteAsync(Guid key, Guid performingUserKey) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -720,6 +890,7 @@ public async Task DeleteAsync(Guid key, Guid perform return ContentTypeOperationStatus.Success; } + /// public void Delete(TItem item, int userId = Constants.Security.SuperUserId) { if (CanDelete(item) is false) @@ -791,6 +962,7 @@ public void Delete(TItem item, int userId = Constants.Security.SuperUserId) } } + /// public void Delete(IEnumerable items, int userId = Constants.Security.SuperUserId) { TItem[] itemsA = items.ToArray(); @@ -851,14 +1023,31 @@ public void Delete(IEnumerable items, int userId = Constants.Security.Sup } } + /// + /// Deletes content items of the specified types. + /// + /// The type IDs whose content should be deleted. protected abstract void DeleteItemsOfTypes(IEnumerable typeIds); + /// + /// Determines whether the specified content type can be deleted. + /// + /// The content type to check. + /// true if the content type can be deleted; otherwise, false. protected virtual bool CanDelete(TItem item) => true; #endregion #region Copy + /// + /// Copies the specified content type to a new content type with the specified alias and name. + /// + /// The original content type to copy. + /// The alias for the new content type. + /// The name for the new content type. + /// The parent identifier for the new content type. Use -1 for root. + /// The newly created content type copy. [Obsolete("Please use CopyAsync. Will be removed in V15.")] public TItem Copy(TItem original, string alias, string name, int parentId = -1) { @@ -874,6 +1063,14 @@ public TItem Copy(TItem original, string alias, string name, int parentId = -1) return Copy(original, alias, name, parent); } + /// + /// Copies the specified content type to a new content type with the specified alias, name, and parent. + /// + /// The original content type to copy. + /// The alias for the new content type. + /// The name for the new content type. + /// The parent content type for the new content type. Use null for root. + /// The newly created content type copy. [Obsolete("Please use CopyAsync. Will be removed in V15.")] public TItem Copy(TItem original, string alias, string name, TItem? parent) { @@ -929,6 +1126,12 @@ public TItem Copy(TItem original, string alias, string name, TItem? parent) return clone; } + /// + /// Copies a content type to a specified container. + /// + /// The content type to copy. + /// The identifier of the target container. Use -1 for root. + /// An attempt result containing the operation status and the copied content type. [Obsolete("Please use CopyAsync. Will be removed in V16.")] public Attempt?> Copy(TItem copying, int containerId) { @@ -1003,6 +1206,7 @@ public TItem Copy(TItem original, string alias, string name, TItem? parent) return OperationResult.Attempt.Succeed(MoveOperationStatusType.Success, eventMessages, copy); } + /// public async Task> CopyAsync(Guid key, Guid? containerKey) { TItem? toCopy = await GetAsync(key); @@ -1024,6 +1228,11 @@ public TItem Copy(TItem original, string alias, string name, TItem? parent) return MapStatusTypeToAttempt(result.Result?.Entity, result.Result?.Result); } + /// + /// Gets the container ID from a container key, or returns the root ID if no key is specified. + /// + /// The container key, or null for root. + /// The container ID, or null if the container was not found. private int? GetContainerOrRootId(Guid? containerKey) { if (containerKey is null) @@ -1035,6 +1244,12 @@ public TItem Copy(TItem original, string alias, string name, TItem? parent) return container?.Id; } + /// + /// Maps a move operation status type to a content type structure operation status attempt. + /// + /// The content type item. + /// The move operation result status. + /// An attempt with the mapped status. private Attempt MapStatusTypeToAttempt(TItem? item, MoveOperationStatusType? resultStatus) => resultStatus switch { @@ -1049,6 +1264,12 @@ public TItem Copy(TItem original, string alias, string name, TItem? parent) #region Move + /// + /// Moves a content type to a specified container. + /// + /// The content type to move. + /// The identifier of the target container. Use -1 for root. + /// An attempt result containing the operation status. [Obsolete("Please use MoveAsync. Will be removed in V16.")] public Attempt?> Move(TItem moving, int containerId) { @@ -1102,6 +1323,7 @@ public TItem Copy(TItem original, string alias, string name, TItem? parent) return OperationResult.Attempt.Succeed(MoveOperationStatusType.Success, eventMessages); } + /// public async Task> MoveAsync(Guid key, Guid? containerKey) { TItem? toMove = await GetAsync(key); @@ -1205,10 +1427,24 @@ public async Task> GetAllAllowedAsRootAsync(int skip, int take #region Containers + /// + /// Gets the object type GUID for content types contained by this service. + /// protected abstract Guid ContainedObjectType { get; } + /// + /// Gets the container object type GUID. + /// protected Guid ContainerObjectType => EntityContainer.GetContainerObjectType(ContainedObjectType); + /// + /// Creates a new entity container for organizing content types. + /// + /// The parent container identifier. Use -1 for root. + /// The unique key for the container. + /// The name of the container. + /// The identifier of the user creating the container. + /// An attempt result containing the operation status and the created container. [Obsolete($"Please use {nameof(IContentTypeContainerService)} or {nameof(IMediaTypeContainerService)} for all content or media type container operations. Will be removed in V16.")] public Attempt?> CreateContainer(int parentId, Guid key, string name, int userId = Constants.Security.SuperUserId) { @@ -1250,6 +1486,12 @@ public async Task> GetAllAllowedAsRootAsync(int skip, int take } } + /// + /// Saves an entity container. + /// + /// The container to save. + /// The identifier of the user saving the container. + /// An attempt result containing the operation status. [Obsolete($"Please use {nameof(IContentTypeContainerService)} or {nameof(IMediaTypeContainerService)} for all content or media type container operations. Will be removed in V16.")] public Attempt SaveContainer(EntityContainer container, int userId = Constants.Security.SuperUserId) { @@ -1292,6 +1534,11 @@ public async Task> GetAllAllowedAsRootAsync(int skip, int take return OperationResult.Attempt.Succeed(eventMessages); } + /// + /// Gets an entity container by its integer identifier. + /// + /// The integer identifier of the container. + /// The entity container if found; otherwise, null. [Obsolete($"Please use {nameof(IContentTypeContainerService)} or {nameof(IMediaTypeContainerService)} for all content or media type container operations. Will be removed in V16.")] public EntityContainer? GetContainer(int containerId) { @@ -1301,6 +1548,11 @@ public async Task> GetAllAllowedAsRootAsync(int skip, int take return _containerRepository.Get(containerId); } + /// + /// Gets an entity container by its GUID identifier. + /// + /// The GUID identifier of the container. + /// The entity container if found; otherwise, null. [Obsolete($"Please use {nameof(IContentTypeContainerService)} or {nameof(IMediaTypeContainerService)} for all content or media type container operations. Will be removed in V16.")] public EntityContainer? GetContainer(Guid containerId) { @@ -1310,6 +1562,11 @@ public async Task> GetAllAllowedAsRootAsync(int skip, int take return _containerRepository.Get(containerId); } + /// + /// Gets entity containers by their integer identifiers. + /// + /// The array of container identifiers. + /// A collection of entity containers. [Obsolete($"Please use {nameof(IContentTypeContainerService)} or {nameof(IMediaTypeContainerService)} for all content or media type container operations. Will be removed in V16.")] public IEnumerable GetContainers(int[] containerIds) { @@ -1319,6 +1576,11 @@ public IEnumerable GetContainers(int[] containerIds) return _containerRepository.GetMany(containerIds); } + /// + /// Gets the ancestor containers of the specified content type item. + /// + /// The content type item to get ancestor containers for. + /// A collection of ancestor entity containers. [Obsolete($"Please use {nameof(IContentTypeContainerService)} or {nameof(IMediaTypeContainerService)} for all content or media type container operations. Will be removed in V16.")] public IEnumerable GetContainers(TItem item) { @@ -1330,6 +1592,12 @@ public IEnumerable GetContainers(TItem item) return GetContainers(ancestorIds); } + /// + /// Gets entity containers by name and level. + /// + /// The name of the containers to find. + /// The level of the containers in the hierarchy. + /// A collection of entity containers matching the criteria. [Obsolete($"Please use {nameof(IContentTypeContainerService)} or {nameof(IMediaTypeContainerService)} for all content or media type container operations. Will be removed in V16.")] public IEnumerable GetContainers(string name, int level) { @@ -1339,6 +1607,12 @@ public IEnumerable GetContainers(string name, int level) return _containerRepository.Get(name, level); } + /// + /// Deletes an entity container. + /// + /// The identifier of the container to delete. + /// The identifier of the user deleting the container. + /// An attempt result containing the operation status. [Obsolete($"Please use {nameof(IContentTypeContainerService)} or {nameof(IMediaTypeContainerService)} for all content or media type container operations. Will be removed in V16.")] public Attempt DeleteContainer(int containerId, int userId = Constants.Security.SuperUserId) { @@ -1379,6 +1653,13 @@ public IEnumerable GetContainers(string name, int level) // TODO: Audit trail ? } + /// + /// Renames an entity container. + /// + /// The identifier of the container to rename. + /// The new name for the container. + /// The identifier of the user renaming the container. + /// An attempt result containing the operation status and the renamed container. [Obsolete($"Please use {nameof(IContentTypeContainerService)} or {nameof(IMediaTypeContainerService)} for all content or media type container operations. Will be removed in V16.")] public Attempt?> RenameContainer(int id, string name, int userId = Constants.Security.SuperUserId) { @@ -1426,9 +1707,21 @@ public IEnumerable GetContainers(string name, int level) #region Audit + /// + /// Creates an audit entry synchronously. + /// + /// The type of audit entry. + /// The ID of the user performing the action. + /// The ID of the object being audited. private void Audit(AuditType type, int userId, int objectId) => AuditAsync(type, userId, objectId).GetAwaiter().GetResult(); + /// + /// Creates an audit entry asynchronously. + /// + /// The type of audit entry. + /// The ID of the user performing the action. + /// The ID of the object being audited. private async Task AuditAsync(AuditType type, int userId, int objectId) { Guid userKey = await _userIdKeyResolver.GetAsync(userId); diff --git a/src/Umbraco.Core/Services/ContentTypeServiceExtensions.cs b/src/Umbraco.Core/Services/ContentTypeServiceExtensions.cs index 5ae8da3a1236..0b212ff25721 100644 --- a/src/Umbraco.Core/Services/ContentTypeServiceExtensions.cs +++ b/src/Umbraco.Core/Services/ContentTypeServiceExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Umbraco. +// Copyright (c) Umbraco. // See LICENSE for more details. using Umbraco.Cms.Core; @@ -7,6 +7,9 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for the interface. +/// public static class ContentTypeServiceExtensions { /// @@ -140,6 +143,12 @@ public static ContentTypeAvailableCompositionsResults GetAvailableCompositeConte return new ContentTypeAvailableCompositionsResults(ancestors, result); } + /// + /// Gets all ancestor content types for the specified content type. + /// + /// The content type to get ancestors for. + /// All available content types. + /// An array of ancestor content types. private static IContentTypeComposition[] GetAncestors( IContentTypeComposition? ctype, IContentTypeComposition[] allContentTypes) @@ -169,10 +178,10 @@ private static IContentTypeComposition[] GetAncestors( } /// - /// Get those that we use directly + /// Gets all content type compositions that are used directly or indirectly by the specified content type. /// - /// - /// + /// The content type to get compositions for. + /// A collection of direct and indirect content type compositions. private static IEnumerable GetDirectOrIndirect(IContentTypeComposition? ctype) { if (ctype == null) diff --git a/src/Umbraco.Core/Services/ContentValidationService.cs b/src/Umbraco.Core/Services/ContentValidationService.cs index 0f93278c5324..6e3ebf3f3770 100644 --- a/src/Umbraco.Core/Services/ContentValidationService.cs +++ b/src/Umbraco.Core/Services/ContentValidationService.cs @@ -1,15 +1,24 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentEditing; namespace Umbraco.Cms.Core.Services; +/// +/// Provides validation services for content (document) properties and cultures. +/// internal sealed class ContentValidationService : ContentValidationServiceBase, IContentValidationService { + /// + /// Initializes a new instance of the class. + /// + /// The property validation service. + /// The language service. public ContentValidationService(IPropertyValidationService propertyValidationService, ILanguageService languageService) : base(propertyValidationService, languageService) { } + /// public async Task ValidatePropertiesAsync( ContentEditingModelBase contentEditingModelBase, IContentType contentType, diff --git a/src/Umbraco.Core/Services/ContentValidationServiceBase.cs b/src/Umbraco.Core/Services/ContentValidationServiceBase.cs index 98876c411075..92c00fda12cd 100644 --- a/src/Umbraco.Core/Services/ContentValidationServiceBase.cs +++ b/src/Umbraco.Core/Services/ContentValidationServiceBase.cs @@ -9,12 +9,21 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Base class for content validation services that validates properties against content types. +/// +/// The type of content type composition. internal abstract class ContentValidationServiceBase where TContentType : IContentTypeComposition { private readonly ILanguageService _languageService; private readonly IPropertyValidationService _propertyValidationService; + /// + /// Initializes a new instance of the class. + /// + /// The property validation service. + /// The language service. protected ContentValidationServiceBase( IPropertyValidationService propertyValidationService, ILanguageService languageService) @@ -23,6 +32,13 @@ protected ContentValidationServiceBase( _languageService = languageService; } + /// + /// Handles the validation of properties against the content type. + /// + /// The content editing model to validate. + /// The content type to validate against. + /// Optional cultures to restrict validation to. + /// The validation result containing any validation errors. protected async Task HandlePropertiesValidationAsync( ContentEditingModelBase contentEditingModelBase, TContentType contentType, @@ -144,6 +160,11 @@ protected async Task HandlePropertiesValidationAsync( return new ContentValidationResult { ValidationErrors = validationErrors }; } + /// + /// Validates that all cultures specified in the content editing model are valid. + /// + /// The content editing model to validate. + /// true if all cultures are valid; otherwise, false. public async Task ValidateCulturesAsync(ContentEditingModelBase contentEditingModelBase) { var cultures = await GetCultureCodes(); diff --git a/src/Umbraco.Core/Services/ContentVersionService.cs b/src/Umbraco.Core/Services/ContentVersionService.cs index 230aa2212623..ff1de9b0c7dc 100644 --- a/src/Umbraco.Core/Services/ContentVersionService.cs +++ b/src/Umbraco.Core/Services/ContentVersionService.cs @@ -13,6 +13,9 @@ // ReSharper disable once CheckNamespace namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing content versions, including retrieval, cleanup, and rollback operations. +/// internal sealed class ContentVersionService : IContentVersionService { private readonly IAuditService _auditService; @@ -26,6 +29,19 @@ internal sealed class ContentVersionService : IContentVersionService private readonly ILogger _logger; private readonly ICoreScopeProvider _scopeProvider; + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The document version repository. + /// The content version cleanup policy. + /// The scope provider. + /// The event messages factory. + /// The audit service. + /// The language repository. + /// The entity service. + /// The content service. + /// The user ID key resolver. public ContentVersionService( ILogger logger, IDocumentVersionRepository documentVersionRepository, @@ -57,6 +73,11 @@ public IReadOnlyCollection PerformContentVersionCleanup(Date // Members - ignored CleanupDocumentVersions(asAtDate); + /// + /// Gets a content version by its ID. + /// + /// The version ID. + /// The content version metadata, or null if not found. public ContentVersionMeta? Get(int versionId) { using (ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true)) @@ -66,6 +87,7 @@ public IReadOnlyCollection PerformContentVersionCleanup(Date } } + /// public Task?, ContentVersionOperationStatus>> GetPagedContentVersionsAsync(Guid contentId, string? culture, int skip, int take) { IEntitySlim? document = _entityService.Get(contentId, UmbracoObjectTypes.Document); @@ -91,6 +113,7 @@ public IReadOnlyCollection PerformContentVersionCleanup(Date ContentVersionOperationStatus.Success, new PagedModel(total, versions))); } + /// public Task> GetAsync(Guid versionId) { IContent? version = _contentService.GetVersion(versionId.ToInt()); @@ -102,6 +125,7 @@ public IReadOnlyCollection PerformContentVersionCleanup(Date return Task.FromResult(Attempt.Succeed(ContentVersionOperationStatus.Success, version)); } + /// public async Task> SetPreventCleanupAsync(Guid versionId, bool preventCleanup, Guid userKey) { ContentVersionMeta? version = Get(versionId.ToInt()); @@ -115,6 +139,7 @@ public async Task> SetPreventCleanupAsync return Attempt.Succeed(ContentVersionOperationStatus.Success); } + /// public async Task> RollBackAsync(Guid versionId, string? culture, Guid userKey) { ContentVersionMeta? version = Get(versionId.ToInt()); diff --git a/src/Umbraco.Core/Services/CultureImpactFactory.cs b/src/Umbraco.Core/Services/CultureImpactFactory.cs index 3dd9b6b1f0b1..a43d40f17fb7 100644 --- a/src/Umbraco.Core/Services/CultureImpactFactory.cs +++ b/src/Umbraco.Core/Services/CultureImpactFactory.cs @@ -7,10 +7,18 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Factory for creating instances that represent +/// the impact of culture settings on content variations. +/// public class CultureImpactFactory : ICultureImpactFactory { private ContentSettings _contentSettings; + /// + /// Initializes a new instance of the class. + /// + /// The content settings options monitor. public CultureImpactFactory(IOptionsMonitor contentSettings) { _contentSettings = contentSettings.CurrentValue; diff --git a/src/Umbraco.Core/Services/CultureService.cs b/src/Umbraco.Core/Services/CultureService.cs index e4a4d3f6e732..4d31498abdf8 100644 --- a/src/Umbraco.Core/Services/CultureService.cs +++ b/src/Umbraco.Core/Services/CultureService.cs @@ -2,12 +2,20 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for working with cultures and ISO codes. +/// public class CultureService : ICultureService { private readonly IIsoCodeValidator _isoCodeValidator; + /// + /// Initializes a new instance of the class. + /// + /// The ISO code validator. public CultureService(IIsoCodeValidator isoCodeValidator) => _isoCodeValidator = isoCodeValidator; + /// public CultureInfo[] GetValidCultureInfos() { CultureInfo[] all = CultureInfo.GetCultures(CultureTypes.AllCultures) diff --git a/src/Umbraco.Core/Services/DataTypeContainerService.cs b/src/Umbraco.Core/Services/DataTypeContainerService.cs index 8b892226efe0..8ca95a8c6369 100644 --- a/src/Umbraco.Core/Services/DataTypeContainerService.cs +++ b/src/Umbraco.Core/Services/DataTypeContainerService.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence.Repositories; @@ -6,8 +6,21 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing data type containers (folders). +/// internal sealed class DataTypeContainerService : EntityTypeContainerService, IDataTypeContainerService { + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The data type container repository. + /// The audit service. + /// The entity repository. + /// The user ID key resolver. public DataTypeContainerService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -20,13 +33,17 @@ public DataTypeContainerService( { } + /// protected override Guid ContainedObjectType => Constants.ObjectTypes.DataType; + /// protected override UmbracoObjectTypes ContainerObjectType => UmbracoObjectTypes.DataTypeContainer; - // data types do not have read/write locks (yet) + /// + /// Data types do not have read/write locks (yet). protected override int[] ReadLockIds => []; - // data types do not have read/write locks (yet) + /// + /// Data types do not have read/write locks (yet). protected override int[] WriteLockIds => []; } diff --git a/src/Umbraco.Core/Services/DataTypeService.cs b/src/Umbraco.Core/Services/DataTypeService.cs index 04c8a91060c7..c0d8eaeb87db 100644 --- a/src/Umbraco.Core/Services/DataTypeService.cs +++ b/src/Umbraco.Core/Services/DataTypeService.cs @@ -31,6 +31,18 @@ public class DataTypeService : RepositoryService, IDataTypeService private readonly IUserIdKeyResolver _userIdKeyResolver; private readonly Lazy _idKeyMap; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The data type repository. + /// The audit service. + /// The content type repository. + /// The media type repository. + /// The member type repository. + /// The ID key map. public DataTypeService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -56,6 +68,18 @@ public DataTypeService( _userIdKeyResolver = StaticServiceProvider.Instance.GetRequiredService(); } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The data type repository. + /// The audit repository (obsolete). + /// The content type repository. + /// The media type repository. + /// The member type repository. + /// The ID key map. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v18.")] public DataTypeService( ICoreScopeProvider provider, @@ -80,6 +104,20 @@ public DataTypeService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The data type repository. + /// The data value editor factory (obsolete). + /// The audit repository (obsolete). + /// The content type repository. + /// The media type repository. + /// The member type repository. + /// The IO helper (obsolete). + /// The ID key map. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v18.")] public DataTypeService( ICoreScopeProvider provider, @@ -106,6 +144,21 @@ public DataTypeService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The data type repository. + /// The data value editor factory (obsolete). + /// The audit repository (obsolete). + /// The audit service. + /// The content type repository. + /// The media type repository. + /// The member type repository. + /// The IO helper (obsolete). + /// The ID key map. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v18.")] public DataTypeService( ICoreScopeProvider provider, @@ -135,6 +188,14 @@ public DataTypeService( #region Containers + /// + /// Creates a container for organizing data types. + /// + /// The parent container ID, or -1 for root. + /// The unique key for the new container. + /// The name of the container. + /// The ID of the user performing the action. + /// An operation result containing the created container. [Obsolete($"Please use {nameof(IDataTypeContainerService)} for all data type container operations. Will be removed in V15.")] public Attempt?> CreateContainer(int parentId, Guid key, string name, int userId = Constants.Security.SuperUserId) { @@ -162,6 +223,11 @@ public DataTypeService( } } + /// + /// Gets a container by its ID. + /// + /// The container ID. + /// The container, or null if not found. [Obsolete($"Please use {nameof(IDataTypeContainerService)} for all data type container operations. Will be removed in V16.")] public EntityContainer? GetContainer(int containerId) { @@ -169,10 +235,21 @@ public DataTypeService( return _dataTypeContainerRepository.Get(containerId); } + /// + /// Gets a container by its unique key. + /// + /// The container unique key. + /// The container, or null if not found. [Obsolete($"Please use {nameof(IDataTypeContainerService)} for all data type container operations. Will be removed in V16.")] public EntityContainer? GetContainer(Guid containerId) => _dataTypeContainerService.GetAsync(containerId).GetAwaiter().GetResult(); + /// + /// Gets containers by name and level. + /// + /// The container name. + /// The container level. + /// A collection of matching containers. [Obsolete($"Please use {nameof(IDataTypeContainerService)} for all data type container operations. Will be removed in V16.")] public IEnumerable GetContainers(string name, int level) { @@ -180,6 +257,11 @@ public IEnumerable GetContainers(string name, int level) return _dataTypeContainerRepository.Get(name, level); } + /// + /// Gets all ancestor containers for a data type. + /// + /// The data type. + /// A collection of ancestor containers. [Obsolete($"Please use {nameof(IDataTypeContainerService)} for all data type container operations. Will be removed in V16.")] public IEnumerable GetContainers(IDataType dataType) { @@ -195,6 +277,11 @@ public IEnumerable GetContainers(IDataType dataType) return GetContainers(ancestorIds); } + /// + /// Gets containers by their IDs. + /// + /// The container IDs. + /// A collection of containers. [Obsolete($"Please use {nameof(IDataTypeContainerService)} for all data type container operations. Will be removed in V16.")] public IEnumerable GetContainers(int[] containerIds) { @@ -202,6 +289,12 @@ public IEnumerable GetContainers(int[] containerIds) return _dataTypeContainerRepository.GetMany(containerIds); } + /// + /// Saves a container. + /// + /// The container to save. + /// The ID of the user performing the action. + /// An operation result indicating success or failure. [Obsolete($"Please use {nameof(IDataTypeContainerService)} for all data type container operations. Will be removed in V16.")] public Attempt SaveContainer(EntityContainer container, int userId = Constants.Security.SuperUserId) { @@ -228,6 +321,12 @@ public IEnumerable GetContainers(int[] containerIds) } } + /// + /// Deletes a container. + /// + /// The ID of the container to delete. + /// The ID of the user performing the action. + /// An operation result indicating success or failure. [Obsolete($"Please use {nameof(IDataTypeContainerService)} for all data type container operations. Will be removed in V16.")] public Attempt DeleteContainer(int containerId, int userId = Constants.Security.SuperUserId) { @@ -253,6 +352,13 @@ public IEnumerable GetContainers(int[] containerIds) } } + /// + /// Renames a container. + /// + /// The ID of the container to rename. + /// The new name for the container. + /// The ID of the user performing the action. + /// An operation result containing the renamed container. [Obsolete($"Please use {nameof(IDataTypeContainerService)} for all data type container operations. Will be removed in V16.")] public Attempt?> RenameContainer(int id, string name, int userId = Constants.Security.SuperUserId) { @@ -434,6 +540,7 @@ public IEnumerable GetAll(params int[] ids) return dataTypes; } + /// public Attempt?> Move(IDataType toMove, int parentId) { Guid? containerKey = null; @@ -462,6 +569,7 @@ public IEnumerable GetAll(params int[] ids) }; } + /// public async Task> MoveAsync(IDataType toMove, Guid? containerKey, Guid userKey) { EventMessages eventMessages = EventMessagesFactory.Get(); @@ -505,10 +613,23 @@ public async Task> MoveAsync(IDataTy return Attempt.SucceedWithStatus(DataTypeOperationStatus.Success, toMove); } + /// + /// Copies a data type to a container. + /// + /// The data type to copy. + /// The target container ID. + /// An operation result containing the copied data type. [Obsolete("Use the method which specifies the userId parameter")] public Attempt?> Copy(IDataType copying, int containerId) => Copy(copying, containerId, Constants.Security.SuperUserId); + /// + /// Copies a data type to a container. + /// + /// The data type to copy. + /// The target container ID. + /// The ID of the user performing the action. + /// An operation result containing the copied data type. public Attempt?> Copy(IDataType copying, int containerId, int userId = Constants.Security.SuperUserId) { Guid? containerKey = null; @@ -663,6 +784,7 @@ public void Save(IEnumerable dataTypeDefinitions, int userId) /// /// to delete /// Optional Id of the user issuing the deletion + /// public void Delete(IDataType dataType, int userId = Constants.Security.SuperUserId) { Guid currentUserKey = _userIdKeyResolver.GetAsync(userId).GetAwaiter().GetResult(); @@ -808,6 +930,11 @@ public Task> GetPagedRelationsAsync(Guid key, int return Task.FromResult(pagedModel); } + /// + /// Gets the content types referenced by the paged usages. + /// + /// The paged usages containing property aliases and UDIs. + /// A list of content type compositions. private List GetReferencedContentTypes(List<(string PropertyAlias, Udi Udi)> pagedUsages) { IEnumerable documentTypes = GetContentTypes( @@ -825,6 +952,14 @@ private List GetReferencedContentTypes(List<(string Pro return documentTypes.Concat(mediaTypes).Concat(memberTypes).ToList(); } + /// + /// Gets content types for the specified entity type from the usages collection. + /// + /// The content type composition type. + /// The data type usages. + /// The entity type to filter by. + /// The repository to query. + /// A collection of content types. private static IEnumerable GetContentTypes( IEnumerable<(string PropertyAlias, Udi Udi)> dataTypeUsages, string entityType, @@ -853,6 +988,14 @@ public IEnumerable ValidateConfigurationData(IDataType dataTyp : configurationEditor.Validate(dataType.ConfigurationData); } + /// + /// Saves a data type with validation and notifications. + /// + /// The data type to save. + /// A function that validates the operation and returns a status. + /// The key of the user performing the action. + /// The type of audit entry to create. + /// An attempt result with the saved data type and operation status. private async Task> SaveAsync( IDataType dataType, Func operationValidation, @@ -909,6 +1052,11 @@ private async Task> SaveAsync( return Attempt.SucceedWithStatus(DataTypeOperationStatus.Success, dataType); } + /// + /// Gets a data type from the repository by its unique key. + /// + /// The unique key of the data type. + /// The data type, or null if not found. private IDataType? GetDataTypeFromRepository(Guid id) => _idKeyMap.Value.GetIdForKey(id, UmbracoObjectTypes.DataType) switch { @@ -916,15 +1064,35 @@ private async Task> SaveAsync( { Result: var intId } => _dataTypeRepository.Get(intId), }; + /// + /// Creates an audit entry for a data type operation. + /// + /// The audit type. + /// The ID of the user performing the action. + /// The ID of the object being audited. private void Audit(AuditType type, int userId, int objectId) => AuditAsync(type, userId, objectId).GetAwaiter().GetResult(); + /// + /// Asynchronously creates an audit entry for a data type operation. + /// + /// The audit type. + /// The ID of the user performing the action. + /// The ID of the object being audited. + /// A task representing the asynchronous operation. private async Task AuditAsync(AuditType type, int userId, int objectId) { Guid userKey = await _userIdKeyResolver.GetAsync(userId); await AuditAsync(type, userKey, objectId); } + /// + /// Asynchronously creates an audit entry for a data type operation. + /// + /// The audit type. + /// The key of the user performing the action. + /// The ID of the object being audited. + /// A task representing the asynchronous operation. private async Task AuditAsync(AuditType type, Guid userKey, int objectId) => await _auditService.AddAsync( type, diff --git a/src/Umbraco.Core/Services/DataTypeUsageService.cs b/src/Umbraco.Core/Services/DataTypeUsageService.cs index 58e53a8803fd..9d53b0a00461 100644 --- a/src/Umbraco.Core/Services/DataTypeUsageService.cs +++ b/src/Umbraco.Core/Services/DataTypeUsageService.cs @@ -5,12 +5,21 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for checking data type usage information. +/// public class DataTypeUsageService : IDataTypeUsageService { private readonly IDataTypeUsageRepository _dataTypeUsageRepository; private readonly IDataTypeService _dataTypeService; private readonly ICoreScopeProvider _scopeProvider; + /// + /// Initializes a new instance of the class. + /// + /// The data type usage repository. + /// The data type service. + /// The scope provider. public DataTypeUsageService( IDataTypeUsageRepository dataTypeUsageRepository, IDataTypeService dataTypeService, diff --git a/src/Umbraco.Core/Services/DateTypeServiceExtensions.cs b/src/Umbraco.Core/Services/DateTypeServiceExtensions.cs index 11e178808736..8a110364036a 100644 --- a/src/Umbraco.Core/Services/DateTypeServiceExtensions.cs +++ b/src/Umbraco.Core/Services/DateTypeServiceExtensions.cs @@ -4,11 +4,26 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class DateTypeServiceExtensions { + /// + /// Determines whether the data type is configured to ignore user start nodes. + /// + /// The data type service. + /// The data type key. + /// true if the data type ignores user start nodes; otherwise, false. public static bool IsDataTypeIgnoringUserStartNodes(this IDataTypeService dataTypeService, Guid key) => dataTypeService.IsDataTypeIgnoringUserStartNodesAsync(key).GetAwaiter().GetResult(); + /// + /// Determines asynchronously whether the data type is configured to ignore user start nodes. + /// + /// The data type service. + /// The data type key. + /// true if the data type ignores user start nodes; otherwise, false. public static async Task IsDataTypeIgnoringUserStartNodesAsync(this IDataTypeService dataTypeService, Guid key) { IDataType? dataType = await dataTypeService.GetAsync(key); diff --git a/src/Umbraco.Core/Services/DefaultContentVersionCleanupPolicy.cs b/src/Umbraco.Core/Services/DefaultContentVersionCleanupPolicy.cs index 51813c3163b6..1721868e3210 100644 --- a/src/Umbraco.Core/Services/DefaultContentVersionCleanupPolicy.cs +++ b/src/Umbraco.Core/Services/DefaultContentVersionCleanupPolicy.cs @@ -7,12 +7,23 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Default implementation of the content version cleanup policy that determines which content versions +/// should be cleaned up based on configuration settings and per-content-type overrides. +/// public class DefaultContentVersionCleanupPolicy : IContentVersionCleanupPolicy { private readonly IOptions _contentSettings; private readonly IDocumentVersionRepository _documentVersionRepository; private readonly ICoreScopeProvider _scopeProvider; + /// + /// Initializes a new instance of the class. + /// + /// The content settings options. + /// The scope provider. + /// The document version repository. + /// Thrown when any parameter is null. public DefaultContentVersionCleanupPolicy( IOptions contentSettings, ICoreScopeProvider scopeProvider, @@ -24,6 +35,7 @@ public DefaultContentVersionCleanupPolicy( throw new ArgumentNullException(nameof(documentVersionRepository)); } + /// public IEnumerable Apply(DateTime asAtDate, IEnumerable items) { // Note: Not checking global enable flag, that's handled in the scheduled job. diff --git a/src/Umbraco.Core/Services/DictionaryItemService.cs b/src/Umbraco.Core/Services/DictionaryItemService.cs index 0181ab2482ca..f5199b68f960 100644 --- a/src/Umbraco.Core/Services/DictionaryItemService.cs +++ b/src/Umbraco.Core/Services/DictionaryItemService.cs @@ -9,6 +9,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing dictionary items (localized text entries). +/// internal sealed class DictionaryItemService : RepositoryService, IDictionaryItemService { private readonly IDictionaryRepository _dictionaryRepository; @@ -16,6 +19,16 @@ internal sealed class DictionaryItemService : RepositoryService, IDictionaryItem private readonly ILanguageService _languageService; private readonly IUserIdKeyResolver _userIdKeyResolver; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The dictionary repository. + /// The audit service. + /// The language service. + /// The user ID key resolver. public DictionaryItemService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -74,8 +87,12 @@ public Task> GetManyAsync(params string[] keys) /// /// Gets the dictionary items in a paged manner. - /// Currently implements the paging in memory on the itenkey property because the underlying repository does not support paging yet /// + /// The parent dictionary item ID, or null for root items. + /// The number of items to skip. + /// The number of items to take. + /// A paged model containing dictionary items. + /// Currently implements the paging in memory on the item key property because the underlying repository does not support paging yet. public async Task> GetPagedAsync(Guid? parentId, int skip, int take) { using ICoreScope coreScope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -102,6 +119,11 @@ public async Task> GetPagedAsync(Guid? parentId, int public async Task> GetChildrenAsync(Guid parentId) => await GetByQueryAsync(Query().Where(x => x.ParentId == parentId)); + /// + /// Counts the number of child dictionary items under a specified parent. + /// + /// The parent dictionary item ID. + /// The number of child dictionary items. public async Task CountChildrenAsync(Guid parentId) => await CountByQueryAsync(Query().Where(x => x.ParentId == parentId)); @@ -119,6 +141,10 @@ public Task> GetDescendantsAsync(Guid? parentId, st public async Task> GetAtRootAsync() => await GetByQueryAsync(Query().Where(x => x.ParentId == null)); + /// + /// Counts the number of root dictionary items. + /// + /// The number of root dictionary items. public async Task CountRootAsync() => await CountByQueryAsync(Query().Where(x => x.ParentId == null)); @@ -288,6 +314,11 @@ public async Task> MoveA } } + /// + /// Counts dictionary items matching the specified query. + /// + /// The query to execute. + /// The count of matching dictionary items. private Task CountByQueryAsync(IQuery query) { using (ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -297,6 +328,15 @@ private Task CountByQueryAsync(IQuery query) } } + /// + /// Saves a dictionary item with validation and notification handling. + /// + /// The dictionary item to save. + /// A function that validates the operation and returns the status. + /// The type of audit entry to create. + /// The audit message. + /// The unique identifier of the user performing the save. + /// An attempt containing the saved dictionary item and operation status. private async Task> SaveAsync( IDictionaryItem dictionaryItem, Func operationValidation, @@ -348,6 +388,11 @@ private async Task> Save } } + /// + /// Gets dictionary items matching the specified query. + /// + /// The query to execute. + /// A collection of dictionary items matching the query. private Task> GetByQueryAsync(IQuery query) { using (ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -357,6 +402,14 @@ private Task> GetByQueryAsync(IQuery + /// Creates an audit entry for a dictionary item operation. + /// + /// The type of audit entry. + /// The audit message. + /// The unique identifier of the user performing the operation. + /// The ID of the affected object. + /// The type of entity being audited. private async Task AuditAsync(AuditType type, string message, Guid userKey, int objectId, string? entityType) => await _auditService.AddAsync( type, @@ -365,9 +418,19 @@ await _auditService.AddAsync( entityType, message); + /// + /// Validates that the dictionary item has a valid parent. + /// + /// The dictionary item to validate. + /// true if the parent is valid or no parent is specified; otherwise, false. private bool HasValidParent(IDictionaryItem dictionaryItem) => dictionaryItem.ParentId.HasValue == false || _dictionaryRepository.Get(dictionaryItem.ParentId.Value) != null; + /// + /// Removes translations for languages that no longer exist. + /// + /// The dictionary item to clean up. + /// All available languages. private void RemoveInvalidTranslations(IDictionaryItem dictionaryItem, IEnumerable allLanguages) { IDictionaryTranslation[] translationsAsArray = dictionaryItem.Translations.ToArray(); @@ -380,6 +443,11 @@ private void RemoveInvalidTranslations(IDictionaryItem dictionaryItem, IEnumerab dictionaryItem.Translations = translationsAsArray.Where(translation => allLanguageIsoCodes.Contains(translation.LanguageIsoCode)).ToArray(); } + /// + /// Checks whether another dictionary item exists with the same item key. + /// + /// The dictionary item to check. + /// true if a collision exists; otherwise, false. private bool HasItemKeyCollision(IDictionaryItem dictionaryItem) { IDictionaryItem? itemKeyCollision = _dictionaryRepository.Get(dictionaryItem.ItemKey); diff --git a/src/Umbraco.Core/Services/DictionaryPermissionService.cs b/src/Umbraco.Core/Services/DictionaryPermissionService.cs index 0cf73b630039..80b449424af3 100644 --- a/src/Umbraco.Core/Services/DictionaryPermissionService.cs +++ b/src/Umbraco.Core/Services/DictionaryPermissionService.cs @@ -4,10 +4,17 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for checking dictionary item culture permissions for users. +/// public class DictionaryPermissionService : IDictionaryPermissionService { private readonly ILanguageService _languageService; + /// + /// Initializes a new instance of the class. + /// + /// The language service. public DictionaryPermissionService(ILanguageService languageService) { _languageService = languageService; diff --git a/src/Umbraco.Core/Services/DictionaryService.cs b/src/Umbraco.Core/Services/DictionaryService.cs index 1c48ac445816..53b9688d056f 100644 --- a/src/Umbraco.Core/Services/DictionaryService.cs +++ b/src/Umbraco.Core/Services/DictionaryService.cs @@ -1,13 +1,21 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides helper services for dictionary-related operations, such as path calculation. +/// public class DictionaryService : IDictionaryService { private readonly ILocalizationService _localizationService; + /// + /// Initializes a new instance of the class. + /// + /// The localization service. public DictionaryService(ILocalizationService localizationService) => _localizationService = localizationService; + /// public string CalculatePath(Guid? parentId, int sourceId) { string path; diff --git a/src/Umbraco.Core/Services/DocumentUrlServiceInitializerNotificationHandler.cs b/src/Umbraco.Core/Services/DocumentUrlServiceInitializerNotificationHandler.cs index a10843f6e6cd..848931dcf13b 100644 --- a/src/Umbraco.Core/Services/DocumentUrlServiceInitializerNotificationHandler.cs +++ b/src/Umbraco.Core/Services/DocumentUrlServiceInitializerNotificationHandler.cs @@ -3,17 +3,26 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Handles the application starting notification to initialize the document URL service. +/// public class DocumentUrlServiceInitializerNotificationHandler : INotificationAsyncHandler { private readonly IDocumentUrlService _documentUrlService; private readonly IRuntimeState _runtimeState; + /// + /// Initializes a new instance of the class. + /// + /// The document URL service. + /// The runtime state. public DocumentUrlServiceInitializerNotificationHandler(IDocumentUrlService documentUrlService, IRuntimeState runtimeState) { _documentUrlService = documentUrlService; _runtimeState = runtimeState; } + /// public async Task HandleAsync(UmbracoApplicationStartingNotification notification, CancellationToken cancellationToken) { if (_runtimeState.Level == RuntimeLevel.Upgrade) diff --git a/src/Umbraco.Core/Services/DomainService.cs b/src/Umbraco.Core/Services/DomainService.cs index 1bcfd9cf821f..cc75f12e2470 100644 --- a/src/Umbraco.Core/Services/DomainService.cs +++ b/src/Umbraco.Core/Services/DomainService.cs @@ -10,12 +10,24 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing domains (hostnames and culture assignments for content). +/// public class DomainService : RepositoryService, IDomainService { private readonly IDomainRepository _domainRepository; private readonly ILanguageService _languageService; private readonly IContentService _contentService; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The domain repository. + /// The language service. + /// The content service. public DomainService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -30,6 +42,7 @@ public DomainService( _contentService = contentService; } + /// public bool Exists(string domainName) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -38,6 +51,11 @@ public bool Exists(string domainName) } } + /// + /// Deletes a domain. + /// + /// The domain to delete. + /// An attempt result indicating the success or failure of the operation. [Obsolete($"Please use {nameof(UpdateDomainsAsync)}. Will be removed in V15")] public Attempt Delete(IDomain domain) { @@ -50,6 +68,7 @@ public bool Exists(string domainName) return result ? OperationResult.Attempt.Succeed(eventMessages) : OperationResult.Attempt.Cancel(eventMessages); } + /// public IDomain? GetByName(string name) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -58,6 +77,7 @@ public bool Exists(string domainName) } } + /// public IDomain? GetById(int id) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -66,6 +86,11 @@ public bool Exists(string domainName) } } + /// + /// Gets all domains. + /// + /// A value indicating whether to include wildcard domains. + /// A collection of all domains. [Obsolete($"Please use {nameof(GetAllAsync)}. Will be removed in V15")] public IEnumerable GetAll(bool includeWildcards) { @@ -75,6 +100,12 @@ public IEnumerable GetAll(bool includeWildcards) } } + /// + /// Gets the domains assigned to a specific content item. + /// + /// The identifier of the content item. + /// A value indicating whether to include wildcard domains. + /// A collection of domains assigned to the content item. [Obsolete($"Please use {nameof(GetAssignedDomainsAsync)}. Will be removed in V15")] public IEnumerable GetAssignedDomains(int contentId, bool includeWildcards) { @@ -84,6 +115,11 @@ public IEnumerable GetAssignedDomains(int contentId, bool includeWildca } } + /// + /// Saves a domain. + /// + /// The domain entity to save. + /// An attempt result indicating the success or failure of the operation. [Obsolete($"Please use {nameof(UpdateDomainsAsync)}. Will be removed in V15")] public Attempt Save(IDomain domainEntity) { @@ -96,6 +132,11 @@ public IEnumerable GetAssignedDomains(int contentId, bool includeWildca return result ? OperationResult.Attempt.Succeed(eventMessages) : OperationResult.Attempt.Cancel(eventMessages); } + /// + /// Sorts domains. + /// + /// The domains to sort. + /// An attempt result indicating the success or failure of the operation. [Obsolete($"Please use {nameof(UpdateDomainsAsync)}. Will be removed in V15")] public Attempt Sort(IEnumerable items) { diff --git a/src/Umbraco.Core/Services/EntityService.cs b/src/Umbraco.Core/Services/EntityService.cs index c13111088edc..25c7de6a4836 100644 --- a/src/Umbraco.Core/Services/EntityService.cs +++ b/src/Umbraco.Core/Services/EntityService.cs @@ -11,6 +11,13 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides entity-related operations for retrieving lightweight entity representations and managing entity identifiers. +/// +/// +/// This service provides efficient access to entity metadata without loading full entity objects, +/// supporting operations like getting parent/child relationships, pagination, and ID/Key mapping. +/// public class EntityService : RepositoryService, IEntityService { private readonly IEntityRepository _entityRepository; @@ -18,6 +25,14 @@ public class EntityService : RepositoryService, IEntityService private readonly Dictionary _objectTypes; private IQuery? _queryRootEntity; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The ID/Key mapping service for converting between integer IDs and GUIDs. + /// The repository for entity data access. public EntityService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -125,6 +140,7 @@ public bool Exists(Guid key) } } + /// public bool Exists(IEnumerable keys) { using (ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -304,6 +320,7 @@ public virtual IEnumerable GetChildren(int parentId, UmbracoObjectT } } + /// public IEnumerable GetChildren(Guid? key, UmbracoObjectTypes objectType) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -441,6 +458,7 @@ public IEnumerable GetPagedChildren( Ordering? ordering = null) => GetPagedChildren(id, objectType, pageIndex, pageSize, false, filter, ordering, out totalRecords); + /// public IEnumerable GetPagedChildren( Guid? parentKey, UmbracoObjectTypes childObjectType, @@ -459,6 +477,7 @@ public IEnumerable GetPagedChildren( filter, ordering); + /// public IEnumerable GetPagedChildren( Guid? parentKey, IEnumerable parentObjectTypes, @@ -511,6 +530,7 @@ public IEnumerable GetPagedTrashedChildren( Ordering? ordering = null) => GetPagedChildren(id, objectType, pageIndex, pageSize, true, filter, ordering, out totalRecords); + /// public IEnumerable GetPagedTrashedChildren( Guid? key, UmbracoObjectTypes objectType, @@ -807,6 +827,7 @@ private IEnumerable GetPagedChildren( } } + /// public IEnumerable GetPagedChildren( Guid? parentKey, IEnumerable parentObjectTypes, diff --git a/src/Umbraco.Core/Services/EntityTypeContainerService.cs b/src/Umbraco.Core/Services/EntityTypeContainerService.cs index 5c724e1529f0..98847ec6494a 100644 --- a/src/Umbraco.Core/Services/EntityTypeContainerService.cs +++ b/src/Umbraco.Core/Services/EntityTypeContainerService.cs @@ -9,6 +9,15 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides base functionality for entity type container services that manage folder hierarchies for content types. +/// +/// The type of tree entity contained within the containers. +/// The type of repository used for container operations. +/// +/// Containers (folders) are used to organize content types, media types, data types, and other entities +/// in a hierarchical structure within the Umbraco backoffice. +/// internal abstract class EntityTypeContainerService : RepositoryService, IEntityTypeContainerService where TTreeEntity : ITreeEntity where TEntityContainerRepository : IEntityContainerRepository @@ -18,14 +27,36 @@ internal abstract class EntityTypeContainerService + /// Gets the GUID identifying the type of objects contained within these containers. + /// protected abstract Guid ContainedObjectType { get; } + /// + /// Gets the Umbraco object type for the container itself. + /// protected abstract UmbracoObjectTypes ContainerObjectType { get; } + /// + /// Gets the lock identifiers required for read operations. + /// protected abstract int[] ReadLockIds { get; } + /// + /// Gets the lock identifiers required for write operations. + /// protected abstract int[] WriteLockIds { get; } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for container data access. + /// The audit service for logging operations. + /// The entity repository for general entity operations. + /// The resolver for converting user IDs to keys. protected EntityTypeContainerService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, diff --git a/src/Umbraco.Core/Services/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/EntityXmlSerializer.cs index 013591e67830..c9cfed205687 100644 --- a/src/Umbraco.Core/Services/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/EntityXmlSerializer.cs @@ -11,8 +11,12 @@ namespace Umbraco.Cms.Core.Services; /// -/// Serializes entities to XML +/// Serializes entities to XML for export, packaging, and data transfer operations. /// +/// +/// This service supports serializing content, media, members, data types, dictionary items, +/// templates, stylesheets, languages, and content types to XML format. +/// internal sealed class EntityXmlSerializer : IEntityXmlSerializer { private readonly IConfigurationEditorJsonSerializer _configurationEditorJsonSerializer; @@ -26,6 +30,19 @@ internal sealed class EntityXmlSerializer : IEntityXmlSerializer private readonly UrlSegmentProviderCollection _urlSegmentProviders; private readonly IUserService _userService; + /// + /// Initializes a new instance of the class. + /// + /// The content service for content operations. + /// The media service for media operations. + /// The data type service for data type operations. + /// The user service for user lookups. + /// The localization service for dictionary items. + /// The content type service for content type operations. + /// The collection of URL segment providers. + /// The helper for string operations. + /// The collection of property editors. + /// The serializer for configuration data. public EntityXmlSerializer( IContentService contentService, IMediaService mediaService, @@ -50,9 +67,7 @@ public EntityXmlSerializer( _configurationEditorJsonSerializer = configurationEditorJsonSerializer; } - /// - /// Exports an IContent item as an XElement. - /// + /// public XElement Serialize( IContent content, bool published, @@ -96,9 +111,7 @@ public XElement Serialize( return xml; } - /// - /// Exports an IMedia item as an XElement. - /// + /// public XElement Serialize( IMedia media, bool withDescendants = false, @@ -167,9 +180,7 @@ public XElement Serialize( return xml; } - /// - /// Exports an IMember item as an XElement. - /// + /// public XElement Serialize(IMember member) { var nodeName = member.ContentType.Alias.ToSafeAlias(_shortStringHelper); @@ -188,11 +199,7 @@ public XElement Serialize(IMember member) return xml; } - /// - /// Exports a list of Data Types - /// - /// List of data types to export - /// containing the xml representation of the IDataTypeDefinition objects + /// public XElement Serialize(IEnumerable dataTypeDefinitions) { var container = new XElement("DataTypes"); @@ -204,6 +211,7 @@ public XElement Serialize(IEnumerable dataTypeDefinitions) return container; } + /// public XElement Serialize(IDataType dataType) { var xml = new XElement("DataType"); @@ -237,12 +245,7 @@ public XElement Serialize(IDataType dataType) return xml; } - /// - /// Exports a list of items to xml as an - /// - /// List of dictionary items to export - /// Optional boolean indicating whether or not to include children - /// containing the xml representation of the IDictionaryItem objects + /// public XElement Serialize(IEnumerable dictionaryItem, bool includeChildren = true) { var xml = new XElement("DictionaryItems"); @@ -254,12 +257,7 @@ public XElement Serialize(IEnumerable dictionaryItem, bool incl return xml; } - /// - /// Exports a single item to xml as an - /// - /// Dictionary Item to export - /// Optional boolean indicating whether or not to include children - /// containing the xml representation of the IDictionaryItem object + /// public XElement Serialize(IDictionaryItem dictionaryItem, bool includeChildren) { XElement xml = Serialize(dictionaryItem); @@ -279,6 +277,7 @@ public XElement Serialize(IDictionaryItem dictionaryItem, bool includeChildren) return xml; } + /// public XElement Serialize(IStylesheet stylesheet, bool includeProperties) { var xml = new XElement( @@ -310,11 +309,7 @@ public XElement Serialize(IStylesheet stylesheet, bool includeProperties) return xml; } - /// - /// Exports a list of items to xml as an - /// - /// List of Languages to export - /// containing the xml representation of the ILanguage objects + /// public XElement Serialize(IEnumerable languages) { var xml = new XElement("Languages"); @@ -326,6 +321,7 @@ public XElement Serialize(IEnumerable languages) return xml; } + /// public XElement Serialize(ILanguage language) { var xml = new XElement( @@ -337,6 +333,7 @@ public XElement Serialize(ILanguage language) return xml; } + /// public XElement Serialize(ITemplate template) { var xml = new XElement("Template"); @@ -358,11 +355,7 @@ public XElement Serialize(ITemplate template) return xml; } - /// - /// Exports a list of items to xml as an - /// - /// - /// + /// public XElement Serialize(IEnumerable templates) { var xml = new XElement("Templates"); @@ -374,10 +367,18 @@ public XElement Serialize(IEnumerable templates) return xml; } + /// public XElement Serialize(IMediaType mediaType) => SerializeMediaOrMemberType(mediaType, IEntityXmlSerializer.MediaTypeElementName); + /// public XElement Serialize(IMemberType memberType) => SerializeMediaOrMemberType(memberType, IEntityXmlSerializer.MemberTypeElementName); + /// + /// Serializes a media type or member type to an . + /// + /// The content type composition to serialize. + /// The XML element name to use for the root element. + /// An containing the XML representation of the content type. private XElement SerializeMediaOrMemberType(IContentTypeComposition mediaType, string elementName) { var info = new XElement( @@ -423,6 +424,7 @@ private XElement SerializeMediaOrMemberType(IContentTypeComposition mediaType, s return xml; } + /// public XElement Serialize(IContentType contentType) { var info = new XElement( @@ -526,6 +528,11 @@ public XElement Serialize(IContentType contentType) return xml; } + /// + /// Serializes a single dictionary item to an without child items. + /// + /// The dictionary item to serialize. + /// An containing the XML representation of the dictionary item. private XElement Serialize(IDictionaryItem dictionaryItem) { var xml = new XElement( @@ -544,6 +551,12 @@ private XElement Serialize(IDictionaryItem dictionaryItem) return xml; } + /// + /// Serializes property types to a collection of objects. + /// + /// The property types to serialize. + /// The property groups for looking up group information. + /// A collection of objects representing the property types. private IEnumerable SerializePropertyTypes( IEnumerable propertyTypes, IEnumerable propertyGroups) @@ -563,6 +576,11 @@ private IEnumerable SerializePropertyTypes( } } + /// + /// Serializes property groups to a collection of objects. + /// + /// The property groups to serialize. + /// A collection of objects representing the property groups. private IEnumerable SerializePropertyGroups(IEnumerable propertyGroups) { foreach (PropertyGroup propertyGroup in propertyGroups) @@ -578,6 +596,13 @@ private IEnumerable SerializePropertyGroups(IEnumerable } } + /// + /// Serializes a single property type to an . + /// + /// The property type to serialize. + /// The data type definition for the property. + /// The property group the property belongs to, if any. + /// An containing the XML representation of the property type. private XElement SerializePropertyType(IPropertyType propertyType, IDataType? definition, PropertyGroup? propertyGroup) => new( "GenericProperty", @@ -595,6 +620,11 @@ private XElement SerializePropertyType(IPropertyType propertyType, IDataType? de propertyType.ValidationRegExpMessage != null ? new XElement("ValidationRegExpMessage", propertyType.ValidationRegExpMessage) : null, propertyType.Description != null ? new XElement("Description", new XCData(propertyType.Description)) : null); + /// + /// Serializes a history cleanup policy to an . + /// + /// The cleanup policy to serialize. + /// An containing the XML representation of the cleanup policy. private XElement SerializeCleanupPolicy(HistoryCleanup cleanupPolicy) { if (cleanupPolicy == null) @@ -619,7 +649,14 @@ private XElement SerializeCleanupPolicy(HistoryCleanup cleanupPolicy) return element; } - // exports an IContentBase (IContent, IMedia or IMember) as an XElement. + /// + /// Exports an (IContent, IMedia or IMember) as an . + /// + /// The content base item to serialize. + /// The URL segment value for the content. + /// The XML node name to use. + /// Whether to serialize the published version. + /// An containing the XML representation of the content base. private XElement SerializeContentBase(IContentBase contentBase, string? urlValue, string nodeName, bool published) { var xml = new XElement( @@ -651,7 +688,12 @@ private XElement SerializeContentBase(IContentBase contentBase, string? urlValue return xml; } - // exports a property as XElements. + /// + /// Exports a property as objects. + /// + /// The property to serialize. + /// Whether to serialize the published value. + /// A collection of objects representing the property. private IEnumerable SerializeProperty(IProperty property, bool published) { IPropertyType propertyType = property.PropertyType; @@ -663,7 +705,12 @@ private IEnumerable SerializeProperty(IProperty property, bool publish : propertyEditor.GetValueEditor().ConvertDbToXml(property, published); } - // exports an IContent item descendants. + /// + /// Exports item descendants recursively. + /// + /// The child content items to serialize. + /// The parent XML element to add children to. + /// Whether to serialize the published version. private void SerializeChildren(IEnumerable children, XElement xml, bool published) { foreach (IContent child in children) @@ -686,7 +733,12 @@ private void SerializeChildren(IEnumerable children, XElement xml, boo } } - // exports an IMedia item descendants. + /// + /// Exports item descendants recursively. + /// + /// The child media items to serialize. + /// The parent XML element to add children to. + /// Optional callback invoked after each media item is serialized. private void SerializeChildren(IEnumerable children, XElement xml, Action? onMediaItemSerialized) { foreach (IMedia child in children) @@ -710,12 +762,19 @@ private void SerializeChildren(IEnumerable children, XElement xml, Actio } /// - /// We have two properties containing configuration data: - /// 1. ConfigurationData - a dictionary that contains all the configuration data stored as key/value pairs. - /// 2. ConfigurationObject - a strongly typed object that represents the configuration data known to the server. - /// To fully be able to restore the package, we need to serialize the full ConfigurationData dictionary, not - /// just the configuration properties known to the server. + /// Serializes the configuration data for a data type to JSON. /// + /// The data type whose configuration to serialize. + /// A JSON string representing the data type configuration. + /// + /// We have two properties containing configuration data: + /// + /// ConfigurationData - a dictionary that contains all the configuration data stored as key/value pairs. + /// ConfigurationObject - a strongly typed object that represents the configuration data known to the server. + /// + /// To fully be able to restore the package, we need to serialize the full ConfigurationData dictionary, not + /// just the configuration properties known to the server. + /// private string SerializeDataTypeConfiguration(IDataType dataType) => _configurationEditorJsonSerializer.Serialize(dataType.ConfigurationData); } diff --git a/src/Umbraco.Core/Services/ExternalLoginService.cs b/src/Umbraco.Core/Services/ExternalLoginService.cs index 29c503629d5b..3eb76b708cbf 100644 --- a/src/Umbraco.Core/Services/ExternalLoginService.cs +++ b/src/Umbraco.Core/Services/ExternalLoginService.cs @@ -6,11 +6,26 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing external login providers and tokens for users and members. +/// +/// +/// This service handles OAuth/OpenID Connect external login associations, allowing users +/// to authenticate via external providers like Google, Microsoft, Facebook, etc. +/// public class ExternalLoginService : RepositoryService, IExternalLoginWithKeyService { private readonly IExternalLoginWithKeyRepository _externalLoginRepository; private readonly IUserRepository _userRepository; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for external login data access. + /// The repository for user data access. public ExternalLoginService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -23,6 +38,12 @@ public ExternalLoginService( _userRepository = userRepository; } + /// + /// Finds external logins matching the specified login provider and provider key. + /// + /// The name of the external login provider (e.g., "Google", "Microsoft"). + /// The unique key assigned by the external provider for the user. + /// A collection of matching external login records. public IEnumerable Find(string loginProvider, string providerKey) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) diff --git a/src/Umbraco.Core/Services/FileService.cs b/src/Umbraco.Core/Services/FileService.cs index cf0873c2e8bc..833f9727f83f 100644 --- a/src/Umbraco.Core/Services/FileService.cs +++ b/src/Umbraco.Core/Services/FileService.cs @@ -18,9 +18,14 @@ namespace Umbraco.Cms.Core.Services; /// -/// Represents the File Service, which is an easy access to operations involving objects like -/// Scripts, Stylesheets and Templates +/// Represents the File Service, which provides access to operations involving objects like +/// Scripts, Stylesheets, Templates, and Partial Views. /// +/// +/// Many methods in this service are marked as obsolete. For new implementations, use the specific +/// services: , , , +/// , and their corresponding folder services. +/// public class FileService : RepositoryService, IFileService { private const string PartialViewHeader = "@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage"; @@ -33,6 +38,20 @@ public class FileService : RepositoryService, IFileService private readonly ITemplateRepository _templateRepository; private readonly IUserIdKeyResolver _userIdKeyResolver; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for stylesheet operations. + /// The repository for script operations. + /// The repository for partial view operations. + /// The audit service for logging operations. + /// The hosting environment for path resolution. + /// The template service for template operations. + /// The template repository for direct template access. + /// The resolver for converting user IDs to keys. public FileService( ICoreScopeProvider uowProvider, ILoggerFactory loggerFactory, @@ -57,6 +76,22 @@ public FileService( _userIdKeyResolver = userIdKeyResolver; } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for stylesheet operations. + /// The repository for script operations. + /// The repository for partial view operations. + /// The audit repository (no longer used). + /// The hosting environment for path resolution. + /// The template service for template operations. + /// The template repository for direct template access. + /// The resolver for converting user IDs to keys. + /// The short string helper (no longer used). + /// The global settings options (no longer used). [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public FileService( ICoreScopeProvider uowProvider, @@ -87,6 +122,23 @@ public FileService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for stylesheet operations. + /// The repository for script operations. + /// The repository for partial view operations. + /// The audit service for logging operations. + /// The audit repository (no longer used). + /// The hosting environment for path resolution. + /// The template service for template operations. + /// The template repository for direct template access. + /// The resolver for converting user IDs to keys. + /// The short string helper (no longer used). + /// The global settings options (no longer used). [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public FileService( ICoreScopeProvider uowProvider, @@ -130,9 +182,24 @@ public IEnumerable GetStylesheets(params string[] paths) } } + /// + /// Records an audit entry synchronously. + /// + /// The type of audit action. + /// The ID of the user performing the action. + /// The ID of the object being acted upon. + /// The type of entity being audited. private void Audit(AuditType type, int userId, int objectId, string? entityType) => AuditAsync(type, userId, objectId, entityType).GetAwaiter().GetResult(); + /// + /// Records an audit entry asynchronously. + /// + /// The type of audit action. + /// The ID of the user performing the action. + /// The ID of the object being acted upon. + /// The type of entity being audited. + /// A task that represents the asynchronous operation. private async Task AuditAsync(AuditType type, int userId, int objectId, string? entityType) { Guid userKey = await _userIdKeyResolver.GetAsync(userId); @@ -618,6 +685,7 @@ public long GetTemplateFileSize(string filepath) #region Partial Views + /// [Obsolete("Please use IPartialViewFolderService for partial view folder operations - will be removed in Umbraco 15")] public void DeletePartialViewFolder(string folderPath) { @@ -628,6 +696,7 @@ public void DeletePartialViewFolder(string folderPath) } } + /// [Obsolete("Please use IPartialViewService for partial view operations - will be removed in Umbraco 15")] public IEnumerable GetPartialViews(params string[] names) { @@ -637,6 +706,7 @@ public IEnumerable GetPartialViews(params string[] names) } } + /// [Obsolete("Please use IPartialViewService for partial view operations - will be removed in Umbraco 15")] public IPartialView? GetPartialView(string path) { @@ -646,6 +716,7 @@ public IEnumerable GetPartialViews(params string[] names) } } + /// [Obsolete("Please use IPartialViewService for partial view operations - will be removed in Umbraco 15")] public Attempt CreatePartialView(IPartialView partialView, string? snippetName = null, int? userId = Constants.Security.SuperUserId) { @@ -701,6 +772,7 @@ public IEnumerable GetPartialViews(params string[] names) return Attempt.Succeed(partialView); } + /// [Obsolete("Please use IPartialViewService for partial view operations - will be removed in Umbraco 15")] public Attempt SavePartialView(IPartialView partialView, int? userId = null) { @@ -727,6 +799,7 @@ public IEnumerable GetPartialViews(params string[] names) return Attempt.Succeed(partialView); } + /// [Obsolete("Please use IPartialViewService for partial view operations - will be removed in Umbraco 15")] public bool DeletePartialView(string path, int? userId = null) { @@ -759,6 +832,7 @@ public bool DeletePartialView(string path, int? userId = null) return true; } + /// [Obsolete("Please use IPartialViewFolderService for partial view folder operations - will be removed in Umbraco 15")] public void CreatePartialViewFolder(string folderPath) { @@ -769,12 +843,22 @@ public void CreatePartialViewFolder(string folderPath) } } + /// + /// Strips the @inherits directive header from partial view contents. + /// + /// The partial view content. + /// The content with the header stripped. internal string StripPartialViewHeader(string contents) { var headerMatch = new Regex("^@inherits\\s+?.*$", RegexOptions.Multiline); return headerMatch.Replace(contents, string.Empty); } + /// + /// Attempts to get the file system path to a snippet file. + /// + /// The name of the snippet file. + /// An containing the path if found; otherwise, a failed attempt. internal Attempt TryGetSnippetPath(string? fileName) { if (fileName?.EndsWith(".cshtml") == false) diff --git a/src/Umbraco.Core/Services/FileServiceBase.cs b/src/Umbraco.Core/Services/FileServiceBase.cs index 62215efd234e..9c461dd7462e 100644 --- a/src/Umbraco.Core/Services/FileServiceBase.cs +++ b/src/Umbraco.Core/Services/FileServiceBase.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence; @@ -8,12 +8,31 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides base functionality for file-based services that manage file entities like scripts, stylesheets, and partial views. +/// +/// The type of repository used for file operations. +/// The type of file entity being managed. +/// +/// This abstract class provides common file operations including retrieval, content streaming, and validation +/// for file-based entities stored in the file system. +/// public abstract class FileServiceBase : RepositoryService, IBasicFileService where TRepository : IFileRepository, IReadRepository where TEntity : IFile { + /// + /// Gets the repository used for file operations. + /// public TRepository Repository { get; } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for file data access. public FileServiceBase( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -24,11 +43,24 @@ public FileServiceBase( Repository = repository; } + /// + /// Gets the allowed file extensions for this file type. + /// protected abstract string[] AllowedFileExtensions { get; } + /// + /// Determines whether the specified file name has a valid file extension. + /// + /// The file name to validate. + /// true if the file extension is valid; otherwise, false. protected virtual bool HasValidFileExtension(string fileName) => AllowedFileExtensions.Contains(Path.GetExtension(fileName)); + /// + /// Determines whether the specified file name is valid. + /// + /// The file name to validate. + /// true if the file name is valid; otherwise, false. protected virtual bool HasValidFileName(string fileName) { if (fileName.ContainsAny(Path.GetInvalidFileNameChars())) @@ -40,12 +72,14 @@ protected virtual bool HasValidFileName(string fileName) } /// - /// Checks if a path is considered a root path. + /// Checks if a path is considered a root path. /// /// The path to check. - /// True if the path is considered a root path. + /// true if the path is considered a root path; otherwise, false. + /// + /// We use "/" here instead of path separator because it's the virtual path used by backoffice, and not an actual file system path. + /// protected virtual bool IsRootPath(string? path) - // We use "/" here instead of path separator because it's the virtual path used by backoffice, and not an actual FS path. => string.IsNullOrWhiteSpace(path) || path == "/"; /// diff --git a/src/Umbraco.Core/Services/FileServiceOperationBase.cs b/src/Umbraco.Core/Services/FileServiceOperationBase.cs index 88501af28a7c..4b3c6269d205 100644 --- a/src/Umbraco.Core/Services/FileServiceOperationBase.cs +++ b/src/Umbraco.Core/Services/FileServiceOperationBase.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; @@ -11,6 +11,16 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides base functionality for file services that support CRUD operations with notifications and auditing. +/// +/// The type of repository used for file operations, supporting read, write, and folder operations. +/// The type of file entity being managed. +/// The enum type representing operation status codes. +/// +/// This abstract class extends to add support for +/// create, update, rename, and delete operations with proper notification publishing and audit logging. +/// public abstract class FileServiceOperationBase : FileServiceBase where TRepository : IFileRepository, IReadRepository, IWriteRepository, IFileWithFoldersRepository where TEntity : IFile @@ -20,6 +30,16 @@ public abstract class FileServiceOperationBase + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for file data access. + /// The logger for operation logging. + /// The resolver for converting user IDs to keys. + /// The audit service for logging operations. protected FileServiceOperationBase( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -35,6 +55,16 @@ protected FileServiceOperationBase( _auditService = auditService; } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The file repository. + /// The logger. + /// The user ID key resolver. + /// The audit repository. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] protected FileServiceOperationBase( ICoreScopeProvider provider, @@ -55,34 +85,97 @@ protected FileServiceOperationBase( { } + /// + /// Gets the operation status value representing a successful operation. + /// protected abstract TOperationStatus Success { get; } + /// + /// Gets the operation status value representing an entity not found condition. + /// protected abstract TOperationStatus NotFound { get; } + /// + /// Gets the operation status value representing a cancellation by notification handler. + /// protected abstract TOperationStatus CancelledByNotification { get; } + /// + /// Gets the operation status value representing a path that exceeds maximum length. + /// protected abstract TOperationStatus PathTooLong { get; } + /// + /// Gets the operation status value representing an entity that already exists. + /// protected abstract TOperationStatus AlreadyExists { get; } + /// + /// Gets the operation status value representing a parent folder not found condition. + /// protected abstract TOperationStatus ParentNotFound { get; } + /// + /// Gets the operation status value representing an invalid file name. + /// protected abstract TOperationStatus InvalidName { get; } + /// + /// Gets the operation status value representing an invalid file extension. + /// protected abstract TOperationStatus InvalidFileExtension { get; } + /// + /// Gets the entity type name used for audit logging. + /// protected abstract string EntityType { get; } + /// + /// Creates a saving notification for the specified entity. + /// + /// The entity being saved. + /// The event messages to include. + /// A saving notification instance. protected abstract SavingNotification SavingNotification(TEntity target, EventMessages messages); + /// + /// Creates a saved notification for the specified entity. + /// + /// The entity that was saved. + /// The event messages to include. + /// A saved notification instance. protected abstract SavedNotification SavedNotification(TEntity target, EventMessages messages); + /// + /// Creates a deleting notification for the specified entity. + /// + /// The entity being deleted. + /// The event messages to include. + /// A deleting notification instance. protected abstract DeletingNotification DeletingNotification(TEntity target, EventMessages messages); + /// + /// Creates a deleted notification for the specified entity. + /// + /// The entity that was deleted. + /// The event messages to include. + /// A deleted notification instance. protected abstract DeletedNotification DeletedNotification(TEntity target, EventMessages messages); + /// + /// Creates a new entity instance with the specified path and content. + /// + /// The file path for the entity. + /// The optional content of the file. + /// A new entity instance. protected abstract TEntity CreateEntity(string path, string? content); + /// + /// Handles the deletion of a file entity. + /// + /// The path of the file to delete. + /// The unique identifier of the user performing the operation. + /// The operation status indicating success or failure reason. protected async Task HandleDeleteAsync(string path, Guid userKey) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -109,6 +202,14 @@ protected async Task HandleDeleteAsync(string path, Guid userK return Success; } + /// + /// Handles the creation of a new file entity. + /// + /// The name of the file to create. + /// The optional parent folder path. + /// The optional initial content of the file. + /// The unique identifier of the user performing the operation. + /// An attempt containing the created entity and operation status. protected async Task> HandleCreateAsync(string name, string? parentPath, string? content, Guid userKey) { if (name.Contains('/')) @@ -151,6 +252,13 @@ protected async Task HandleDeleteAsync(string path, Guid userK return Attempt.SucceedWithStatus(Success, entity); } + /// + /// Handles the update of an existing file entity's content. + /// + /// The path of the file to update. + /// The new content for the file. + /// The unique identifier of the user performing the operation. + /// An attempt containing the updated entity and operation status. protected async Task> HandleUpdateAsync(string path, string content, Guid userKey) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -180,6 +288,13 @@ protected async Task HandleDeleteAsync(string path, Guid userK return Attempt.SucceedWithStatus(Success, entity); } + /// + /// Handles the renaming of an existing file entity. + /// + /// The current path of the file. + /// The new name for the file. + /// The unique identifier of the user performing the operation. + /// An attempt containing the renamed entity and operation status. protected async Task> HandleRenameAsync(string path, string newName, Guid userKey) { if (newName.Contains('/')) @@ -230,6 +345,11 @@ protected async Task HandleDeleteAsync(string path, Guid userK return Attempt.SucceedWithStatus(Success, entity); } + /// + /// Validates that a file can be created at the specified path. + /// + /// The path to validate. + /// The operation status indicating success or the validation failure reason. private TOperationStatus ValidateCreate(string path) { if (Repository.Exists(path)) @@ -257,6 +377,12 @@ private TOperationStatus ValidateCreate(string path) return Success; } + /// + /// Validates that a file can be renamed with the specified new name. + /// + /// The new name for the file. + /// The new path after renaming. + /// The operation status indicating success or the validation failure reason. private TOperationStatus ValidateRename(string newName, string newPath) { if (Repository.Exists(newPath)) @@ -277,18 +403,45 @@ private TOperationStatus ValidateRename(string newName, string newPath) return Success; } + /// + /// Creates an audit entry for the specified operation. + /// + /// The type of audit entry. + /// The unique identifier of the user performing the operation. private async Task AuditAsync(AuditType type, Guid userKey) => await _auditService.AddAsync(type, userKey, -1, EntityType); + /// + /// Combines a parent path and file name into a full file path. + /// + /// The parent directory path, or null for root. + /// The file name. + /// The combined file path. private string GetFilePath(string? parentPath, string fileName) => Path.Join(parentPath, fileName); + /// + /// Replaces the file name in a path with a new name. + /// + /// The current file path. + /// The new file name. + /// The path with the replaced file name. private string ReplaceFileName(string path, string newName) => Path.Join(GetDirectoryPath(path), newName); + /// + /// Gets the directory path from a full file path. + /// + /// The full file path. + /// The directory path, or an empty string if not found. private string GetDirectoryPath(string path) => Path.GetDirectoryName(path) ?? string.Empty; + /// + /// Gets the file name from a full file path. + /// + /// The full file path. + /// The file name. private string GetFileName(string path) => Path.GetFileName(path); } diff --git a/src/Umbraco.Core/Services/FileSystem/FolderServiceOperationBase.cs b/src/Umbraco.Core/Services/FileSystem/FolderServiceOperationBase.cs index 95766a9a6faf..85b13e768e4b 100644 --- a/src/Umbraco.Core/Services/FileSystem/FolderServiceOperationBase.cs +++ b/src/Umbraco.Core/Services/FileSystem/FolderServiceOperationBase.cs @@ -5,6 +5,17 @@ namespace Umbraco.Cms.Core.Services.FileSystem; +/// +/// Provides a base implementation for folder service operations in the file system. +/// +/// The type of the repository that implements . +/// The type of the folder model that inherits from . +/// The type of the operation status enumeration. +/// +/// This abstract base class provides common functionality for creating, deleting, and retrieving +/// folders in the file system. Derived classes must provide the specific operation status values +/// for their respective folder types. +/// internal abstract class FolderServiceOperationBase where TRepository : IFileWithFoldersRepository where TFolderModel : FolderModelBase, new() @@ -14,24 +25,57 @@ internal abstract class FolderServiceOperationBase + /// Initializes a new instance of the class. + /// + /// The repository for file system operations. + /// The scope provider for database transactions. protected FolderServiceOperationBase(TRepository repository, ICoreScopeProvider scopeProvider) { _repository = repository; _scopeProvider = scopeProvider; } + /// + /// Gets the operation status value indicating a successful operation. + /// protected abstract TOperationStatus Success { get; } + /// + /// Gets the operation status value indicating that the folder was not found. + /// protected abstract TOperationStatus NotFound { get; } + /// + /// Gets the operation status value indicating that the folder is not empty. + /// protected abstract TOperationStatus NotEmpty { get; } + /// + /// Gets the operation status value indicating that a folder already exists at the specified path. + /// protected abstract TOperationStatus AlreadyExists { get; } + /// + /// Gets the operation status value indicating that the parent folder was not found. + /// protected abstract TOperationStatus ParentNotFound { get; } + /// + /// Gets the operation status value indicating that the folder name is invalid. + /// protected abstract TOperationStatus InvalidName { get; } + /// + /// Handles the creation of a new folder. + /// + /// The name of the folder to create. + /// The path of the parent folder, or null for root-level folders. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the created folder model on success, + /// or the appropriate operation status on failure. + /// protected Task> HandleCreateAsync(string name, string? parentPath) { using ICoreScope scope = _scopeProvider.CreateCoreScope(); @@ -56,6 +100,14 @@ protected FolderServiceOperationBase(TRepository repository, ICoreScopeProvider return Task.FromResult(Attempt.SucceedWithStatus(Success, result)); } + /// + /// Handles the deletion of a folder. + /// + /// The path of the folder to delete. + /// + /// A task that represents the asynchronous operation. The task result contains + /// the operation status indicating success or the reason for failure. + /// protected Task HandleDeleteAsync(string path) { using ICoreScope scope = _scopeProvider.CreateCoreScope(); @@ -73,6 +125,14 @@ protected Task HandleDeleteAsync(string path) return Task.FromResult(Success); } + /// + /// Handles retrieving a folder by its path. + /// + /// The path of the folder to retrieve. + /// + /// A task that represents the asynchronous operation. The task result contains + /// the folder model if found; otherwise, null. + /// protected Task HandleGetAsync(string path) { using ICoreScope scope = _scopeProvider.CreateCoreScope(); @@ -95,6 +155,16 @@ protected Task HandleDeleteAsync(string path) return Task.FromResult(result); } + /// + /// Validates that a folder can be created with the specified parameters. + /// + /// The name of the folder to create. + /// The full path of the folder to create. + /// The path of the parent folder, or null for root-level folders. + /// + /// The status if validation passes; otherwise, the appropriate + /// error status indicating why the folder cannot be created. + /// private TOperationStatus ValidateCreate(string name, string path, string? parentPath) { if (name.ContainsAny(Path.GetInvalidFileNameChars())) @@ -115,6 +185,14 @@ private TOperationStatus ValidateCreate(string name, string path, string? parent return Success; } + /// + /// Validates that a folder can be deleted at the specified path. + /// + /// The path of the folder to delete. + /// + /// The status if validation passes; otherwise, the appropriate + /// error status indicating why the folder cannot be deleted. + /// private TOperationStatus ValidateDelete(string path) { if (_repository.FolderExists(path) is false) @@ -130,12 +208,28 @@ private TOperationStatus ValidateDelete(string path) return Success; } + /// + /// Constructs the full folder path by combining the parent path and folder name. + /// + /// The name of the folder. + /// The path of the parent folder, or null for root-level folders. + /// The combined folder path. private string GetFolderPath(string folderName, string? parentPath) => Path.Join(parentPath, folderName); + /// + /// Extracts the folder name from a full path. + /// + /// The full path to the folder. + /// The folder name. private string GetFolderName(string path) => Path.GetFileName(path); + /// + /// Extracts the parent folder path from a full path. + /// + /// The full path to the folder. + /// The parent folder path, or null if the folder is at the root level. private string? GetParentFolderPath(string path) => Path.GetDirectoryName(path); } diff --git a/src/Umbraco.Core/Services/FileSystem/IPartialViewFolderService.cs b/src/Umbraco.Core/Services/FileSystem/IPartialViewFolderService.cs index e35144623a3d..256ca1c2f906 100644 --- a/src/Umbraco.Core/Services/FileSystem/IPartialViewFolderService.cs +++ b/src/Umbraco.Core/Services/FileSystem/IPartialViewFolderService.cs @@ -1,13 +1,41 @@ -using Umbraco.Cms.Core.Models.FileSystem; +using Umbraco.Cms.Core.Models.FileSystem; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services.FileSystem; +/// +/// Defines the contract for a service that manages partial view folders in the file system. +/// public interface IPartialViewFolderService { + /// + /// Gets a partial view folder by its path. + /// + /// The path to the partial view folder. + /// + /// A task that represents the asynchronous operation. The task result contains the + /// if found; otherwise, null. + /// Task GetAsync(string path); + /// + /// Creates a new partial view folder. + /// + /// The model containing the folder creation details. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the created + /// on success, or a indicating the failure reason. + /// Task> CreateAsync(PartialViewFolderCreateModel createModel); + /// + /// Deletes a partial view folder at the specified path. + /// + /// The path to the partial view folder to delete. + /// + /// A task that represents the asynchronous operation. The task result contains a + /// indicating the result of the operation. + /// Task DeleteAsync(string path); } diff --git a/src/Umbraco.Core/Services/FileSystem/IScriptFolderService.cs b/src/Umbraco.Core/Services/FileSystem/IScriptFolderService.cs index 7fe2efe7c984..2eb386bfae9f 100644 --- a/src/Umbraco.Core/Services/FileSystem/IScriptFolderService.cs +++ b/src/Umbraco.Core/Services/FileSystem/IScriptFolderService.cs @@ -1,13 +1,41 @@ -using Umbraco.Cms.Core.Models.FileSystem; +using Umbraco.Cms.Core.Models.FileSystem; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services.FileSystem; +/// +/// Defines the contract for a service that manages script folders in the file system. +/// public interface IScriptFolderService { + /// + /// Gets a script folder by its path. + /// + /// The path to the script folder. + /// + /// A task that represents the asynchronous operation. The task result contains the + /// if found; otherwise, null. + /// Task GetAsync(string path); + /// + /// Creates a new script folder. + /// + /// The model containing the folder creation details. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the created + /// on success, or a indicating the failure reason. + /// Task> CreateAsync(ScriptFolderCreateModel createModel); + /// + /// Deletes a script folder at the specified path. + /// + /// The path to the script folder to delete. + /// + /// A task that represents the asynchronous operation. The task result contains a + /// indicating the result of the operation. + /// Task DeleteAsync(string path); } diff --git a/src/Umbraco.Core/Services/FileSystem/IStylesheetFolderService.cs b/src/Umbraco.Core/Services/FileSystem/IStylesheetFolderService.cs index f17163405f56..ef48882e3a68 100644 --- a/src/Umbraco.Core/Services/FileSystem/IStylesheetFolderService.cs +++ b/src/Umbraco.Core/Services/FileSystem/IStylesheetFolderService.cs @@ -1,13 +1,41 @@ -using Umbraco.Cms.Core.Models.FileSystem; +using Umbraco.Cms.Core.Models.FileSystem; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services.FileSystem; +/// +/// Defines the contract for a service that manages stylesheet folders in the file system. +/// public interface IStylesheetFolderService { + /// + /// Gets a stylesheet folder by its path. + /// + /// The path to the stylesheet folder. + /// + /// A task that represents the asynchronous operation. The task result contains the + /// if found; otherwise, null. + /// Task GetAsync(string path); + /// + /// Creates a new stylesheet folder. + /// + /// The model containing the folder creation details. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the created + /// on success, or a indicating the failure reason. + /// Task> CreateAsync(StylesheetFolderCreateModel createModel); + /// + /// Deletes a stylesheet folder at the specified path. + /// + /// The path to the stylesheet folder to delete. + /// + /// A task that represents the asynchronous operation. The task result contains a + /// indicating the result of the operation. + /// Task DeleteAsync(string path); } diff --git a/src/Umbraco.Core/Services/FileSystem/PartialViewFolderService.cs b/src/Umbraco.Core/Services/FileSystem/PartialViewFolderService.cs index 0625ebf7d14a..c57fdc905260 100644 --- a/src/Umbraco.Core/Services/FileSystem/PartialViewFolderService.cs +++ b/src/Umbraco.Core/Services/FileSystem/PartialViewFolderService.cs @@ -1,35 +1,57 @@ -using Umbraco.Cms.Core.Models.FileSystem; +using Umbraco.Cms.Core.Models.FileSystem; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services.FileSystem; +/// +/// Provides a service for managing partial view folders in the file system. +/// +/// +/// This service handles the creation, retrieval, and deletion of folders within the partial view +/// file system area. It inherits common folder operation logic from +/// . +/// internal sealed class PartialViewFolderService : FolderServiceOperationBase, IPartialViewFolderService { + /// + /// Initializes a new instance of the class. + /// + /// The partial view repository for file system operations. + /// The scope provider for database transactions. public PartialViewFolderService(IPartialViewRepository repository, ICoreScopeProvider scopeProvider) : base(repository, scopeProvider) { } + /// protected override PartialViewFolderOperationStatus Success => PartialViewFolderOperationStatus.Success; + /// protected override PartialViewFolderOperationStatus NotFound => PartialViewFolderOperationStatus.NotFound; + /// protected override PartialViewFolderOperationStatus NotEmpty => PartialViewFolderOperationStatus.NotEmpty; + /// protected override PartialViewFolderOperationStatus AlreadyExists => PartialViewFolderOperationStatus.AlreadyExists; + /// protected override PartialViewFolderOperationStatus ParentNotFound => PartialViewFolderOperationStatus.ParentNotFound; + /// protected override PartialViewFolderOperationStatus InvalidName => PartialViewFolderOperationStatus.InvalidName; + /// public async Task GetAsync(string path) => await HandleGetAsync(path); + /// public async Task> CreateAsync(PartialViewFolderCreateModel createModel) => await HandleCreateAsync(createModel.Name, createModel.ParentPath); + /// public async Task DeleteAsync(string path) => await HandleDeleteAsync(path); } diff --git a/src/Umbraco.Core/Services/FileSystem/ScriptFolderService.cs b/src/Umbraco.Core/Services/FileSystem/ScriptFolderService.cs index 0bca13a1eda2..7a872ccc2446 100644 --- a/src/Umbraco.Core/Services/FileSystem/ScriptFolderService.cs +++ b/src/Umbraco.Core/Services/FileSystem/ScriptFolderService.cs @@ -1,35 +1,57 @@ -using Umbraco.Cms.Core.Models.FileSystem; +using Umbraco.Cms.Core.Models.FileSystem; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services.FileSystem; +/// +/// Provides a service for managing script folders in the file system. +/// +/// +/// This service handles the creation, retrieval, and deletion of folders within the script +/// file system area. It inherits common folder operation logic from +/// . +/// internal sealed class ScriptFolderService : FolderServiceOperationBase, IScriptFolderService { + /// + /// Initializes a new instance of the class. + /// + /// The script repository for file system operations. + /// The scope provider for database transactions. public ScriptFolderService(IScriptRepository repository, ICoreScopeProvider scopeProvider) : base(repository, scopeProvider) { } + /// protected override ScriptFolderOperationStatus Success => ScriptFolderOperationStatus.Success; + /// protected override ScriptFolderOperationStatus NotFound => ScriptFolderOperationStatus.NotFound; + /// protected override ScriptFolderOperationStatus NotEmpty => ScriptFolderOperationStatus.NotEmpty; + /// protected override ScriptFolderOperationStatus AlreadyExists => ScriptFolderOperationStatus.AlreadyExists; + /// protected override ScriptFolderOperationStatus ParentNotFound => ScriptFolderOperationStatus.ParentNotFound; + /// protected override ScriptFolderOperationStatus InvalidName => ScriptFolderOperationStatus.InvalidName; + /// public async Task GetAsync(string path) => await HandleGetAsync(path); + /// public async Task> CreateAsync(ScriptFolderCreateModel createModel) => await HandleCreateAsync(createModel.Name, createModel.ParentPath); + /// public async Task DeleteAsync(string path) => await HandleDeleteAsync(path); } diff --git a/src/Umbraco.Core/Services/FileSystem/StylesheetFolderService.cs b/src/Umbraco.Core/Services/FileSystem/StylesheetFolderService.cs index 84bcbf3a18ec..b1e51f7f32fa 100644 --- a/src/Umbraco.Core/Services/FileSystem/StylesheetFolderService.cs +++ b/src/Umbraco.Core/Services/FileSystem/StylesheetFolderService.cs @@ -1,35 +1,57 @@ -using Umbraco.Cms.Core.Models.FileSystem; +using Umbraco.Cms.Core.Models.FileSystem; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services.FileSystem; +/// +/// Provides a service for managing stylesheet folders in the file system. +/// +/// +/// This service handles the creation, retrieval, and deletion of folders within the stylesheet +/// file system area. It inherits common folder operation logic from +/// . +/// internal sealed class StylesheetFolderService : FolderServiceOperationBase, IStylesheetFolderService { + /// + /// Initializes a new instance of the class. + /// + /// The stylesheet repository for file system operations. + /// The scope provider for database transactions. public StylesheetFolderService(IStylesheetRepository repository, ICoreScopeProvider scopeProvider) : base(repository, scopeProvider) { } + /// protected override StylesheetFolderOperationStatus Success => StylesheetFolderOperationStatus.Success; + /// protected override StylesheetFolderOperationStatus NotFound => StylesheetFolderOperationStatus.NotFound; + /// protected override StylesheetFolderOperationStatus NotEmpty => StylesheetFolderOperationStatus.NotEmpty; + /// protected override StylesheetFolderOperationStatus AlreadyExists => StylesheetFolderOperationStatus.AlreadyExists; + /// protected override StylesheetFolderOperationStatus ParentNotFound => StylesheetFolderOperationStatus.ParentNotFound; + /// protected override StylesheetFolderOperationStatus InvalidName => StylesheetFolderOperationStatus.InvalidName; + /// public async Task GetAsync(string path) => await HandleGetAsync(path); + /// public async Task> CreateAsync(StylesheetFolderCreateModel createModel) => await HandleCreateAsync(createModel.Name, createModel.ParentPath); + /// public async Task DeleteAsync(string path) => await HandleDeleteAsync(path); } diff --git a/src/Umbraco.Core/Services/Filters/IContentTypeFilter.cs b/src/Umbraco.Core/Services/Filters/IContentTypeFilter.cs index d872c58d57b1..7a5db6591d9d 100644 --- a/src/Umbraco.Core/Services/Filters/IContentTypeFilter.cs +++ b/src/Umbraco.Core/Services/Filters/IContentTypeFilter.cs @@ -10,6 +10,7 @@ public interface IContentTypeFilter /// /// Filters the content types retrieved for being allowed at the root. /// + /// The type of content type, which must implement . /// Retrieved collection of content types. /// Filtered collection of content types. Task> FilterAllowedAtRootAsync(IEnumerable contentTypes) diff --git a/src/Umbraco.Core/Services/IAuditService.cs b/src/Umbraco.Core/Services/IAuditService.cs index eaca8dde697a..66f0c924a238 100644 --- a/src/Umbraco.Core/Services/IAuditService.cs +++ b/src/Umbraco.Core/Services/IAuditService.cs @@ -27,6 +27,15 @@ public Task> AddAsync( string? comment = null, string? parameters = null) => throw new NotImplementedException(); + /// + /// Adds an audit log entry. + /// + /// The type of audit entry. + /// The identifier of the user performing the action. + /// The identifier of the object being audited. + /// The type of entity being audited. + /// A comment describing the action. + /// Optional parameters associated with the audit entry. [Obsolete("Use AddAsync() instead. Scheduled for removal in Umbraco 19.")] void Add(AuditType type, int userId, int objectId, string? entityType, string comment, string? parameters = null); @@ -53,6 +62,12 @@ public Task> GetItemsAsync( DateTimeOffset? sinceDate = null, AuditType[]? auditTypeFilter = null) => throw new NotImplementedException(); + /// + /// Gets audit logs filtered by audit type. + /// + /// The audit type to filter by. + /// Optional date to filter logs since. + /// A collection of audit items matching the criteria. [Obsolete("Use GetItemsAsync() instead. Scheduled for removal in Umbraco 19.")] IEnumerable GetLogs(AuditType type, DateTime? sinceDate = null); @@ -136,6 +151,11 @@ IEnumerable GetPagedItemsByEntity( AuditType[]? auditTypeFilter = null, IQuery? customFilter = null); + /// + /// Gets audit logs for a specific object. + /// + /// The identifier of the object to get logs for. + /// A collection of audit items for the specified object. [Obsolete("Use GetItemsByEntityAsync() instead. Scheduled for removal in Umbraco 19.")] IEnumerable GetLogs(int objectId); @@ -191,6 +211,13 @@ IEnumerable GetPagedItemsByUser( AuditType[]? auditTypeFilter = null, IQuery? customFilter = null); + /// + /// Gets audit logs for a specific user filtered by audit type. + /// + /// The identifier of the user. + /// The audit type to filter by. + /// Optional date to filter logs since. + /// A collection of audit items for the specified user matching the criteria. [Obsolete("Use GetPagedItemsByUserAsync() instead. Scheduled for removal in Umbraco 19.")] IEnumerable GetUserLogs(int userId, AuditType type, DateTime? sinceDate = null); @@ -231,6 +258,10 @@ IAuditEntry Write( /// Task representing the asynchronous operation. public Task CleanLogsAsync(int maximumAgeOfLogsInMinutes) => throw new NotImplementedException(); + /// + /// Cleans audit logs older than the specified maximum age. + /// + /// The maximum age of logs to keep, in minutes. [Obsolete("Use CleanLogsAsync() instead. Scheduled for removal in Umbraco 19.")] void CleanLogs(int maximumAgeOfLogsInMinutes); } diff --git a/src/Umbraco.Core/Services/IBasicAuthService.cs b/src/Umbraco.Core/Services/IBasicAuthService.cs index c371376f8552..e4cb89113bf9 100644 --- a/src/Umbraco.Core/Services/IBasicAuthService.cs +++ b/src/Umbraco.Core/Services/IBasicAuthService.cs @@ -3,11 +3,34 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for basic authentication operations. +/// public interface IBasicAuthService { + /// + /// Gets a value indicating whether basic authentication is enabled. + /// + /// true if basic authentication is enabled; otherwise, false. bool IsBasicAuthEnabled(); + + /// + /// Checks if the specified IP address is in the allow list. + /// + /// The client IP address to check. + /// true if the IP address is allow-listed; otherwise, false. bool IsIpAllowListed(IPAddress clientIpAddress); + + /// + /// Checks if the request headers contain the correct shared secret. + /// + /// The HTTP request headers. + /// true if the headers contain the correct shared secret; otherwise, false. bool HasCorrectSharedSecret(IDictionary headers) => false; + /// + /// Gets a value indicating whether redirect to login page is enabled for unauthenticated requests. + /// + /// true if redirect to login page is enabled; otherwise, false. bool IsRedirectToLoginPageEnabled() => false; } diff --git a/src/Umbraco.Core/Services/IConflictingRouteService.cs b/src/Umbraco.Core/Services/IConflictingRouteService.cs index fe044362b764..8deb9f45daa5 100644 --- a/src/Umbraco.Core/Services/IConflictingRouteService.cs +++ b/src/Umbraco.Core/Services/IConflictingRouteService.cs @@ -1,6 +1,14 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for detecting conflicting routes in the application. +/// public interface IConflictingRouteService { + /// + /// Checks if there are any conflicting routes registered in the application. + /// + /// When this method returns, contains the name of the conflicting controller if a conflict exists. + /// true if there are conflicting routes; otherwise, false. public bool HasConflictingRoutes(out string controllerName); } diff --git a/src/Umbraco.Core/Services/IContentBlueprintContainerService.cs b/src/Umbraco.Core/Services/IContentBlueprintContainerService.cs index 445a85517735..2b144ac3a846 100644 --- a/src/Umbraco.Core/Services/IContentBlueprintContainerService.cs +++ b/src/Umbraco.Core/Services/IContentBlueprintContainerService.cs @@ -1,7 +1,14 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides container (folder) management services for content blueprints. +/// +/// +/// Content blueprints are templates for creating new content items. This service manages +/// the folder structure used to organize blueprints in the backoffice. +/// public interface IContentBlueprintContainerService : IEntityTypeContainerService { } diff --git a/src/Umbraco.Core/Services/IContentBlueprintEditingService.cs b/src/Umbraco.Core/Services/IContentBlueprintEditingService.cs index f6c2409cb7dd..ae6ca4c34065 100644 --- a/src/Umbraco.Core/Services/IContentBlueprintEditingService.cs +++ b/src/Umbraco.Core/Services/IContentBlueprintEditingService.cs @@ -4,24 +4,82 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides editing services for content blueprints. +/// +/// +/// Content blueprints are templates that can be used to create new content items +/// with pre-populated property values. +/// public interface IContentBlueprintEditingService { + /// + /// Gets a content blueprint by its unique identifier. + /// + /// The unique identifier of the blueprint. + /// The content blueprint, or null if not found. Task GetAsync(Guid key); + /// + /// Gets a scaffolded content item based on a blueprint. + /// + /// The unique identifier of the blueprint to scaffold from. + /// A new content item with values populated from the blueprint, or null if the blueprint is not found. Task GetScaffoldedAsync(Guid key) => Task.FromResult(null); + /// + /// Gets a paged collection of blueprints for a specific content type. + /// + /// The unique identifier of the content type. + /// The number of items to skip. + /// The number of items to take. + /// An attempt containing the paged result of blueprints or an error status. Task?, ContentEditingOperationStatus>> GetPagedByContentTypeAsync( Guid contentTypeKey, int skip, int take); + /// + /// Creates a new content blueprint. + /// + /// The model containing the blueprint data. + /// The unique identifier of the user performing the action. + /// An attempt containing the creation result or an error status. Task> CreateAsync(ContentBlueprintCreateModel createModel, Guid userKey); + /// + /// Creates a new content blueprint from an existing content item. + /// + /// The unique identifier of the content item to create the blueprint from. + /// The name for the new blueprint. + /// The optional unique identifier for the new blueprint. + /// The unique identifier of the user performing the action. + /// An attempt containing the creation result or an error status. Task> CreateFromContentAsync(Guid contentKey, string name, Guid? key, Guid userKey); + /// + /// Updates an existing content blueprint. + /// + /// The unique identifier of the blueprint to update. + /// The model containing the updated blueprint data. + /// The unique identifier of the user performing the action. + /// An attempt containing the update result or an error status. Task> UpdateAsync(Guid key, ContentBlueprintUpdateModel updateModel, Guid userKey); + /// + /// Deletes a content blueprint. + /// + /// The unique identifier of the blueprint to delete. + /// The unique identifier of the user performing the action. + /// An attempt containing the deleted blueprint or an error status. Task> DeleteAsync(Guid key, Guid userKey); + /// + /// Moves a content blueprint to a different container. + /// + /// The unique identifier of the blueprint to move. + /// The unique identifier of the target container, or null to move to the root. + /// The unique identifier of the user performing the action. + /// An attempt containing the operation status. Task> MoveAsync(Guid key, Guid? containerKey, Guid userKey); } diff --git a/src/Umbraco.Core/Services/IContentEditingService.cs b/src/Umbraco.Core/Services/IContentEditingService.cs index 0d1ef9ae42f5..ee01d66113e6 100644 --- a/src/Umbraco.Core/Services/IContentEditingService.cs +++ b/src/Umbraco.Core/Services/IContentEditingService.cs @@ -4,35 +4,111 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides editing services for content items. +/// public interface IContentEditingService { + /// + /// Gets a content item by its unique identifier. + /// + /// The unique identifier of the content item. + /// The content item, or null if not found. Task GetAsync(Guid key); + /// + /// Validates a content creation model without persisting it. + /// + /// The model containing the content data to validate. + /// The unique identifier of the user performing the action. + /// An attempt containing the validation result or an error status. Task> ValidateCreateAsync(ContentCreateModel createModel, Guid userKey); + /// + /// Validates a content update model without persisting it. + /// + /// The unique identifier of the content item to validate. + /// The model containing the content data to validate. + /// The unique identifier of the user performing the action. + /// An attempt containing the validation result or an error status. Task> ValidateUpdateAsync(Guid key, ValidateContentUpdateModel updateModel, Guid userKey); + /// + /// Creates a new content item. + /// + /// The model containing the content data. + /// The unique identifier of the user performing the action. + /// An attempt containing the creation result or an error status. Task> CreateAsync(ContentCreateModel createModel, Guid userKey); + /// + /// Updates an existing content item. + /// + /// The unique identifier of the content item to update. + /// The model containing the updated content data. + /// The unique identifier of the user performing the action. + /// An attempt containing the update result or an error status. Task> UpdateAsync(Guid key, ContentUpdateModel updateModel, Guid userKey); + /// + /// Moves a content item to the recycle bin. + /// + /// The unique identifier of the content item to move. + /// The unique identifier of the user performing the action. + /// An attempt containing the moved content item or an error status. Task> MoveToRecycleBinAsync(Guid key, Guid userKey); /// - /// Deletes a Content Item if it is in the recycle bin. + /// Deletes a content item if it is in the recycle bin. /// + /// The unique identifier of the content item to delete. + /// The unique identifier of the user performing the action. + /// An attempt containing the deleted content item or an error status. Task> DeleteFromRecycleBinAsync(Guid key, Guid userKey); + /// + /// Moves a content item to a new parent. + /// + /// The unique identifier of the content item to move. + /// The unique identifier of the new parent, or null to move to the root. + /// The unique identifier of the user performing the action. + /// An attempt containing the moved content item or an error status. Task> MoveAsync(Guid key, Guid? parentKey, Guid userKey); + /// + /// Copies a content item to a new location. + /// + /// The unique identifier of the content item to copy. + /// The unique identifier of the parent for the copy, or null for the root. + /// Whether to create a relation between the copy and the original. + /// Whether to also copy all descendant content items. + /// The unique identifier of the user performing the action. + /// An attempt containing the copied content item or an error status. Task> CopyAsync(Guid key, Guid? parentKey, bool relateToOriginal, bool includeDescendants, Guid userKey); + /// + /// Sorts content items under a parent. + /// + /// The unique identifier of the parent, or null for root-level sorting. + /// The collection of sorting models defining the new order. + /// The unique identifier of the user performing the action. + /// The operation status indicating success or failure. Task SortAsync(Guid? parentKey, IEnumerable sortingModels, Guid userKey); /// - /// Deletes a Content Item whether it is in the recycle bin or not. + /// Deletes a content item whether it is in the recycle bin or not. /// + /// The unique identifier of the content item to delete. + /// The unique identifier of the user performing the action. + /// An attempt containing the deleted content item or an error status. Task> DeleteAsync(Guid key, Guid userKey); + /// + /// Restores a content item from the recycle bin. + /// + /// The unique identifier of the content item to restore. + /// The unique identifier of the parent to restore to, or null for the original location. + /// The unique identifier of the user performing the action. + /// An attempt containing the restored content item or an error status. Task> RestoreAsync(Guid key, Guid? parentKey, Guid userKey); } diff --git a/src/Umbraco.Core/Services/IContentListViewService.cs b/src/Umbraco.Core/Services/IContentListViewService.cs index 7ab16fbbfe0e..dc75783d3f39 100644 --- a/src/Umbraco.Core/Services/IContentListViewService.cs +++ b/src/Umbraco.Core/Services/IContentListViewService.cs @@ -4,8 +4,24 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for retrieving content items in a list view format. +/// public interface IContentListViewService { + /// + /// Gets content items for display in a list view. + /// + /// The user requesting the list view items. + /// The unique identifier of the parent content item. + /// The optional data type key to filter the list view configuration. + /// The property alias to order by. + /// The culture to use for ordering culture-variant properties. + /// The direction of the ordering (ascending or descending). + /// An optional filter string to apply to the results. + /// The number of items to skip. + /// The number of items to take. + /// An attempt containing the paged list view result or an error status. Task?, ContentCollectionOperationStatus>> GetListViewItemsByKeyAsync( IUser user, Guid key, diff --git a/src/Umbraco.Core/Services/IContentPublishingService.cs b/src/Umbraco.Core/Services/IContentPublishingService.cs index 661e7e54efe0..85ec74007c6e 100644 --- a/src/Umbraco.Core/Services/IContentPublishingService.cs +++ b/src/Umbraco.Core/Services/IContentPublishingService.cs @@ -6,6 +6,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides methods for publishing and unpublishing content. +/// public interface IContentPublishingService { /// @@ -48,7 +51,7 @@ public interface IContentPublishingService /// The key of the root content. /// The cultures to publish or schedule. /// The identifier of the user performing the operation. - /// + /// An containing the result of the publish operation. Task> PublishAsync( Guid key, ICollection culturesToPublishOrSchedule, diff --git a/src/Umbraco.Core/Services/IContentSearchService.cs b/src/Umbraco.Core/Services/IContentSearchService.cs index afebc9d87111..4036b1c437ab 100644 --- a/src/Umbraco.Core/Services/IContentSearchService.cs +++ b/src/Umbraco.Core/Services/IContentSearchService.cs @@ -1,7 +1,11 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides search services for content items. +/// +/// public interface IContentSearchService : IContentSearchService { } diff --git a/src/Umbraco.Core/Services/IContentSearchService{TContent}.cs b/src/Umbraco.Core/Services/IContentSearchService{TContent}.cs index ca8b88d4bc1b..d2fa74c48e84 100644 --- a/src/Umbraco.Core/Services/IContentSearchService{TContent}.cs +++ b/src/Umbraco.Core/Services/IContentSearchService{TContent}.cs @@ -1,10 +1,23 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides search services for content items of a specific type. +/// +/// The type of content to search for. public interface IContentSearchService where TContent : class, IContentBase { + /// + /// Searches for child content items under a specified parent. + /// + /// The search query string to filter results. + /// The unique identifier of the parent content item, or null to search at the root level. + /// The ordering configuration for the results. + /// The number of items to skip for pagination. + /// The number of items to take for pagination. + /// A paged model containing the matching content items. Task> SearchChildrenAsync( string? query, Guid? parentId, diff --git a/src/Umbraco.Core/Services/IContentServiceBase.cs b/src/Umbraco.Core/Services/IContentServiceBase.cs index 1e07da7d8f91..61b8010748fb 100644 --- a/src/Umbraco.Core/Services/IContentServiceBase.cs +++ b/src/Umbraco.Core/Services/IContentServiceBase.cs @@ -2,11 +2,26 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides a generic base interface for content services. +/// +/// The type of content item managed by this service. public interface IContentServiceBase : IContentServiceBase where TItem : class, IContentBase { + /// + /// Gets a content item by its unique identifier. + /// + /// The unique identifier of the content item. + /// The content item, or null if not found. TItem? GetById(Guid key); + /// + /// Saves a collection of content items. + /// + /// The content items to save. + /// The identifier of the user performing the save operation. + /// An attempt containing the operation result. Attempt Save(IEnumerable contents, int userId = Constants.Security.SuperUserId); } diff --git a/src/Umbraco.Core/Services/IContentTypeBaseService.cs b/src/Umbraco.Core/Services/IContentTypeBaseService.cs index cb408940e58f..0d6676d76b10 100644 --- a/src/Umbraco.Core/Services/IContentTypeBaseService.cs +++ b/src/Umbraco.Core/Services/IContentTypeBaseService.cs @@ -44,33 +44,95 @@ public interface IContentTypeBaseService : IContentTypeBaseService, IServ /// TItem? Get(string alias); + /// + /// Gets the total count of content types. + /// + /// The count of content types. int Count(); /// /// Returns true or false depending on whether content nodes have been created based on the provided content type id. /// + /// The identifier of the content type. + /// true if content nodes exist for this content type; otherwise, false. bool HasContentNodes(int id); + /// + /// Gets all content types. + /// + /// A collection of all content types. IEnumerable GetAll(); + + /// + /// Gets multiple content types by their identifiers. + /// + /// The identifiers of the content types to retrieve. + /// A collection of content types. IEnumerable GetMany(params int[] ids); + /// + /// Gets multiple content types by their unique identifiers. + /// + /// The unique identifiers of the content types to retrieve. + /// A collection of content types. IEnumerable GetMany(IEnumerable? ids); + /// + /// Gets all descendant content types of a given content type. + /// + /// The identifier of the parent content type. + /// Whether to include the parent content type itself. + /// A collection of descendant content types. IEnumerable GetDescendants(int id, bool andSelf); // parent-child axis + /// + /// Gets all content types that are composed of a given content type. + /// + /// The identifier of the composition content type. + /// A collection of content types that use the specified composition. IEnumerable GetComposedOf(int id); // composition axis + /// + /// Gets all child content types of a given content type. + /// + /// The identifier of the parent content type. + /// A collection of child content types. IEnumerable GetChildren(int id); + /// + /// Gets all child content types of a given content type. + /// + /// The unique identifier of the parent content type. + /// A collection of child content types. IEnumerable GetChildren(Guid id); + /// + /// Checks if a content type has child content types. + /// + /// The identifier of the content type. + /// true if the content type has children; otherwise, false. bool HasChildren(int id); + /// + /// Checks if a content type has child content types. + /// + /// The unique identifier of the content type. + /// true if the content type has children; otherwise, false. bool HasChildren(Guid id); + /// + /// Saves a content type. + /// + /// The content type to save. + /// The identifier of the user performing the action. [Obsolete("Please use the respective Create or Update instead")] void Save(TItem? item, int userId = Constants.Security.SuperUserId); + /// + /// Saves a content type asynchronously. + /// + /// The content type to save. + /// The unique identifier of the user performing the action. [Obsolete("Please use the respective Create or Update instead")] Task SaveAsync(TItem item, Guid performingUserKey) { @@ -78,33 +140,65 @@ Task SaveAsync(TItem item, Guid performingUserKey) return Task.CompletedTask; } + /// + /// Saves a collection of content types. + /// + /// The content types to save. + /// The identifier of the user performing the action. [Obsolete("Please use the respective Create or Update instead")] void Save(IEnumerable items, int userId = Constants.Security.SuperUserId); + /// + /// Creates a new content type. + /// + /// The content type to create. + /// The unique identifier of the user performing the action. + /// An attempt containing the operation status. Task> CreateAsync(TItem item, Guid performingUserKey) { Save(item); return Task.FromResult(Attempt.Succeed(ContentTypeOperationStatus.Success)); } + /// + /// Updates an existing content type. + /// + /// The content type to update. + /// The unique identifier of the user performing the action. + /// An attempt containing the operation status. Task> UpdateAsync(TItem item, Guid performingUserKey) { Save(item); return Task.FromResult(Attempt.Succeed(ContentTypeOperationStatus.Success)); } + /// + /// Deletes a content type. + /// + /// The content type to delete. + /// The identifier of the user performing the action. void Delete(TItem item, int userId = Constants.Security.SuperUserId); /// - /// Deletes an item + /// Deletes a content type by its unique identifier. /// - /// The item to delete. - /// - /// + /// The unique identifier of the content type to delete. + /// The unique identifier of the user performing the action. + /// The operation status. Task DeleteAsync(Guid key, Guid performingUserKey); + /// + /// Deletes a collection of content types. + /// + /// The content types to delete. + /// The identifier of the user performing the action. void Delete(IEnumerable item, int userId = Constants.Security.SuperUserId); + /// + /// Validates that a content type's composition is valid. + /// + /// The content type composition to validate. + /// An attempt containing an array of error messages if validation fails, or null if valid. Attempt ValidateComposition(TItem? compo); /// @@ -122,38 +216,131 @@ Task> UpdateAsync(TItem item, Guid performin /// bool HasContainerInPath(params int[] ids); + /// + /// Creates a new container (folder) for organizing content types. + /// + /// The identifier of the parent container, or -1 for root level. + /// The unique identifier for the new container. + /// The name of the container. + /// The identifier of the user performing the action. + /// An attempt containing the operation result with the created container. Attempt?> CreateContainer(int parentContainerId, Guid key, string name, int userId = Constants.Security.SuperUserId); + /// + /// Saves a container. + /// + /// The container to save. + /// The identifier of the user performing the action. + /// An attempt containing the operation result. Attempt SaveContainer(EntityContainer container, int userId = Constants.Security.SuperUserId); + /// + /// Gets a container by its identifier. + /// + /// The identifier of the container. + /// The container, or null if not found. EntityContainer? GetContainer(int containerId); + /// + /// Gets a container by its unique identifier. + /// + /// The unique identifier of the container. + /// The container, or null if not found. EntityContainer? GetContainer(Guid containerId); + /// + /// Gets multiple containers by their identifiers. + /// + /// The identifiers of the containers to retrieve. + /// A collection of containers. IEnumerable GetContainers(int[] containerIds); + /// + /// Gets all containers in the path of a content type. + /// + /// The content type. + /// A collection of containers in the content type's path. IEnumerable GetContainers(TItem contentType); + /// + /// Gets containers by name and level. + /// + /// The name of the folder. + /// The level in the hierarchy. + /// A collection of matching containers. IEnumerable GetContainers(string folderName, int level); + /// + /// Deletes a container. + /// + /// The identifier of the container to delete. + /// The identifier of the user performing the action. + /// An attempt containing the operation result. Attempt DeleteContainer(int containerId, int userId = Constants.Security.SuperUserId); + /// + /// Renames a container. + /// + /// The identifier of the container to rename. + /// The new name for the container. + /// The identifier of the user performing the action. + /// An attempt containing the operation result with the renamed container. Attempt?> RenameContainer(int id, string name, int userId = Constants.Security.SuperUserId); + /// + /// Moves a content type to a container. + /// + /// The content type to move. + /// The identifier of the target container. + /// An attempt containing the operation result. [Obsolete("Please use MoveAsync. Will be removed in V16.")] Attempt?> Move(TItem moving, int containerId); + /// + /// Copies a content type to a container. + /// + /// The content type to copy. + /// The identifier of the target container. + /// An attempt containing the operation result with the copied content type. [Obsolete("Please use CopyAsync. Will be removed in V16.")] Attempt?> Copy(TItem copying, int containerId); + /// + /// Copies a content type with a new alias and name. + /// + /// The content type to copy. + /// The alias for the copy. + /// The name for the copy. + /// The identifier of the parent container. + /// The copied content type. [Obsolete("Please use CopyAsync. Will be removed in V15.")] TItem Copy(TItem original, string alias, string name, int parentId = -1); + /// + /// Copies a content type with a new alias and name under a parent. + /// + /// The content type to copy. + /// The alias for the copy. + /// The name for the copy. + /// The parent content type. + /// The copied content type. [Obsolete("Please use CopyAsync. Will be removed in V15.")] TItem Copy(TItem original, string alias, string name, TItem parent); + /// + /// Copies a content type to a container asynchronously. + /// + /// The unique identifier of the content type to copy. + /// The unique identifier of the target container, or null for the root. + /// An attempt containing the copied content type or an error status. Task> CopyAsync(Guid key, Guid? containerKey); + /// + /// Moves a content type to a container asynchronously. + /// + /// The unique identifier of the content type to move. + /// The unique identifier of the target container, or null for the root. + /// An attempt containing the moved content type or an error status. Task> MoveAsync(Guid key, Guid? containerKey); /// diff --git a/src/Umbraco.Core/Services/IContentTypeContainerService.cs b/src/Umbraco.Core/Services/IContentTypeContainerService.cs index 9f92581d4c0f..913d96dcab1e 100644 --- a/src/Umbraco.Core/Services/IContentTypeContainerService.cs +++ b/src/Umbraco.Core/Services/IContentTypeContainerService.cs @@ -1,7 +1,14 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides container (folder) management services for content types (document types). +/// +/// +/// This service manages the folder structure used to organize content types +/// in the backoffice Settings section. +/// public interface IContentTypeContainerService : IEntityTypeContainerService { } diff --git a/src/Umbraco.Core/Services/IContentTypeSearchService.cs b/src/Umbraco.Core/Services/IContentTypeSearchService.cs index 1cb41ad57328..a77f6722ca29 100644 --- a/src/Umbraco.Core/Services/IContentTypeSearchService.cs +++ b/src/Umbraco.Core/Services/IContentTypeSearchService.cs @@ -1,8 +1,23 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides search services for content types (document types). +/// public interface IContentTypeSearchService { + /// + /// Searches for content types matching the specified criteria. + /// + /// The search query string to filter results by name or alias. + /// + /// Filter by element type status. true returns only element types, + /// false returns only non-element types, null returns all types. + /// + /// A token to observe for cancellation requests. + /// The number of items to skip for pagination. + /// The number of items to take for pagination. + /// A paged model containing the matching content types. Task> SearchAsync(string query, bool? isElement, CancellationToken cancellationToken, int skip = 0, int take = 100); } diff --git a/src/Umbraco.Core/Services/IContentTypeService.cs b/src/Umbraco.Core/Services/IContentTypeService.cs index 66337666c579..cfb2eed8e230 100644 --- a/src/Umbraco.Core/Services/IContentTypeService.cs +++ b/src/Umbraco.Core/Services/IContentTypeService.cs @@ -12,7 +12,7 @@ public interface IContentTypeService : IContentTypeBaseService /// /// Gets all property type aliases. /// - /// + /// An enumerable collection of all property type aliases. IEnumerable GetAllPropertyTypeAliases(); /// @@ -22,16 +22,22 @@ public interface IContentTypeService : IContentTypeBaseService /// If this list is empty, it will return all content type aliases for media, members and content, otherwise /// it will only return content type aliases for the object types specified /// - /// + /// An enumerable collection of content type aliases. IEnumerable GetAllContentTypeAliases(params Guid[] objectTypes); /// - /// Returns all content type Ids for the aliases given + /// Returns all content type Ids for the aliases given. /// - /// - /// + /// The content type aliases to look up. + /// An enumerable collection of content type identifiers. IEnumerable GetAllContentTypeIds(string[] aliases); + /// + /// Gets content types matching the specified query. + /// + /// The query to filter content types. + /// A cancellation token to cancel the operation. + /// A task that represents the asynchronous operation. The task result contains the matching content types. Task> GetByQueryAsync(IQuery query, CancellationToken cancellationToken) => Task.FromResult(Enumerable.Empty()); /// diff --git a/src/Umbraco.Core/Services/IContentValidationService.cs b/src/Umbraco.Core/Services/IContentValidationService.cs index e06322fcd7c9..189f504a1e43 100644 --- a/src/Umbraco.Core/Services/IContentValidationService.cs +++ b/src/Umbraco.Core/Services/IContentValidationService.cs @@ -1,7 +1,10 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides validation services for content items. +/// internal interface IContentValidationService : IContentValidationServiceBase { } diff --git a/src/Umbraco.Core/Services/IContentValidationServiceBase.cs b/src/Umbraco.Core/Services/IContentValidationServiceBase.cs index 7c91bdd0ec8a..d977d067ee0e 100644 --- a/src/Umbraco.Core/Services/IContentValidationServiceBase.cs +++ b/src/Umbraco.Core/Services/IContentValidationServiceBase.cs @@ -1,12 +1,28 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentEditing; namespace Umbraco.Cms.Core.Services; +/// +/// Provides a base interface for content validation services. +/// +/// The type of content type used for validation. internal interface IContentValidationServiceBase where TContentType : IContentTypeComposition { + /// + /// Validates the properties of a content editing model against its content type definition. + /// + /// The content editing model to validate. + /// The content type definition to validate against. + /// The optional collection of cultures to validate. If null, all cultures are validated. + /// A validation result containing any validation errors. Task ValidatePropertiesAsync(ContentEditingModelBase contentEditingModelBase, TContentType contentType, IEnumerable? culturesToValidate = null); + /// + /// Validates that the cultures specified in the content editing model are valid. + /// + /// The content editing model to validate. + /// true if the cultures are valid; otherwise, false. Task ValidateCulturesAsync(ContentEditingModelBase contentEditingModelBase); } diff --git a/src/Umbraco.Core/Services/IContentVersionService.cs b/src/Umbraco.Core/Services/IContentVersionService.cs index 874e561b3f79..5a0f7ea34d5c 100644 --- a/src/Umbraco.Core/Services/IContentVersionService.cs +++ b/src/Umbraco.Core/Services/IContentVersionService.cs @@ -3,17 +3,57 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing content versions. +/// public interface IContentVersionService { /// /// Removes historic content versions according to a policy. /// + /// The date to use when applying cleanup policies. + /// A collection of version metadata for the versions that were cleaned up. IReadOnlyCollection PerformContentVersionCleanup(DateTime asAtDate); + /// + /// Gets the metadata for a specific content version. + /// + /// The identifier of the version. + /// The version metadata, or null if not found. ContentVersionMeta? Get(int versionId); + + /// + /// Gets a paged collection of content versions for a content item. + /// + /// The unique identifier of the content item. + /// The optional culture to filter versions by. + /// The number of versions to skip for pagination. + /// The number of versions to take for pagination. + /// An attempt containing the paged result or an error status. Task?, ContentVersionOperationStatus>> GetPagedContentVersionsAsync(Guid contentId, string? culture, int skip, int take); + + /// + /// Gets a specific content version by its unique identifier. + /// + /// The unique identifier of the version. + /// An attempt containing the content version or an error status. Task> GetAsync(Guid versionId); + /// + /// Sets whether a content version should be prevented from automatic cleanup. + /// + /// The unique identifier of the version. + /// true to prevent cleanup; false to allow cleanup. + /// The unique identifier of the user performing the action. + /// An attempt containing the operation status. Task> SetPreventCleanupAsync(Guid versionId, bool preventCleanup, Guid userKey); + + /// + /// Rolls back content to a specific version. + /// + /// The unique identifier of the version to roll back to. + /// The optional culture to roll back. If null, all cultures are rolled back. + /// The unique identifier of the user performing the rollback. + /// An attempt containing the operation status. Task> RollBackAsync(Guid versionId, string? culture, Guid userKey); } diff --git a/src/Umbraco.Core/Services/ICultureImpactFactory.cs b/src/Umbraco.Core/Services/ICultureImpactFactory.cs index 986b2f1aed2e..0c86ef3f3ff1 100644 --- a/src/Umbraco.Core/Services/ICultureImpactFactory.cs +++ b/src/Umbraco.Core/Services/ICultureImpactFactory.cs @@ -1,7 +1,11 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides methods for creating instances that represent +/// the impact of culture variations on content operations. +/// public interface ICultureImpactFactory { /// diff --git a/src/Umbraco.Core/Services/ICultureService.cs b/src/Umbraco.Core/Services/ICultureService.cs index 11f9cb4b8e5e..95fd7a2765f4 100644 --- a/src/Umbraco.Core/Services/ICultureService.cs +++ b/src/Umbraco.Core/Services/ICultureService.cs @@ -2,7 +2,14 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for retrieving culture information. +/// public interface ICultureService { + /// + /// Gets all valid culture information objects that can be used in the application. + /// + /// An array of valid objects. CultureInfo[] GetValidCultureInfos(); } diff --git a/src/Umbraco.Core/Services/IDataTypeContainerService.cs b/src/Umbraco.Core/Services/IDataTypeContainerService.cs index b26b44bcc8d4..aae1a6bd5b42 100644 --- a/src/Umbraco.Core/Services/IDataTypeContainerService.cs +++ b/src/Umbraco.Core/Services/IDataTypeContainerService.cs @@ -1,7 +1,14 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides container (folder) management services for data types. +/// +/// +/// This service manages the folder structure used to organize data types +/// in the backoffice Settings section. +/// public interface IDataTypeContainerService : IEntityTypeContainerService { } diff --git a/src/Umbraco.Core/Services/IDataTypeService.cs b/src/Umbraco.Core/Services/IDataTypeService.cs index 9f9b32a54141..fb782c5d3143 100644 --- a/src/Umbraco.Core/Services/IDataTypeService.cs +++ b/src/Umbraco.Core/Services/IDataTypeService.cs @@ -25,6 +25,14 @@ public interface IDataTypeService : IService Task> GetPagedRelationsAsync(Guid key, int skip, int take) => Task.FromResult(new PagedModel()); + /// + /// Creates a container for organizing data types. + /// + /// The parent container ID, or -1 for root. + /// The unique key for the new container. + /// The name of the container. + /// The ID of the user performing the action. + /// An operation result containing the created container. [Obsolete("Please use IDataTypeContainerService for all data type container operations. Will be removed in V15.")] Attempt?> CreateContainer( int parentId, @@ -32,27 +40,72 @@ Task> GetPagedRelationsAsync(Guid key, int skip, i string name, int userId = Constants.Security.SuperUserId); + /// + /// Saves a container. + /// + /// The container to save. + /// The ID of the user performing the action. + /// An operation result indicating success or failure. [Obsolete("Please use IDataTypeContainerService for all data type container operations. Will be removed in V15.")] Attempt SaveContainer(EntityContainer container, int userId = Constants.Security.SuperUserId); + /// + /// Gets a container by its ID. + /// + /// The container ID. + /// The container, or null if not found. [Obsolete("Please use IDataTypeContainerService for all data type container operations. Will be removed in V15.")] EntityContainer? GetContainer(int containerId); + /// + /// Gets a container by its unique key. + /// + /// The container unique key. + /// The container, or null if not found. [Obsolete("Please use IDataTypeContainerService for all data type container operations. Will be removed in V15.")] EntityContainer? GetContainer(Guid containerId); + /// + /// Gets containers by name and level. + /// + /// The container name. + /// The container level. + /// A collection of matching containers. [Obsolete("Please use IDataTypeContainerService for all data type container operations. Will be removed in V15.")] IEnumerable GetContainers(string folderName, int level); + /// + /// Gets all ancestor containers for a data type. + /// + /// The data type. + /// A collection of ancestor containers. [Obsolete("Please use IDataTypeContainerService for all data type container operations. Will be removed in V15.")] IEnumerable GetContainers(IDataType dataType); + /// + /// Gets containers by their IDs. + /// + /// The container IDs. + /// A collection of containers. [Obsolete("Please use IDataTypeContainerService for all data type container operations. Will be removed in V15.")] IEnumerable GetContainers(int[] containerIds); + /// + /// Deletes a container. + /// + /// The ID of the container to delete. + /// The ID of the user performing the action. + /// An operation result indicating success or failure. [Obsolete("Please use IDataTypeContainerService for all data type container operations. Will be removed in V15.")] Attempt DeleteContainer(int containerId, int userId = Constants.Security.SuperUserId); + /// + /// Renames a container. + /// + /// The ID of the container to rename. + /// The new name for the container. + /// The ID of the user performing the action. + /// An operation result containing the renamed container. [Obsolete("Please use IDataTypeContainerService for all data type container operations. Will be removed in V15.")] Attempt?> RenameContainer( int id, @@ -185,19 +238,25 @@ Task> GetPagedRelationsAsync(Guid key, int skip, i IEnumerable GetByEditorAlias(string propertyEditorAlias); /// - /// Gets all for a given property editor + /// Gets all for a given property editor. /// - /// Alias of the property editor - /// Collection of configured for the property editor + /// Alias of the property editor. + /// Collection of configured for the property editor. Task> GetByEditorAliasAsync(string propertyEditorAlias) => Task.FromResult(GetByEditorAlias(propertyEditorAlias)); /// - /// Gets all for a given editor UI alias + /// Gets all for a given editor UI alias. /// /// The UI Alias to query by. /// Collection of which has the UI alias. Task> GetByEditorUiAlias(string editorUiAlias); + /// + /// Moves a to a given container. + /// + /// The data type that will be moved. + /// The ID of the parent container to move to. + /// An operation result indicating the move status. [Obsolete("Please use MoveAsync instead. Will be removed in V15")] Attempt?> Move(IDataType toMove, int parentId); @@ -207,13 +266,26 @@ Task> GetPagedRelationsAsync(Guid key, int skip, i /// The data type that will be moved /// The container key where the data type will be moved to. /// The user that did the Move action - /// + /// An attempt result with the moved data type and operation status. Task> MoveAsync(IDataType toMove, Guid? containerKey, Guid userKey); + /// + /// Copies a to a given container. + /// + /// The data type to copy. + /// The ID of the target container. + /// An operation result containing the copied data type. [Obsolete("Please use CopyASync instead. Will be removed in V15")] Attempt?> Copy(IDataType copying, int containerId) => Copy(copying, containerId, Constants.Security.SuperUserId); + /// + /// Copies a to a given container. + /// + /// The data type to copy. + /// The ID of the target container. + /// The ID of the user performing the action. + /// An operation result containing the copied data type. [Obsolete("Please use CopyASync instead. Will be removed in V15")] Attempt?> Copy( IDataType copying, @@ -226,7 +298,7 @@ Task> GetPagedRelationsAsync(Guid key, int skip, i /// The data type that will be copied /// The container key where the data type will be copied to. /// The user that did the Copy action - /// + /// An attempt result with the copied data type and operation status. Task> CopyAsync(IDataType toCopy, Guid? containerKey, Guid userKey); /// @@ -237,9 +309,9 @@ Task> GetPagedRelationsAsync(Guid key, int skip, i IEnumerable ValidateConfigurationData(IDataType dataType); /// - /// Gets all for a set of property editors + /// Gets all for a set of property editors. /// - /// Aliases of the property editors - /// Collection of configured for the property editors + /// Aliases of the property editors. + /// Collection of configured for the property editors. Task> GetByEditorAliasAsync(string[] propertyEditorAlias) => Task.FromResult(propertyEditorAlias.SelectMany(x=>GetByEditorAlias(x))); } diff --git a/src/Umbraco.Core/Services/IDataTypeUsageService.cs b/src/Umbraco.Core/Services/IDataTypeUsageService.cs index 405b8f49b1a1..0d0aa1692d61 100644 --- a/src/Umbraco.Core/Services/IDataTypeUsageService.cs +++ b/src/Umbraco.Core/Services/IDataTypeUsageService.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides methods for querying data type usage across the application. +/// public interface IDataTypeUsageService { /// diff --git a/src/Umbraco.Core/Services/IDictionaryItemService.cs b/src/Umbraco.Core/Services/IDictionaryItemService.cs index 89d06ade1d3c..9879826f7a8f 100644 --- a/src/Umbraco.Core/Services/IDictionaryItemService.cs +++ b/src/Umbraco.Core/Services/IDictionaryItemService.cs @@ -1,9 +1,12 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence.Querying; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services; +/// +/// Provides methods for managing objects for localization. +/// public interface IDictionaryItemService { /// @@ -101,7 +104,17 @@ public interface IDictionaryItemService /// Key of the user moving the dictionary item Task> MoveAsync(IDictionaryItem dictionaryItem, Guid? parentId, Guid userKey); + /// + /// Counts the number of children for a . + /// + /// The identifier of the parent dictionary item. + /// A task that represents the asynchronous operation. The task result contains the count of children. Task CountChildrenAsync(Guid parentId); + + /// + /// Counts the number of root objects. + /// + /// A task that represents the asynchronous operation. The task result contains the count of root items. Task CountRootAsync(); /// diff --git a/src/Umbraco.Core/Services/IDictionaryPermissionService.cs b/src/Umbraco.Core/Services/IDictionaryPermissionService.cs index 925c83a7b5a1..d84089283d53 100644 --- a/src/Umbraco.Core/Services/IDictionaryPermissionService.cs +++ b/src/Umbraco.Core/Services/IDictionaryPermissionService.cs @@ -3,8 +3,16 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Manages permissions for dictionary item access. +/// public interface IDictionaryPermissionService { - /// + /// + /// Authorizes that a user has access to specific cultures for dictionary operations. + /// + /// The user to authorize. + /// The collection of culture codes to check access for. + /// A task resolving into a indicating the authorization result. Task AuthorizeCultureAccessAsync(IUser user, ISet culturesToCheck); } diff --git a/src/Umbraco.Core/Services/IDictionaryService.cs b/src/Umbraco.Core/Services/IDictionaryService.cs index 3a26e99a1764..66fefaac4b35 100644 --- a/src/Umbraco.Core/Services/IDictionaryService.cs +++ b/src/Umbraco.Core/Services/IDictionaryService.cs @@ -1,6 +1,15 @@ -namespace Umbraco.Cms.Core.Services; +namespace Umbraco.Cms.Core.Services; +/// +/// Provides utility services for dictionary items. +/// public interface IDictionaryService { + /// + /// Calculates the hierarchical path for a dictionary item. + /// + /// The unique identifier of the parent dictionary item, or null for root items. + /// The source identifier of the dictionary item. + /// The calculated path string. string CalculatePath(Guid? parentId, int sourceId); } diff --git a/src/Umbraco.Core/Services/IDomainService.cs b/src/Umbraco.Core/Services/IDomainService.cs index 2d03a8a966db..af48b8b2a9dd 100644 --- a/src/Umbraco.Core/Services/IDomainService.cs +++ b/src/Umbraco.Core/Services/IDomainService.cs @@ -5,47 +5,98 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing domains (hostnames) assigned to content items. +/// +/// +/// Domains are used to configure multi-site setups where different hostnames +/// route to different content nodes in the content tree. +/// public interface IDomainService : IService { + /// + /// Checks if a domain with the specified name exists. + /// + /// The domain name to check. + /// true if the domain exists; otherwise, false. bool Exists(string domainName); + /// + /// Deletes a domain. + /// + /// The domain to delete. + /// An attempt containing the operation result. [Obsolete($"Please use {nameof(UpdateDomainsAsync)}. Will be removed in V15")] Attempt Delete(IDomain domain); + /// + /// Gets a domain by its name. + /// + /// The domain name. + /// The domain, or null if not found. IDomain? GetByName(string name); + /// + /// Gets a domain by its identifier. + /// + /// The domain identifier. + /// The domain, or null if not found. IDomain? GetById(int id); + /// + /// Gets all domains. + /// + /// Whether to include wildcard domains. + /// A collection of domains. [Obsolete($"Please use {nameof(GetAllAsync)}. Will be removed in V15")] IEnumerable GetAll(bool includeWildcards); + /// + /// Gets all domains assigned to a content item. + /// + /// The content item identifier. + /// Whether to include wildcard domains. + /// A collection of domains assigned to the content item. [Obsolete($"Please use {nameof(GetAssignedDomainsAsync)}. Will be removed in V15")] IEnumerable GetAssignedDomains(int contentId, bool includeWildcards); + /// + /// Saves a domain. + /// + /// The domain to save. + /// An attempt containing the operation result. [Obsolete($"Please use {nameof(UpdateDomainsAsync)}. Will be removed in V15")] Attempt Save(IDomain domainEntity); + /// + /// Sorts a collection of domains. + /// + /// The domains to sort. + /// An attempt containing the operation result. [Obsolete($"Please use {nameof(UpdateDomainsAsync)}. Will be removed in V15")] Attempt Sort(IEnumerable items) => Attempt.Fail(new OperationResult(OperationResultType.Failed, new EventMessages())); // TODO Remove default implmentation in a future version /// - /// Gets all assigned domains for content item. + /// Gets all assigned domains for a content item. /// - /// The key of the content item. - /// Whether or not to include wildcard domains. + /// The unique identifier of the content item. + /// Whether to include wildcard domains. + /// A collection of domains assigned to the content item. Task> GetAssignedDomainsAsync(Guid contentKey, bool includeWildcards); /// - /// Gets all assigned domains. + /// Gets all assigned domains. /// - /// Whether or not to include wildcard domains. + /// Whether to include wildcard domains. + /// A collection of all domains. Task> GetAllAsync(bool includeWildcards); /// - /// Updates the domain assignments for a content item. + /// Updates the domain assignments for a content item. /// - /// The key of the content item. + /// The unique identifier of the content item. /// The domain assignments to apply. + /// An attempt containing the update result or an error status. Task> UpdateDomainsAsync(Guid contentKey, DomainsUpdateModel updateModel); } diff --git a/src/Umbraco.Core/Services/IEntitySearchService.cs b/src/Umbraco.Core/Services/IEntitySearchService.cs index 1bb7db569ab9..79ce6e4e41b5 100644 --- a/src/Umbraco.Core/Services/IEntitySearchService.cs +++ b/src/Umbraco.Core/Services/IEntitySearchService.cs @@ -1,4 +1,4 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; namespace Umbraco.Cms.Core.Services; @@ -8,5 +8,13 @@ namespace Umbraco.Cms.Core.Services; /// public interface IEntitySearchService { + /// + /// Searches for entities of a given object type using a query string. + /// + /// The type of entities to search for. + /// The search query string. + /// The number of results to skip for pagination. + /// The maximum number of results to return. + /// A paged model containing the matching entities. PagedModel Search(UmbracoObjectTypes objectType, string query, int skip = 0, int take = 100); } diff --git a/src/Umbraco.Core/Services/IEntityService.cs b/src/Umbraco.Core/Services/IEntityService.cs index cab5615103f1..f921884a78ba 100644 --- a/src/Umbraco.Core/Services/IEntityService.cs +++ b/src/Umbraco.Core/Services/IEntityService.cs @@ -4,6 +4,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides methods for working with entities across Umbraco, including content, media, members, and other entity types. +/// public interface IEntityService { /// @@ -237,6 +240,12 @@ IEnumerable GetTrashedSiblings( /// The object type of the children. IEnumerable GetChildren(int id, UmbracoObjectTypes objectType); + /// + /// Gets the children of an entity. + /// + /// The unique key of the parent entity, or null for root level entities. + /// The object type of the children. + /// An enumerable collection of child entities. IEnumerable GetChildren(Guid? key, UmbracoObjectTypes objectType) { return Array.Empty(); @@ -255,6 +264,17 @@ IEnumerable GetChildren(Guid? key, UmbracoObjectTypes objectType) /// The object type of the descendants. IEnumerable GetDescendants(int id, UmbracoObjectTypes objectType); + /// + /// Gets children of an entity with paging support. + /// + /// The unique key of the parent entity, or null for root level entities. + /// The object type of the children. + /// The number of items to skip. + /// The number of items to take. + /// Outputs the total number of records. + /// An optional filter to apply to the result set. + /// The ordering to apply to the children. + /// An enumerable collection of child entities. IEnumerable GetPagedChildren( Guid? parentKey, UmbracoObjectTypes childObjectType, @@ -273,6 +293,18 @@ IEnumerable GetPagedChildren( filter, ordering); + /// + /// Gets children of an entity with paging support, filtering by parent object types. + /// + /// The unique key of the parent entity, or null for root level entities. + /// The object types of the parent entities. + /// The object type of the children. + /// The number of items to skip. + /// The number of items to take. + /// Outputs the total number of records. + /// An optional filter to apply to the result set. + /// The ordering to apply to the children. + /// An enumerable collection of child entities. IEnumerable GetPagedChildren( Guid? parentKey, IEnumerable parentObjectTypes, @@ -287,6 +319,19 @@ IEnumerable GetPagedChildren( return Array.Empty(); } + /// + /// Gets children of an entity with paging support, filtering by parent and child object types and trashed state. + /// + /// The unique key of the parent entity, or null for root level entities. + /// The object types of the parent entities. + /// The object types of the children. + /// The number of items to skip. + /// The number of items to take. + /// A value indicating whether to include trashed entities. + /// Outputs the total number of records. + /// An optional filter to apply to the result set. + /// The ordering to apply to the children. + /// An enumerable collection of child entities. IEnumerable GetPagedChildren( Guid? parentKey, IEnumerable parentObjectTypes, diff --git a/src/Umbraco.Core/Services/IEntityTypeContainerService.cs b/src/Umbraco.Core/Services/IEntityTypeContainerService.cs index 831eb4b2e452..635d2d929ea4 100644 --- a/src/Umbraco.Core/Services/IEntityTypeContainerService.cs +++ b/src/Umbraco.Core/Services/IEntityTypeContainerService.cs @@ -1,72 +1,76 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services; +/// +/// Provides methods for managing objects for entity types. +/// +/// The type of tree entity this container service manages. public interface IEntityTypeContainerService where TTreeEntity : ITreeEntity { /// - /// Gets a container + /// Gets a container. /// /// The ID of the container to get. - /// + /// A task that represents the asynchronous operation. The task result contains the container, or null if not found. Task GetAsync(Guid id); /// - /// Gets containers by name and level + /// Gets containers by name and level. /// /// The name of the containers to get. /// The level in the tree of the containers to get. - /// + /// A task that represents the asynchronous operation. The task result contains the matching containers. Task> GetAsync(string name, int level); /// - /// Gets all containers + /// Gets all containers. /// - /// + /// A task that represents the asynchronous operation. The task result contains all containers. Task> GetAllAsync(); /// - /// Gets the parent container of a container + /// Gets the parent container of a container. /// /// The container whose parent container to get. - /// + /// A task that represents the asynchronous operation. The task result contains the parent container, or null if the container is at the root. Task GetParentAsync(EntityContainer container); /// - /// Gets the parent container of an entity + /// Gets the parent container of an entity. /// /// The entity whose parent container to get. - /// + /// A task that represents the asynchronous operation. The task result contains the parent container, or null if the entity is at the root. Task GetParentAsync(TTreeEntity entity); /// - /// Creates a new container + /// Creates a new container. /// /// The key to assign to the newly created container (if null is specified, a random key will be assigned). /// The name of the created container. /// The ID of the parent container to create the new container under. /// Key of the user issuing the creation. - /// + /// An containing the created container if successful, or an error status if not. /// If parent key is supplied as null, the container will be created at the tree root. Task> CreateAsync(Guid? key, string name, Guid? parentKey, Guid userKey); /// - /// Updates an existing container + /// Updates an existing container. /// /// The key of the container to update. /// The name to assign to the container. /// Key of the user issuing the update. - /// + /// An containing the updated container if successful, or an error status if not. Task> UpdateAsync(Guid key, string name, Guid userKey); /// - /// Deletes a container + /// Deletes a container. /// /// The ID of the container to delete. /// Key of the user issuing the deletion. - /// + /// An containing the deleted container if successful, or an error status if not. Task> DeleteAsync(Guid id, Guid userKey); } diff --git a/src/Umbraco.Core/Services/IEntityXmlSerializer.cs b/src/Umbraco.Core/Services/IEntityXmlSerializer.cs index bb976daffaca..c0c14f0c7a88 100644 --- a/src/Umbraco.Core/Services/IEntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/IEntityXmlSerializer.cs @@ -8,30 +8,51 @@ namespace Umbraco.Cms.Core.Services; /// public interface IEntityXmlSerializer { + /// + /// The XML element name used for document type serialization. + /// internal const string DocumentTypeElementName = "DocumentType"; + + /// + /// The XML element name used for media type serialization. + /// internal const string MediaTypeElementName = "MediaType"; + + /// + /// The XML element name used for member type serialization. + /// internal const string MemberTypeElementName = "MemberType"; /// - /// Exports an IContent item as an XElement. + /// Exports an item as an . /// + /// The content item to serialize. + /// If true, serializes the published version; otherwise serializes the draft version. + /// If true, includes all descendant content items in the serialization. + /// An containing the XML representation of the content item. + // TODO: take care of usage! only used for the packager XElement Serialize( IContent content, bool published, - bool withDescendants = false) // TODO: take care of usage! only used for the packager - ; + bool withDescendants = false); /// - /// Exports an IMedia item as an XElement. + /// Exports an item as an . /// + /// The media item to serialize. + /// If true, includes all descendant media items in the serialization. + /// Optional callback action invoked after each media item is serialized. + /// An containing the XML representation of the media item. XElement Serialize( IMedia media, bool withDescendants = false, Action? onMediaItemSerialized = null); /// - /// Exports an IMember item as an XElement. + /// Exports an item as an . /// + /// The member to serialize. + /// An containing the XML representation of the member. XElement Serialize(IMember member); /// @@ -41,6 +62,11 @@ XElement Serialize( /// containing the xml representation of the IDataTypeDefinition objects XElement Serialize(IEnumerable dataTypeDefinitions); + /// + /// Exports a single to an . + /// + /// The data type to serialize. + /// An containing the XML representation of the data type. XElement Serialize(IDataType dataType); /// @@ -59,6 +85,12 @@ XElement Serialize( /// containing the xml representation of the IDictionaryItem object XElement Serialize(IDictionaryItem dictionaryItem, bool includeChildren); + /// + /// Exports an to an . + /// + /// The stylesheet to serialize. + /// If true, includes the stylesheet's properties in the serialization. + /// An containing the XML representation of the stylesheet. XElement Serialize(IStylesheet stylesheet, bool includeProperties); /// @@ -68,20 +100,45 @@ XElement Serialize( /// containing the xml representation of the ILanguage objects XElement Serialize(IEnumerable languages); + /// + /// Exports a single to an . + /// + /// The language to serialize. + /// An containing the XML representation of the language. XElement Serialize(ILanguage language); + /// + /// Exports a single to an . + /// + /// The template to serialize. + /// An containing the XML representation of the template. XElement Serialize(ITemplate template); /// - /// Exports a list of items to xml as an + /// Exports a list of items to XML as an . /// - /// - /// + /// The collection of templates to serialize. + /// An containing the XML representation of all templates. XElement Serialize(IEnumerable templates); + /// + /// Exports an to an . + /// + /// The media type to serialize. + /// An containing the XML representation of the media type. XElement Serialize(IMediaType mediaType); + /// + /// Exports an to an . + /// + /// The member type to serialize. + /// An containing the XML representation of the member type. XElement Serialize(IMemberType memberType) => throw new NotImplementedException(); + /// + /// Exports an to an . + /// + /// The content type to serialize. + /// An containing the XML representation of the content type. XElement Serialize(IContentType contentType); } diff --git a/src/Umbraco.Core/Services/IExamineIndexCountService.cs b/src/Umbraco.Core/Services/IExamineIndexCountService.cs index 8d85e17e04c5..e989b051596d 100644 --- a/src/Umbraco.Core/Services/IExamineIndexCountService.cs +++ b/src/Umbraco.Core/Services/IExamineIndexCountService.cs @@ -1,6 +1,13 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality to retrieve counts from Examine search indexes. +/// public interface IExamineIndexCountService { + /// + /// Gets the total number of documents across all Examine indexes. + /// + /// The total count of indexed documents. public int GetCount(); } diff --git a/src/Umbraco.Core/Services/IExternalLoginWithKeyService.cs b/src/Umbraco.Core/Services/IExternalLoginWithKeyService.cs index deaa135f16b2..faf976cf1934 100644 --- a/src/Umbraco.Core/Services/IExternalLoginWithKeyService.cs +++ b/src/Umbraco.Core/Services/IExternalLoginWithKeyService.cs @@ -2,6 +2,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides methods for managing external login providers and tokens for users and members. +/// public interface IExternalLoginWithKeyService : IService { /// diff --git a/src/Umbraco.Core/Services/IFileService.cs b/src/Umbraco.Core/Services/IFileService.cs index 23a05f8194aa..60bed6d8039f 100644 --- a/src/Umbraco.Core/Services/IFileService.cs +++ b/src/Umbraco.Core/Services/IFileService.cs @@ -8,9 +8,17 @@ namespace Umbraco.Cms.Core.Services; /// public interface IFileService : IService { + /// + /// Creates a folder for partial views. + /// + /// The path of the folder to create. [Obsolete("Please use IPartialViewFolderService for partial view folder operations - will be removed in Umbraco 15")] void CreatePartialViewFolder(string folderPath); + /// + /// Deletes a folder for partial views. + /// + /// The path of the folder to delete. [Obsolete("Please use IPartialViewFolderService for partial view folder operations - will be removed in Umbraco 15")] void DeletePartialViewFolder(string folderPath); @@ -21,15 +29,39 @@ public interface IFileService : IService [Obsolete("Please use IPartialViewService for partial view operations - will be removed in Umbraco 15")] IEnumerable GetPartialViews(params string[] names); + /// + /// Gets a object by its path. + /// + /// The path of the partial view. + /// The object matching the path, or null. [Obsolete("Please use IPartialViewService for partial view operations - will be removed in Umbraco 15")] IPartialView? GetPartialView(string path); + /// + /// Creates a new . + /// + /// The to create. + /// Optional name of a snippet to use as template content. + /// Optional id of the user creating the partial view. + /// An indicating success or failure with the created partial view. [Obsolete("Please use IPartialViewService for partial view operations - will be removed in Umbraco 15")] Attempt CreatePartialView(IPartialView partialView, string? snippetName = null, int? userId = Constants.Security.SuperUserId); + /// + /// Deletes a partial view by its path. + /// + /// The path of the partial view to delete. + /// Optional id of the user deleting the partial view. + /// True if the partial view was deleted; otherwise, false. [Obsolete("Please use IPartialViewService for partial view operations - will be removed in Umbraco 15")] bool DeletePartialView(string path, int? userId = null); + /// + /// Saves a . + /// + /// The to save. + /// Optional id of the user saving the partial view. + /// An indicating success or failure with the saved partial view. [Obsolete("Please use IPartialViewService for partial view operations - will be removed in Umbraco 15")] Attempt SavePartialView(IPartialView partialView, int? userId = null); @@ -266,6 +298,15 @@ public interface IFileService : IService string? contentTypeName, int userId = Constants.Security.SuperUserId); + /// + /// Creates a new template with identity, setting the content if a view exists in the filesystem. + /// + /// The name of the template. + /// The alias of the template. + /// The content/markup of the template. + /// Optional master template. + /// Optional id of the user creating the template. + /// The created . [Obsolete("Please use ITemplateService for template operations - will be removed in Umbraco 15")] ITemplate CreateTemplateWithIdentity(string? name, string? alias, string? content, ITemplate? masterTemplate = null, int userId = Constants.Security.SuperUserId); diff --git a/src/Umbraco.Core/Services/IIdKeyMap.cs b/src/Umbraco.Core/Services/IIdKeyMap.cs index e85095d41fc7..c9784b9331a2 100644 --- a/src/Umbraco.Core/Services/IIdKeyMap.cs +++ b/src/Umbraco.Core/Services/IIdKeyMap.cs @@ -2,19 +2,59 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides a mapping between integer IDs, GUIDs (keys), and UDIs for Umbraco entities. +/// +/// +/// This service maintains a cache of ID/key mappings for efficient lookups. +/// public interface IIdKeyMap { + /// + /// Gets the integer ID for a given GUID key and object type. + /// + /// The unique GUID key of the entity. + /// The type of the Umbraco object. + /// An attempt containing the integer ID if found. Attempt GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType); + /// + /// Gets the integer ID for a given UDI. + /// + /// The Umbraco Document Identifier. + /// An attempt containing the integer ID if found. Attempt GetIdForUdi(Udi udi); + /// + /// Gets the UDI for a given integer ID and object type. + /// + /// The integer identifier of the entity. + /// The type of the Umbraco object. + /// An attempt containing the UDI if found. Attempt GetUdiForId(int id, UmbracoObjectTypes umbracoObjectType); + /// + /// Gets the GUID key for a given integer ID and object type. + /// + /// The integer identifier of the entity. + /// The type of the Umbraco object. + /// An attempt containing the GUID key if found. Attempt GetKeyForId(int id, UmbracoObjectTypes umbracoObjectType); + /// + /// Clears the entire ID/key mapping cache. + /// void ClearCache(); + /// + /// Clears the cache entry for a specific integer ID. + /// + /// The integer identifier to remove from the cache. void ClearCache(int id); + /// + /// Clears the cache entry for a specific GUID key. + /// + /// The GUID key to remove from the cache. void ClearCache(Guid key); } diff --git a/src/Umbraco.Core/Services/IIndexedEntitySearchService.cs b/src/Umbraco.Core/Services/IIndexedEntitySearchService.cs index 147525dcae9e..d79d164efbda 100644 --- a/src/Umbraco.Core/Services/IIndexedEntitySearchService.cs +++ b/src/Umbraco.Core/Services/IIndexedEntitySearchService.cs @@ -1,4 +1,4 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Entities; namespace Umbraco.Cms.Core.Services; @@ -12,6 +12,19 @@ namespace Umbraco.Cms.Core.Services; /// public interface IIndexedEntitySearchService { + /// + /// Searches for entities using the search index with support for filtering and pagination. + /// + /// The type of entities to search for. + /// The search query string. + /// Optional parent ID to restrict the search to descendants of a specific node. + /// Optional collection of content type IDs to filter results by. + /// Optional filter for trashed state. If null, all items are included. + /// Optional culture code to filter results by language variant. + /// The number of results to skip for pagination. + /// The maximum number of results to return. + /// If true, ignores user start node restrictions when searching. + /// A paged model containing the matching entities. Task> SearchAsync( UmbracoObjectTypes objectType, string query, diff --git a/src/Umbraco.Core/Services/IInstallationService.cs b/src/Umbraco.Core/Services/IInstallationService.cs index 688c6298bd32..84775146c23f 100644 --- a/src/Umbraco.Core/Services/IInstallationService.cs +++ b/src/Umbraco.Core/Services/IInstallationService.cs @@ -1,6 +1,14 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for logging Umbraco installation events and telemetry. +/// public interface IInstallationService { + /// + /// Logs an installation event with the provided installation details. + /// + /// The installation log containing details about the installation. + /// A task representing the asynchronous operation. Task LogInstall(InstallLog installLog); } diff --git a/src/Umbraco.Core/Services/IIpAddressUtilities.cs b/src/Umbraco.Core/Services/IIpAddressUtilities.cs index f6c371724416..db66da65e460 100644 --- a/src/Umbraco.Core/Services/IIpAddressUtilities.cs +++ b/src/Umbraco.Core/Services/IIpAddressUtilities.cs @@ -2,7 +2,16 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides utility methods for working with IP addresses. +/// public interface IIpAddressUtilities { + /// + /// Determines whether the specified client IP address is in the allow list. + /// + /// The client IP address to check. + /// The allowed IP string pattern to match against. + /// true if the IP address is in the allow list; otherwise, false. bool IsAllowListed(IPAddress clientIpAddress, string allowedIpString); } diff --git a/src/Umbraco.Core/Services/ILanguageService.cs b/src/Umbraco.Core/Services/ILanguageService.cs index 6ee7e5beba08..ae03a45147b5 100644 --- a/src/Umbraco.Core/Services/ILanguageService.cs +++ b/src/Umbraco.Core/Services/ILanguageService.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides methods for managing objects for localization. +/// public interface ILanguageService { /// diff --git a/src/Umbraco.Core/Services/ILocalizationService.cs b/src/Umbraco.Core/Services/ILocalizationService.cs index 5ddd710d97d8..f85bf8aff6e4 100644 --- a/src/Umbraco.Core/Services/ILocalizationService.cs +++ b/src/Umbraco.Core/Services/ILocalizationService.cs @@ -218,6 +218,12 @@ public interface ILocalizationService : IService [Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")] Dictionary GetDictionaryItemKeyMap(); + /// + /// Gets all languages with paging support. + /// + /// The number of items to skip. + /// The number of items to take. + /// A paged model containing the languages. [Obsolete("Please use ILanguageService for language operations. Will be removed in V15.")] PagedModel GetAllLanguagesPaged(int skip, int take) { diff --git a/src/Umbraco.Core/Services/ILogViewerService.cs b/src/Umbraco.Core/Services/ILogViewerService.cs index 9e7f9feb3f85..8c35d51274be 100644 --- a/src/Umbraco.Core/Services/ILogViewerService.cs +++ b/src/Umbraco.Core/Services/ILogViewerService.cs @@ -6,6 +6,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides methods for viewing and managing application log entries. +/// public interface ILogViewerService : IService { /// diff --git a/src/Umbraco.Core/Services/IMediaEditingService.cs b/src/Umbraco.Core/Services/IMediaEditingService.cs index fd96bef34a0f..b0174910ba1b 100644 --- a/src/Umbraco.Core/Services/IMediaEditingService.cs +++ b/src/Umbraco.Core/Services/IMediaEditingService.cs @@ -1,30 +1,145 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Cms.Core.Models.ContentEditing.Validation; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services; +/// +/// Defines the Media Editing Service, which provides operations for creating, updating, deleting, +/// and managing items through the editing API. +/// public interface IMediaEditingService { + /// + /// Gets a media item by its unique identifier. + /// + /// The unique identifier of the media item to retrieve. + /// + /// A task that represents the asynchronous operation. The task result contains + /// the item if found; otherwise, null. + /// Task GetAsync(Guid key); + /// + /// Validates a media creation model without persisting it. + /// + /// The containing the media data to validate. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the and + /// indicating the validation outcome. + /// Task> ValidateCreateAsync(MediaCreateModel createModel); + /// + /// Validates a media update model without persisting it. + /// + /// The unique identifier of the media item to validate the update for. + /// The containing the updated media data to validate. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the and + /// indicating the validation outcome. + /// Task> ValidateUpdateAsync(Guid key, MediaUpdateModel updateModel); + /// + /// Creates a new media item. + /// + /// The containing the media data to create. + /// The unique identifier of the user performing the operation. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the containing + /// the created media and indicating the operation outcome. + /// Task> CreateAsync(MediaCreateModel createModel, Guid userKey); + /// + /// Updates an existing media item. + /// + /// The unique identifier of the media item to update. + /// The containing the updated media data. + /// The unique identifier of the user performing the operation. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the containing + /// the updated media and indicating the operation outcome. + /// Task> UpdateAsync(Guid key, MediaUpdateModel updateModel, Guid userKey); + /// + /// Moves a media item to the recycle bin. + /// + /// The unique identifier of the media item to move to the recycle bin. + /// The unique identifier of the user performing the operation. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the moved item (if successful) + /// and indicating the operation outcome. + /// Task> MoveToRecycleBinAsync(Guid key, Guid userKey); + /// + /// Permanently deletes a media item. + /// + /// The unique identifier of the media item to delete. + /// The unique identifier of the user performing the operation. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the deleted item (if successful) + /// and indicating the operation outcome. + /// Task> DeleteAsync(Guid key, Guid userKey); + /// + /// Moves a media item to a new parent location. + /// + /// The unique identifier of the media item to move. + /// The unique identifier of the new parent, or null to move to the root. + /// The unique identifier of the user performing the operation. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the moved item (if successful) + /// and indicating the operation outcome. + /// Task> MoveAsync(Guid key, Guid? parentKey, Guid userKey); + /// + /// Sorts media items under a specified parent. + /// + /// The unique identifier of the parent, or null for root-level sorting. + /// The collection of items defining the sort order. + /// The unique identifier of the user performing the operation. + /// + /// A task that represents the asynchronous operation. The task result contains a + /// indicating the operation outcome. + /// Task SortAsync(Guid? parentKey, IEnumerable sortingModels, Guid userKey); + + /// + /// Permanently deletes a media item from the recycle bin. + /// + /// The unique identifier of the media item to delete from the recycle bin. + /// The unique identifier of the user performing the operation. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the deleted item (if successful) + /// and indicating the operation outcome. + /// Task> DeleteFromRecycleBinAsync(Guid key, Guid userKey); + /// + /// Restores a media item from the recycle bin to a specified parent location. + /// + /// The unique identifier of the media item to restore. + /// The unique identifier of the parent to restore to, or null to restore to the root. + /// The unique identifier of the user performing the operation. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the restored item (if successful) + /// and indicating the operation outcome. + /// Task> RestoreAsync(Guid key, Guid? parentKey, Guid userKey); } diff --git a/src/Umbraco.Core/Services/IMediaImportService.cs b/src/Umbraco.Core/Services/IMediaImportService.cs index 0b2c90022e4a..de6afd6c4839 100644 --- a/src/Umbraco.Core/Services/IMediaImportService.cs +++ b/src/Umbraco.Core/Services/IMediaImportService.cs @@ -1,8 +1,20 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides methods for importing media files into Umbraco. +/// public interface IMediaImportService { + /// + /// Imports a media file asynchronously. + /// + /// The name of the file being imported. + /// The stream containing the file data. + /// The parent folder identifier, or null to import at the root. + /// The media type alias, or null to auto-detect. + /// The key of the user performing the import. + /// A task that represents the asynchronous operation. The task result contains the imported . public Task ImportAsync(string fileName, Stream fileStream, Guid? parentId, string? mediaTypeAlias, Guid userKey); } diff --git a/src/Umbraco.Core/Services/IMediaListViewService.cs b/src/Umbraco.Core/Services/IMediaListViewService.cs index b7147f917c1d..126109141e07 100644 --- a/src/Umbraco.Core/Services/IMediaListViewService.cs +++ b/src/Umbraco.Core/Services/IMediaListViewService.cs @@ -4,8 +4,23 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides methods for retrieving media items in a list view format with paging and filtering support. +/// public interface IMediaListViewService { + /// + /// Gets media items for a list view by their container key with paging and filtering support. + /// + /// The user requesting the list view items. + /// The key of the parent container, or null for root level items. + /// The optional data type key to filter by. + /// The property to order results by. + /// The direction to order results. + /// An optional filter string to apply. + /// The number of items to skip. + /// The number of items to take. + /// An containing the paged media items if successful, or an error status if not. Task?, ContentCollectionOperationStatus>> GetListViewItemsByKeyAsync( IUser user, Guid? key, diff --git a/src/Umbraco.Core/Services/IMediaSearchService.cs b/src/Umbraco.Core/Services/IMediaSearchService.cs index ce8262956f97..b468e3e90a30 100644 --- a/src/Umbraco.Core/Services/IMediaSearchService.cs +++ b/src/Umbraco.Core/Services/IMediaSearchService.cs @@ -1,7 +1,13 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides search functionality for media items. +/// +/// +/// This interface extends to provide media-specific search capabilities. +/// public interface IMediaSearchService : IContentSearchService { } diff --git a/src/Umbraco.Core/Services/IMediaService.cs b/src/Umbraco.Core/Services/IMediaService.cs index 301d2a04278e..4552d62e9cc6 100644 --- a/src/Umbraco.Core/Services/IMediaService.cs +++ b/src/Umbraco.Core/Services/IMediaService.cs @@ -8,16 +8,48 @@ namespace Umbraco.Cms.Core.Services; /// public interface IMediaService : IContentServiceBase { + /// + /// Gets the count of media items that are not in the recycle bin. + /// + /// Optional alias of the to filter by. + /// The count of media items not in the recycle bin. int CountNotTrashed(string? contentTypeAlias = null); + /// + /// Gets the total count of media items. + /// + /// Optional alias of the to filter by. + /// The total count of media items. int Count(string? mediaTypeAlias = null); + /// + /// Gets the count of child media items under the specified parent. + /// + /// The Id of the parent to count children for. + /// Optional alias of the to filter by. + /// The count of child media items. int CountChildren(int parentId, string? mediaTypeAlias = null); + /// + /// Gets the count of descendant media items under the specified parent. + /// + /// The Id of the parent to count descendants for. + /// Optional alias of the to filter by. + /// The count of descendant media items. int CountDescendants(int parentId, string? mediaTypeAlias = null); + /// + /// Gets a collection of objects by their integer Ids. + /// + /// The collection of integer Ids to retrieve media for. + /// An enumerable collection of objects. IEnumerable GetByIds(IEnumerable ids); + /// + /// Gets a collection of objects by their unique Guids. + /// + /// The collection of keys to retrieve media for. + /// An enumerable collection of objects. IEnumerable GetByIds(IEnumerable ids); /// @@ -388,5 +420,10 @@ IEnumerable GetPagedMediaInRecycleBin( /// The size of the media. long GetMediaFileSize(string filepath); + /// + /// Empties the Recycle Bin asynchronously by deleting all that resides in the bin. + /// + /// The key of the user emptying the Recycle Bin. + /// A representing the asynchronous operation with an . Task EmptyRecycleBinAsync(Guid userId); } diff --git a/src/Umbraco.Core/Services/IMediaTypeContainerService.cs b/src/Umbraco.Core/Services/IMediaTypeContainerService.cs index 7d0f955bd8e6..91ad839c20f1 100644 --- a/src/Umbraco.Core/Services/IMediaTypeContainerService.cs +++ b/src/Umbraco.Core/Services/IMediaTypeContainerService.cs @@ -1,7 +1,13 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing media type containers (folders). +/// +/// +/// Media type containers allow organizing media types into a hierarchical folder structure. +/// public interface IMediaTypeContainerService : IEntityTypeContainerService { } diff --git a/src/Umbraco.Core/Services/IMediaValidationService.cs b/src/Umbraco.Core/Services/IMediaValidationService.cs index 12365ef94740..a6dfce4f779f 100644 --- a/src/Umbraco.Core/Services/IMediaValidationService.cs +++ b/src/Umbraco.Core/Services/IMediaValidationService.cs @@ -1,7 +1,13 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides validation functionality for media content. +/// +/// +/// This interface extends to provide media-specific validation capabilities. +/// internal interface IMediaValidationService : IContentValidationServiceBase { } diff --git a/src/Umbraco.Core/Services/IMemberContentEditingService.cs b/src/Umbraco.Core/Services/IMemberContentEditingService.cs index 365b85862a88..1fdeb64e2fbb 100644 --- a/src/Umbraco.Core/Services/IMemberContentEditingService.cs +++ b/src/Umbraco.Core/Services/IMemberContentEditingService.cs @@ -1,14 +1,45 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services; +/// +/// Provides content editing operations for members. +/// public interface IMemberContentEditingService { + /// + /// Validates a member editing model against its member type. + /// + /// The member editing model to validate. + /// The unique identifier of the member type. + /// + /// An attempt containing the if successful, + /// or a indicating the failure reason. + /// Task> ValidateAsync(MemberEditingModelBase editingModel, Guid memberTypeKey); + /// + /// Updates an existing member with the provided editing model. + /// + /// The member to update. + /// The model containing the updated member data. + /// The unique identifier of the user performing the update. + /// + /// An attempt containing the if successful, + /// or a indicating the failure reason. + /// Task> UpdateAsync(IMember member, MemberEditingModelBase updateModel, Guid userKey); + /// + /// Deletes a member by its unique identifier. + /// + /// The unique identifier of the member to delete. + /// The unique identifier of the user performing the deletion. + /// + /// An attempt containing the deleted if successful, + /// or a indicating the failure reason. + /// Task> DeleteAsync(Guid key, Guid userKey); } diff --git a/src/Umbraco.Core/Services/IMemberEditingService.cs b/src/Umbraco.Core/Services/IMemberEditingService.cs index c7d9486362a0..ed0cbe004c4d 100644 --- a/src/Umbraco.Core/Services/IMemberEditingService.cs +++ b/src/Umbraco.Core/Services/IMemberEditingService.cs @@ -1,21 +1,59 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services; +/// +/// Defines the member editing service, which provides operations for creating, updating, and deleting members. +/// public interface IMemberEditingService { + /// + /// Gets a member by its unique key. + /// + /// The unique key of the member. + /// A task that represents the asynchronous operation. The task result contains the if found; otherwise, null. Task GetAsync(Guid key); + /// + /// Validates a member create model before creation. + /// + /// The to validate. + /// A task that represents the asynchronous operation. The task result contains an with validation results and operation status. Task> ValidateCreateAsync(MemberCreateModel createModel); + /// + /// Validates a member update model before updating. + /// + /// The unique key of the member to update. + /// The to validate. + /// A task that represents the asynchronous operation. The task result contains an with validation results and operation status. Task> ValidateUpdateAsync(Guid key, MemberUpdateModel updateModel); + /// + /// Creates a new member. + /// + /// The containing the member data. + /// The user performing the create operation. + /// A task that represents the asynchronous operation. The task result contains an with the creation result and status. Task> CreateAsync(MemberCreateModel createModel, IUser user); + /// + /// Updates an existing member. + /// + /// The unique key of the member to update. + /// The containing the updated member data. + /// The user performing the update operation. + /// A task that represents the asynchronous operation. The task result contains an with the update result and status. Task> UpdateAsync(Guid key, MemberUpdateModel updateModel, IUser user); + /// + /// Deletes a member. + /// + /// The unique key of the member to delete. + /// The unique key of the user performing the delete operation. + /// A task that represents the asynchronous operation. The task result contains an with the deleted member and status. Task> DeleteAsync(Guid key, Guid userKey); } diff --git a/src/Umbraco.Core/Services/IMemberGroupService.cs b/src/Umbraco.Core/Services/IMemberGroupService.cs index 67e0ac19975f..1f3840c70121 100644 --- a/src/Umbraco.Core/Services/IMemberGroupService.cs +++ b/src/Umbraco.Core/Services/IMemberGroupService.cs @@ -3,25 +3,60 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Defines the MemberGroupService, which provides operations for managing objects. +/// public interface IMemberGroupService : IService { + /// + /// Gets all member groups. + /// + /// An enumerable collection of all objects. [Obsolete("Please use the asynchronous counterpart. Scheduled for removal in v15.")] IEnumerable GetAll(); + /// + /// Gets a member group by its integer id. + /// + /// The integer id of the member group. + /// The if found; otherwise, null. [Obsolete("Please use Guid instead of Int id. Scheduled for removal in v15.")] IMemberGroup? GetById(int id); + /// + /// Gets a member group by its key. + /// + /// The key of the member group. + /// The if found; otherwise, null. [Obsolete("Please use the asynchronous counterpart. Scheduled for removal in v15.")] IMemberGroup? GetById(Guid id); + /// + /// Gets multiple member groups by their integer ids. + /// + /// An enumerable collection of integer ids. + /// An enumerable collection of objects. [Obsolete("Please use the asynchronous counterpart. Scheduled for removal in v15.")] IEnumerable GetByIds(IEnumerable ids); + /// + /// Gets a member group by its name. + /// + /// The name of the member group. + /// The if found; otherwise, null. IMemberGroup? GetByName(string? name); + /// + /// Saves a member group. + /// + /// The to save. [Obsolete("Please use the respective CreateAsync/UpdateAsync for you save operations. Scheduled for removal in v15.")] void Save(IMemberGroup memberGroup); + /// + /// Deletes a member group. + /// + /// The to delete. [Obsolete("Please use the asynchronous counterpart. Scheduled for removal in v15.")] void Delete(IMemberGroup memberGroup); @@ -63,6 +98,7 @@ public interface IMemberGroupService : IService /// Deletes a by removing it and its usages from the db /// /// The key of the to delete + /// An attempt with a status of whether the operation was successful or not, and the deleted object if it succeeded. Task> DeleteAsync(Guid key); /// diff --git a/src/Umbraco.Core/Services/IMemberService.cs b/src/Umbraco.Core/Services/IMemberService.cs index d56cb1b98cca..8bc737d5c133 100644 --- a/src/Umbraco.Core/Services/IMemberService.cs +++ b/src/Umbraco.Core/Services/IMemberService.cs @@ -18,7 +18,7 @@ public interface IMemberService : IMembershipMemberService, IContentServiceBase< /// Total number of records found (out) /// Field to order by /// Direction to order by - /// + /// Optional alias of the MemberType to filter by. /// Search text filter /// /// @@ -42,7 +42,7 @@ IEnumerable GetAll( /// Field to order by /// Direction to order by /// Flag to indicate when ordering by system field - /// + /// Optional alias of the MemberType to filter by. /// Search text filter /// /// @@ -57,6 +57,15 @@ IEnumerable GetAll( string? memberTypeAlias, string filter); + /// + /// Filters members based on the specified criteria. + /// + /// The filter criteria to apply. + /// The field to order results by. Default is "username". + /// The direction to order results. Default is . + /// The number of records to skip. Default is 0. + /// The number of records to take. Default is 100. + /// A containing the filtered members. public Task> FilterAsync( MemberFilter memberFilter, string orderBy = "username", @@ -188,6 +197,7 @@ IMember CreateMemberWithIdentity(string username, string email, string name, str /// or to Save /// Enum for deciding which notifications to publish. /// Id of the User saving the Member + /// An indicating the result of the save operation. Attempt Save(IMember member, PublishNotificationSaveOptions publishNotificationSaveOptions, int userId = Constants.Security.SuperUserId) => Save(member, userId); /// @@ -195,6 +205,7 @@ IMember CreateMemberWithIdentity(string username, string email, string name, str /// /// The to save /// Id of the User saving the Member + /// An indicating the result of the save operation. Attempt Save(IMember media, int userId = Constants.Security.SuperUserId); // TODO (V18): Rename parameter 'media' to 'member'. /// @@ -202,6 +213,7 @@ IMember CreateMemberWithIdentity(string username, string email, string name, str /// /// Collection of to save /// Id of the User saving the Members + /// An indicating the result of the save operation. // TODO (V18): This is already declared on the base type, so for the next major, when we can allow a binary breaking change, we should remove it from here. #pragma warning disable CS0108 // Member hides inherited member; missing new keyword Attempt Save(IEnumerable members, int userId = Constants.Security.SuperUserId); @@ -311,6 +323,7 @@ IEnumerable GetMembersByEmail(string email) /// /// The to delete /// Id of the User deleting the Member + /// An indicating the result of the delete operation. Attempt Delete(IMember member, int userId = Constants.Security.SuperUserId); /// diff --git a/src/Umbraco.Core/Services/IMemberTypeContainerService.cs b/src/Umbraco.Core/Services/IMemberTypeContainerService.cs index d84b5781c098..048bfd1c3087 100644 --- a/src/Umbraco.Core/Services/IMemberTypeContainerService.cs +++ b/src/Umbraco.Core/Services/IMemberTypeContainerService.cs @@ -2,6 +2,12 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing member type containers (folders). +/// +/// +/// Member type containers allow organizing member types into a hierarchical folder structure. +/// public interface IMemberTypeContainerService : IEntityTypeContainerService { } diff --git a/src/Umbraco.Core/Services/IMemberTypeService.cs b/src/Umbraco.Core/Services/IMemberTypeService.cs index 6a70e620a165..ee29392f5cda 100644 --- a/src/Umbraco.Core/Services/IMemberTypeService.cs +++ b/src/Umbraco.Core/Services/IMemberTypeService.cs @@ -7,5 +7,9 @@ namespace Umbraco.Cms.Core.Services; /// public interface IMemberTypeService : IContentTypeBaseService { + /// + /// Gets the alias of the default . + /// + /// The alias of the default member type. string GetDefault(); } diff --git a/src/Umbraco.Core/Services/IMemberValidationService.cs b/src/Umbraco.Core/Services/IMemberValidationService.cs index a575c70a00e2..fbbfe3fd9605 100644 --- a/src/Umbraco.Core/Services/IMemberValidationService.cs +++ b/src/Umbraco.Core/Services/IMemberValidationService.cs @@ -1,7 +1,13 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides validation functionality for member content. +/// +/// +/// This interface extends to provide member-specific validation capabilities. +/// internal interface IMemberValidationService : IContentValidationServiceBase { } diff --git a/src/Umbraco.Core/Services/IMembershipRoleService.cs b/src/Umbraco.Core/Services/IMembershipRoleService.cs index 538ae4fb8c8d..4e535633c126 100644 --- a/src/Umbraco.Core/Services/IMembershipRoleService.cs +++ b/src/Umbraco.Core/Services/IMembershipRoleService.cs @@ -4,46 +4,150 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Defines the MembershipRoleService, which provides role management operations for membership users. +/// +/// The type of membership user, must implement . public interface IMembershipRoleService where T : class, IMembershipUser { + /// + /// Adds a new role with the specified name. + /// + /// The name of the role to add. void AddRole(string roleName); + /// + /// Gets all roles as objects. + /// + /// An enumerable collection of all objects. IEnumerable GetAllRoles(); + /// + /// Gets all role names for a member by their integer id. + /// + /// The integer id of the member. + /// An enumerable collection of role names assigned to the member. IEnumerable GetAllRoles(int memberId); + /// + /// Gets all role names for a member by their username. + /// + /// The username of the member. + /// An enumerable collection of role names assigned to the member. IEnumerable GetAllRoles(string username); + /// + /// Gets the integer ids of all roles. + /// + /// An enumerable collection of all role ids. IEnumerable GetAllRolesIds(); + /// + /// Gets the integer ids of all roles for a member by their integer id. + /// + /// The integer id of the member. + /// An enumerable collection of role ids assigned to the member. IEnumerable GetAllRolesIds(int memberId); + /// + /// Gets the integer ids of all roles for a member by their username. + /// + /// The username of the member. + /// An enumerable collection of role ids assigned to the member. IEnumerable GetAllRolesIds(string username); + /// + /// Gets all members that belong to a specific role. + /// + /// The name of the role. + /// An enumerable collection of members in the specified role. IEnumerable GetMembersInRole(string roleName); + /// + /// Finds members in a role whose username matches the specified pattern. + /// + /// The name of the role to search within. + /// The username pattern to match. + /// The type of string matching to use. Default is . + /// An enumerable collection of members matching the criteria. IEnumerable FindMembersInRole(string roleName, string usernameToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith); + /// + /// Deletes a role by its name. + /// + /// The name of the role to delete. + /// If true, throws an exception if the role is currently assigned to any members. + /// true if the role was successfully deleted; otherwise, false. bool DeleteRole(string roleName, bool throwIfBeingUsed); + /// + /// Assigns a single role to a member by username. + /// + /// The username of the member. + /// The name of the role to assign. void AssignRole(string username, string roleName); + /// + /// Assigns multiple roles to multiple members by their usernames. + /// + /// An array of usernames to assign roles to. + /// An array of role names to assign. void AssignRoles(string[] usernames, string[] roleNames); + /// + /// Removes a single role from a member by username. + /// + /// The username of the member. + /// The name of the role to remove. void DissociateRole(string username, string roleName); + /// + /// Removes multiple roles from multiple members by their usernames. + /// + /// An array of usernames to remove roles from. + /// An array of role names to remove. void DissociateRoles(string[] usernames, string[] roleNames); + /// + /// Assigns a single role to a member by their integer id. + /// + /// The integer id of the member. + /// The name of the role to assign. void AssignRole(int memberId, string roleName); + /// + /// Assigns multiple roles to multiple members by their integer ids. + /// + /// An array of member ids to assign roles to. + /// An array of role names to assign. void AssignRoles(int[] memberIds, string[] roleNames); + /// + /// Removes a single role from a member by their integer id. + /// + /// The integer id of the member. + /// The name of the role to remove. void DissociateRole(int memberId, string roleName); + /// + /// Removes multiple roles from multiple members by their integer ids. + /// + /// An array of member ids to remove roles from. + /// An array of role names to remove. void DissociateRoles(int[] memberIds, string[] roleNames); + /// + /// Replaces all existing roles for the specified members with the given roles, identified by usernames. + /// + /// An array of usernames whose roles will be replaced. + /// An array of role names to assign as the new roles. void ReplaceRoles(string[] usernames, string[] roleNames); + /// + /// Replaces all existing roles for the specified members with the given roles, identified by member ids. + /// + /// An array of member ids whose roles will be replaced. + /// An array of role names to assign as the new roles. void ReplaceRoles(int[] memberIds, string[] roleNames); } diff --git a/src/Umbraco.Core/Services/IMetricsConsentService.cs b/src/Umbraco.Core/Services/IMetricsConsentService.cs index d40b2107d081..4a6184b4bde5 100644 --- a/src/Umbraco.Core/Services/IMetricsConsentService.cs +++ b/src/Umbraco.Core/Services/IMetricsConsentService.cs @@ -2,9 +2,21 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides operations for managing telemetry metrics consent. +/// public interface IMetricsConsentService { + /// + /// Gets the current telemetry consent level. + /// + /// The current configured for the system. TelemetryLevel GetConsentLevel(); + /// + /// Sets the telemetry consent level asynchronously. + /// + /// The to set. + /// A task representing the asynchronous operation. Task SetConsentLevelAsync(TelemetryLevel telemetryLevel); } diff --git a/src/Umbraco.Core/Services/INodeCountService.cs b/src/Umbraco.Core/Services/INodeCountService.cs index d442a7199f45..7f8be4dcb0b8 100644 --- a/src/Umbraco.Core/Services/INodeCountService.cs +++ b/src/Umbraco.Core/Services/INodeCountService.cs @@ -1,8 +1,20 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality to retrieve counts of nodes in the Umbraco content tree. +/// public interface INodeCountService { + /// + /// Gets the count of nodes of a specific object type. + /// + /// The GUID representing the Umbraco object type. + /// The total count of nodes of the specified type. int GetNodeCount(Guid nodeType); + /// + /// Gets the total count of media items. + /// + /// The total count of media items in the system. int GetMediaCount(); } diff --git a/src/Umbraco.Core/Services/INotificationService.cs b/src/Umbraco.Core/Services/INotificationService.cs index 06193b27086e..7f2ce3622e86 100644 --- a/src/Umbraco.Core/Services/INotificationService.cs +++ b/src/Umbraco.Core/Services/INotificationService.cs @@ -5,6 +5,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides operations for managing user notifications related to content changes. +/// public interface INotificationService : IService { /// diff --git a/src/Umbraco.Core/Services/IPackageDataInstallation.cs b/src/Umbraco.Core/Services/IPackageDataInstallation.cs index f07115544337..53db9aded6ef 100644 --- a/src/Umbraco.Core/Services/IPackageDataInstallation.cs +++ b/src/Umbraco.Core/Services/IPackageDataInstallation.cs @@ -5,8 +5,18 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Defines the PackageDataInstallation service, which provides operations for installing package data such as +/// content types, data types, dictionary items, languages, and templates. +/// public interface IPackageDataInstallation { + /// + /// Installs the data from a compiled package. + /// + /// The compiled package containing the data to install. + /// The id of the user performing the installation. + /// An containing the results of the installation. InstallationSummary InstallPackageData(CompiledPackage compiledPackage, int userId); /// @@ -25,6 +35,17 @@ public interface IPackageDataInstallation /// An enumerable list of generated s. IReadOnlyList ImportMemberTypes(IEnumerable docTypeElements, int userId) => throw new NotImplementedException(); + /// + /// Imports and saves content base items from a compiled package. + /// + /// The type of content base being imported (e.g., or ). + /// The type of content type composition. + /// The compiled package content base items to import. + /// A dictionary of imported document types keyed by their alias. + /// The id of the user performing the import. + /// The service for managing content types. + /// The service for managing content. + /// A read-only list of imported content base items. IReadOnlyList ImportContentBase( IEnumerable docs, IDictionary importedDocumentTypes, @@ -34,6 +55,12 @@ IReadOnlyList ImportContentBase + /// Imports and saves a single document type from an . + /// + /// The XML element representing the document type. + /// The id of the user performing the import. + /// A read-only list of imported objects. IReadOnlyList ImportDocumentType(XElement docTypeElement, int userId); /// @@ -56,12 +83,19 @@ IReadOnlyList ImportContentBase /// /// Xml to import - /// + /// The id of the user performing the import. /// An enumerable list of dictionary items IReadOnlyList ImportDictionaryItems( IEnumerable dictionaryItemElementList, int userId); + /// + /// Imports a single dictionary item and its children from an . + /// + /// The XML element representing the dictionary item. + /// The id of the user performing the import. + /// The optional parent id for the dictionary item. + /// An enumerable collection of imported objects. IEnumerable ImportDictionaryItem(XElement dictionaryItemElement, int userId, Guid? parentId); /// @@ -72,6 +106,12 @@ IReadOnlyList ImportDictionaryItems( /// An enumerable list of generated languages IReadOnlyList ImportLanguages(IEnumerable languageElements, int userId); + /// + /// Imports a single template from an asynchronously. + /// + /// The XML element representing the template. + /// The id of the user performing the import. + /// An enumerable collection of imported objects. Task> ImportTemplateAsync(XElement templateElement, int userId); /// @@ -82,7 +122,17 @@ IReadOnlyList ImportDictionaryItems( /// An enumerable list of generated Templates Task> ImportTemplatesAsync(IReadOnlyCollection templateElements, int userId); + /// + /// Gets the content type key from an XML element representing a content type. + /// + /// The XML element representing the content type. + /// The key of the content type. Guid GetContentTypeKey(XElement contentType); + /// + /// Gets the entity type alias from an XML element. + /// + /// The XML element representing the entity type. + /// The alias of the entity type, or null if not found. string? GetEntityTypeAlias(XElement entityType); } diff --git a/src/Umbraco.Core/Services/IPackagingService.cs b/src/Umbraco.Core/Services/IPackagingService.cs index d2a175824d40..bba467c508f0 100644 --- a/src/Umbraco.Core/Services/IPackagingService.cs +++ b/src/Umbraco.Core/Services/IPackagingService.cs @@ -7,6 +7,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides operations for installing, exporting, and managing Umbraco packages. +/// public interface IPackagingService : IService { /// @@ -23,6 +26,12 @@ public interface IPackagingService : IService /// InstallationSummary InstallCompiledPackageData(FileInfo packageXmlFile, int userId = Constants.Security.SuperUserId); + /// + /// Installs the data, entities, objects contained in an umbraco package XML document. + /// + /// The package XML document. + /// The user identifier performing the installation. + /// An containing the results of the installation. InstallationSummary InstallCompiledPackageData(XDocument? packageXml, int userId = Constants.Security.SuperUserId); /// @@ -36,6 +45,11 @@ public interface IPackagingService : IService /// Task> GetInstalledPackagesFromMigrationPlansAsync(int skip, int take); + /// + /// Gets an installed package by its name. + /// + /// The name of the package. + /// The if found; otherwise, null. InstalledPackage? GetInstalledPackageByName(string packageName); /// diff --git a/src/Umbraco.Core/Services/IPartialViewService.cs b/src/Umbraco.Core/Services/IPartialViewService.cs index c547183e31cc..8a8786f96141 100644 --- a/src/Umbraco.Core/Services/IPartialViewService.cs +++ b/src/Umbraco.Core/Services/IPartialViewService.cs @@ -1,10 +1,13 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services.OperationStatus; using Umbraco.Cms.Core.Snippets; using PartialViewSnippet = Umbraco.Cms.Core.Snippets.PartialViewSnippet; namespace Umbraco.Cms.Core.Services; +/// +/// Defines the Partial View Service, which provides operations for managing files. +/// public interface IPartialViewService : IBasicFileService { /// diff --git a/src/Umbraco.Core/Services/IPreviewService.cs b/src/Umbraco.Core/Services/IPreviewService.cs index c65dbe16bbd3..45cffe8d6ed0 100644 --- a/src/Umbraco.Core/Services/IPreviewService.cs +++ b/src/Umbraco.Core/Services/IPreviewService.cs @@ -1,21 +1,39 @@ -using System.Security.Claims; +using System.Security.Claims; using Umbraco.Cms.Core.Models.Membership; namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing content preview mode. +/// +/// +/// Preview mode allows backoffice users to view unpublished content changes +/// as they would appear on the front-end website. +/// public interface IPreviewService { /// - /// Enters preview mode for a given user that calls this + /// Enters preview mode for a given user. /// + /// The user entering preview mode. + /// true if preview mode was entered successfully; otherwise, false. Task TryEnterPreviewAsync(IUser user); /// - /// Exits preview mode for a given user that calls this + /// Exits preview mode for the current request. /// + /// A task representing the asynchronous operation. Task EndPreviewAsync(); + /// + /// Determines whether the current request is in preview mode. + /// + /// true if the current request is in preview mode; otherwise, false. bool IsInPreview(); + /// + /// Attempts to get the claims identity for the current preview session. + /// + /// An attempt containing the claims identity if in preview mode; otherwise, a failed attempt. Task> TryGetPreviewClaimsIdentityAsync(); } diff --git a/src/Umbraco.Core/Services/IPropertyValidationService.cs b/src/Umbraco.Core/Services/IPropertyValidationService.cs index 5937aab40eac..0c63ab36076e 100644 --- a/src/Umbraco.Core/Services/IPropertyValidationService.cs +++ b/src/Umbraco.Core/Services/IPropertyValidationService.cs @@ -5,6 +5,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides validation services for content properties. +/// public interface IPropertyValidationService { /// diff --git a/src/Umbraco.Core/Services/IPublicAccessService.cs b/src/Umbraco.Core/Services/IPublicAccessService.cs index b04ab230e4ef..627e94df853e 100644 --- a/src/Umbraco.Core/Services/IPublicAccessService.cs +++ b/src/Umbraco.Core/Services/IPublicAccessService.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides operations for managing public access restrictions on content. +/// public interface IPublicAccessService : IService { /// diff --git a/src/Umbraco.Core/Services/IRedirectUrlService.cs b/src/Umbraco.Core/Services/IRedirectUrlService.cs index ef90f14e6467..13c161bbb3b6 100644 --- a/src/Umbraco.Core/Services/IRedirectUrlService.cs +++ b/src/Umbraco.Core/Services/IRedirectUrlService.cs @@ -1,9 +1,10 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; /// +/// Provides operations for managing URL redirects for content items. /// public interface IRedirectUrlService : IService { diff --git a/src/Umbraco.Core/Services/IRelationService.cs b/src/Umbraco.Core/Services/IRelationService.cs index 7ddae1394ded..01fc73ae8f55 100644 --- a/src/Umbraco.Core/Services/IRelationService.cs +++ b/src/Umbraco.Core/Services/IRelationService.cs @@ -4,6 +4,13 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing relations and relation types between entities. +/// +/// +/// Relations allow entities like content, media, and members to be linked together +/// through various relationship types. +/// public interface IRelationService : IService { /// @@ -130,6 +137,12 @@ public interface IRelationService : IService /// An enumerable list of objects IEnumerable GetByParentOrChildId(int id); + /// + /// Gets a list of objects by their child or parent Id and relation type alias. + /// + /// Id of the child or parent to retrieve relations for. + /// Alias of the type of relation to retrieve. + /// An enumerable list of objects. IEnumerable GetByParentOrChildId(int id, string relationTypeAlias); /// @@ -355,6 +368,10 @@ bool IsRelated(int id, RelationDirectionFilter directionFilter, int[]? includeRe /// Relation to save void Save(IRelation relation); + /// + /// Saves a collection of objects. + /// + /// The collection of relations to save. void Save(IEnumerable relations); /// @@ -411,7 +428,20 @@ bool IsRelated(int id, RelationDirectionFilter directionFilter, int[]? includeRe /// All of the allowed . IEnumerable GetAllowedObjectTypes(); + /// + /// Gets a paged result of objects by child key. + /// + /// The unique key of the child entity. + /// The number of items to skip. + /// The number of items to take. + /// Optional alias of the relation type to filter by. + /// A paged model containing the relations. Task> GetPagedByChildKeyAsync(Guid childKey, int skip, int take, string? relationTypeAlias); + + /// + /// Gets the total count of relation types. + /// + /// The number of relation types. int CountRelationTypes(); /// diff --git a/src/Umbraco.Core/Services/IReservedFieldNamesService.cs b/src/Umbraco.Core/Services/IReservedFieldNamesService.cs index 84af0e1f3bb2..4822406f8064 100644 --- a/src/Umbraco.Core/Services/IReservedFieldNamesService.cs +++ b/src/Umbraco.Core/Services/IReservedFieldNamesService.cs @@ -1,10 +1,25 @@ -namespace Umbraco.Cms.Core.Services; +namespace Umbraco.Cms.Core.Services; +/// +/// Provides access to reserved field names that cannot be used for custom properties. +/// public interface IReservedFieldNamesService { + /// + /// Gets the set of reserved field names for document content types. + /// + /// A set of field names that are reserved for documents. ISet GetDocumentReservedFieldNames(); + /// + /// Gets the set of reserved field names for media content types. + /// + /// A set of field names that are reserved for media. ISet GetMediaReservedFieldNames(); + /// + /// Gets the set of reserved field names for member content types. + /// + /// A set of field names that are reserved for members. ISet GetMemberReservedFieldNames(); } diff --git a/src/Umbraco.Core/Services/IRuntimeState.cs b/src/Umbraco.Core/Services/IRuntimeState.cs index a57667101099..309533d85e41 100644 --- a/src/Umbraco.Core/Services/IRuntimeState.cs +++ b/src/Umbraco.Core/Services/IRuntimeState.cs @@ -58,5 +58,11 @@ public interface IRuntimeState /// void DetermineRuntimeLevel(); + /// + /// Configures the runtime state with the specified level and reason. + /// + /// The runtime level to set. + /// The reason for the runtime level. + /// An optional exception that caused a boot failure. void Configure(RuntimeLevel level, RuntimeLevelReason reason, Exception? bootFailedException = null); } diff --git a/src/Umbraco.Core/Services/IScriptService.cs b/src/Umbraco.Core/Services/IScriptService.cs index 157e18f0aac7..2b0f18bb3291 100644 --- a/src/Umbraco.Core/Services/IScriptService.cs +++ b/src/Umbraco.Core/Services/IScriptService.cs @@ -1,8 +1,11 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services; +/// +/// Defines the Script Service, which provides operations for managing files. +/// public interface IScriptService : IBasicFileService { /// diff --git a/src/Umbraco.Core/Services/ISegmentService.cs b/src/Umbraco.Core/Services/ISegmentService.cs index c31cbf9f5e66..b52c36f379f4 100644 --- a/src/Umbraco.Core/Services/ISegmentService.cs +++ b/src/Umbraco.Core/Services/ISegmentService.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides operations for managing content segments. +/// public interface ISegmentService { /// diff --git a/src/Umbraco.Core/Services/IServerInformationService.cs b/src/Umbraco.Core/Services/IServerInformationService.cs index 228b84c3ddd2..a4f4db09370d 100644 --- a/src/Umbraco.Core/Services/IServerInformationService.cs +++ b/src/Umbraco.Core/Services/IServerInformationService.cs @@ -5,17 +5,33 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides server information about the current Umbraco instance. +/// public interface IServerInformationService { + /// + /// Gets information about the server including version, timezone, and runtime mode. + /// + /// A object containing the server details. ServerInformation GetServerInformation(); } +/// +/// Default implementation of . +/// public class ServerInformationService : IServerInformationService { private readonly IUmbracoVersion _umbracoVersion; private readonly TimeProvider _timeProvider; private RuntimeSettings _runtimeSettings; + /// + /// Initializes a new instance of the class. + /// + /// The Umbraco version provider. + /// The time provider for timezone information. + /// The runtime settings monitor. public ServerInformationService(IUmbracoVersion umbracoVersion, TimeProvider timeProvider, IOptionsMonitor runtimeSettingsOptionsMonitor) { _umbracoVersion = umbracoVersion; @@ -24,5 +40,6 @@ public ServerInformationService(IUmbracoVersion umbracoVersion, TimeProvider tim runtimeSettingsOptionsMonitor.OnChange(runtimeSettings => _runtimeSettings = runtimeSettings); } + /// public ServerInformation GetServerInformation() => new(_umbracoVersion.SemanticVersion, _timeProvider.LocalTimeZone, _runtimeSettings.Mode); } diff --git a/src/Umbraco.Core/Services/IServerRegistrationService.cs b/src/Umbraco.Core/Services/IServerRegistrationService.cs index 376376273b17..ffa18fb1e1bf 100644 --- a/src/Umbraco.Core/Services/IServerRegistrationService.cs +++ b/src/Umbraco.Core/Services/IServerRegistrationService.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides operations for managing server registrations in a load-balanced environment. +/// public interface IServerRegistrationService { /// diff --git a/src/Umbraco.Core/Services/IStylesheetService.cs b/src/Umbraco.Core/Services/IStylesheetService.cs index 807fb4285abb..d37151f4ba37 100644 --- a/src/Umbraco.Core/Services/IStylesheetService.cs +++ b/src/Umbraco.Core/Services/IStylesheetService.cs @@ -1,8 +1,11 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services; +/// +/// Defines the Stylesheet Service, which provides operations for managing files. +/// public interface IStylesheetService : IBasicFileService { /// diff --git a/src/Umbraco.Core/Services/ISystemTroubleshootingInformationService.cs b/src/Umbraco.Core/Services/ISystemTroubleshootingInformationService.cs index 697288ccfe2a..1d1fde578b18 100644 --- a/src/Umbraco.Core/Services/ISystemTroubleshootingInformationService.cs +++ b/src/Umbraco.Core/Services/ISystemTroubleshootingInformationService.cs @@ -1,7 +1,10 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Service for retrieving system troubleshooting information. +/// public interface ISystemTroubleshootingInformationService { /// diff --git a/src/Umbraco.Core/Services/ITagService.cs b/src/Umbraco.Core/Services/ITagService.cs index c3583ca35221..caf9e4d5c4e7 100644 --- a/src/Umbraco.Core/Services/ITagService.cs +++ b/src/Umbraco.Core/Services/ITagService.cs @@ -59,6 +59,12 @@ public interface ITagService : IService /// IEnumerable GetAllTags(string? group = null, string? culture = null); + /// + /// Gets all tags asynchronously. + /// + /// The optional tag group to filter by. + /// The optional culture to filter by. + /// A task that represents the asynchronous operation, containing a collection of objects. Task> GetAllAsync(string? group = null, string? culture = null) { if (culture == string.Empty) @@ -69,6 +75,13 @@ Task> GetAllAsync(string? group = null, string? culture = null return Task.FromResult(GetAllTags(group, culture)); } + /// + /// Gets tags matching the specified query asynchronously. + /// + /// The search query to filter tags by. + /// The optional tag group to filter by. + /// The optional culture to filter by. + /// A task that represents the asynchronous operation, containing a collection of matching objects. Task> GetByQueryAsync(string query, string? group = null, string? culture = null) => Task.FromResult(GetAllAsync(group, culture).GetAwaiter().GetResult().Where(x => x.Text.InvariantContains(query))); diff --git a/src/Umbraco.Core/Services/ITemplateContentParserService.cs b/src/Umbraco.Core/Services/ITemplateContentParserService.cs index 0fef658b017b..1101cf4c5455 100644 --- a/src/Umbraco.Core/Services/ITemplateContentParserService.cs +++ b/src/Umbraco.Core/Services/ITemplateContentParserService.cs @@ -1,6 +1,14 @@ -namespace Umbraco.Cms.Core.Services; +namespace Umbraco.Cms.Core.Services; +/// +/// Service for parsing template content to extract layout information. +/// public interface ITemplateContentParserService { + /// + /// Extracts the master template alias from the view content. + /// + /// The view content to parse. + /// The alias of the master template, or null if not found. string? MasterTemplateAlias(string? viewContent); } diff --git a/src/Umbraco.Core/Services/ITemplateService.cs b/src/Umbraco.Core/Services/ITemplateService.cs index a4ec73b40aa1..d45af1291ae9 100644 --- a/src/Umbraco.Core/Services/ITemplateService.cs +++ b/src/Umbraco.Core/Services/ITemplateService.cs @@ -1,8 +1,11 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services; +/// +/// Provides methods for managing templates (views) used for rendering content. +/// public interface ITemplateService : IService { /// diff --git a/src/Umbraco.Core/Services/ITemporaryFileService.cs b/src/Umbraco.Core/Services/ITemporaryFileService.cs index 95c5a956dad8..a167896a9207 100644 --- a/src/Umbraco.Core/Services/ITemporaryFileService.cs +++ b/src/Umbraco.Core/Services/ITemporaryFileService.cs @@ -3,13 +3,38 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing temporary files used during uploads and other operations. +/// +/// +/// Temporary files are stored for a limited time and are automatically cleaned up. +/// public interface ITemporaryFileService { + /// + /// Creates a new temporary file. + /// + /// The model containing the file data and metadata. + /// An attempt containing the created temporary file model if successful, or an operation status indicating failure. Task> CreateAsync(CreateTemporaryFileModel createModel); + /// + /// Deletes a temporary file by its key. + /// + /// The unique identifier of the temporary file to delete. + /// An attempt containing the deleted temporary file model if successful, or an operation status indicating failure. Task> DeleteAsync(Guid key); + /// + /// Gets a temporary file by its key. + /// + /// The unique identifier of the temporary file. + /// The temporary file model if found; otherwise, null. Task GetAsync(Guid key); + /// + /// Cleans up expired temporary files. + /// + /// A collection of keys for the temporary files that were cleaned up. Task> CleanUpOldTempFiles(); } diff --git a/src/Umbraco.Core/Services/ITrackedReferencesService.cs b/src/Umbraco.Core/Services/ITrackedReferencesService.cs index ad84c79fcc83..1c39a136153b 100644 --- a/src/Umbraco.Core/Services/ITrackedReferencesService.cs +++ b/src/Umbraco.Core/Services/ITrackedReferencesService.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Service for tracking references between entities in Umbraco. +/// public interface ITrackedReferencesService { /// @@ -95,5 +98,13 @@ async Task, GetReferencesOperationStatus>> /// A paged result of objects. Task> GetPagedItemsWithRelationsAsync(ISet keys, long skip, long take, bool filterMustBeIsDependency); + /// + /// Gets a paged result of entity keys that have dependent references. + /// + /// The set of entity keys to check for dependent references. + /// The object type identifier of the nodes. + /// The amount of items to skip. + /// The amount of items to take. + /// A paged result of entity keys that have dependent references. Task> GetPagedKeysWithDependentReferencesAsync(ISet keys, Guid nodeObjectTypeId, long skip, long take); } diff --git a/src/Umbraco.Core/Services/ITreeEntitySortingService.cs b/src/Umbraco.Core/Services/ITreeEntitySortingService.cs index fdad2411558f..dfeb179f5a0f 100644 --- a/src/Umbraco.Core/Services/ITreeEntitySortingService.cs +++ b/src/Umbraco.Core/Services/ITreeEntitySortingService.cs @@ -1,10 +1,20 @@ -using Umbraco.Cms.Core.Models.ContentEditing; +using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Cms.Core.Models.Entities; namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for sorting tree entities based on sorting models. +/// public interface ITreeEntitySortingService { + /// + /// Sorts a collection of tree entities according to the specified sorting models. + /// + /// The type of tree entity being sorted. + /// The collection of entities to sort. + /// The sorting models defining the desired sort order. + /// The sorted collection of entities. IEnumerable SortEntities(IEnumerable entities, IEnumerable sortingModels) where TTreeEntity : ITreeEntity; } diff --git a/src/Umbraco.Core/Services/IUpgradeService.cs b/src/Umbraco.Core/Services/IUpgradeService.cs index 86cefd43f8ef..ba75e190236b 100644 --- a/src/Umbraco.Core/Services/IUpgradeService.cs +++ b/src/Umbraco.Core/Services/IUpgradeService.cs @@ -2,9 +2,17 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for checking available Umbraco upgrades. +/// [Obsolete("Upgrade checks are no longer supported and this service will be removed in Umbraco 19.")] public interface IUpgradeService { + /// + /// Checks if an upgrade is available for the specified version. + /// + /// The current semantic version to check for upgrades. + /// The result of the upgrade check. [Obsolete("This method no longer has any function and will be removed in Umbraco 19.")] Task CheckUpgrade(SemVersion version); } diff --git a/src/Umbraco.Core/Services/IUsageInformationService.cs b/src/Umbraco.Core/Services/IUsageInformationService.cs index 1d4caaa5268e..76215925f9ba 100644 --- a/src/Umbraco.Core/Services/IUsageInformationService.cs +++ b/src/Umbraco.Core/Services/IUsageInformationService.cs @@ -2,7 +2,14 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Service for retrieving usage information about the Umbraco installation. +/// public interface IUsageInformationService { + /// + /// Gets detailed usage information about the Umbraco installation. + /// + /// A collection of objects, or null if unavailable. IEnumerable? GetDetailed(); } diff --git a/src/Umbraco.Core/Services/IUserDataService.cs b/src/Umbraco.Core/Services/IUserDataService.cs index db4e01f2204d..e22d96384d5d 100644 --- a/src/Umbraco.Core/Services/IUserDataService.cs +++ b/src/Umbraco.Core/Services/IUserDataService.cs @@ -5,18 +5,48 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Defines the user data service, which provides operations for managing user-specific data entries. +/// public interface IUserDataService { + /// + /// Gets user data by its unique key. + /// + /// The unique key of the user data. + /// A task that represents the asynchronous operation. The task result contains the if found; otherwise, null. public Task GetAsync(Guid key); + /// + /// Gets a paged collection of user data with optional filtering. + /// + /// The number of items to skip. + /// The number of items to take. + /// Optional filter to apply to the query. + /// A task that represents the asynchronous operation. The task result contains a of . public Task> GetAsync( int skip, int take, IUserDataFilter? filter = null); + /// + /// Creates a new user data entry. + /// + /// The to create. + /// A task that represents the asynchronous operation. The task result contains an with the created user data and operation status. public Task> CreateAsync(IUserData userData); + /// + /// Updates an existing user data entry. + /// + /// The to update. + /// A task that represents the asynchronous operation. The task result contains an with the updated user data and operation status. public Task> UpdateAsync(IUserData userData); + /// + /// Deletes a user data entry by its unique key. + /// + /// The unique key of the user data to delete. + /// A task that represents the asynchronous operation. The task result contains an with the operation status. public Task> DeleteAsync(Guid key); } diff --git a/src/Umbraco.Core/Services/IUserGroupService.cs b/src/Umbraco.Core/Services/IUserGroupService.cs index 3b8e78a4f5d3..ddd717dfc7f2 100644 --- a/src/Umbraco.Core/Services/IUserGroupService.cs +++ b/src/Umbraco.Core/Services/IUserGroupService.cs @@ -1,4 +1,4 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Services.OperationStatus; @@ -60,6 +60,11 @@ public interface IUserGroupService /// Task GetAsync(Guid key); + /// + /// Gets all UserGroups matching the specified keys. + /// + /// The keys of the UserGroups to retrieve. + /// An enumerable list of . Task> GetAsync(IEnumerable keys); /// @@ -99,6 +104,11 @@ public interface IUserGroupService /// An attempt indicating if the operation was a success as well as a more detailed . Task> DeleteAsync(ISet userGroupKeys); + /// + /// Deletes a UserGroup. + /// + /// The key of the user group to delete. + /// An attempt indicating if the operation was a success as well as a more detailed . Task> DeleteAsync(Guid userGroupKey) => DeleteAsync(new HashSet { userGroupKey }); /// @@ -109,6 +119,19 @@ public interface IUserGroupService /// An attempt indicating if the operation was a success as well as a more detailed . Task> UpdateUserGroupsOnUsersAsync(ISet userGroupKeys, ISet userKeys); + /// + /// Adds users to a user group. + /// + /// The model containing the user group and users to add. + /// The key of the user performing the operation. + /// An attempt indicating if the operation was a success as well as a more detailed . Task> AddUsersToUserGroupAsync(UsersToUserGroupManipulationModel addUsersModel, Guid performingUserKey); + + /// + /// Removes users from a user group. + /// + /// The model containing the user group and users to remove. + /// The key of the user performing the operation. + /// An attempt indicating if the operation was a success as well as a more detailed . Task> RemoveUsersFromUserGroupAsync(UsersToUserGroupManipulationModel removeUsersModel, Guid performingUserKey); } diff --git a/src/Umbraco.Core/Services/IUserService.cs b/src/Umbraco.Core/Services/IUserService.cs index 116e9301ab3e..f767483cf6fe 100644 --- a/src/Umbraco.Core/Services/IUserService.cs +++ b/src/Umbraco.Core/Services/IUserService.cs @@ -15,34 +15,36 @@ public interface IUserService : IMembershipUserService /// /// Creates a database entry for starting a new login session for a user /// - /// - /// - /// + /// The integer id of the user. + /// The IP address from which the login request originated. + /// A representing the session id. Guid CreateLoginSession(int userId, string requestingIpAddress); /// /// Validates that a user login session is valid/current and hasn't been closed /// - /// - /// - /// + /// The integer id of the user. + /// The session id to validate. + /// true if the session is valid; otherwise, false. bool ValidateLoginSession(int userId, Guid sessionId); /// /// Removes the session's validity /// - /// + /// The session id to clear. void ClearLoginSession(Guid sessionId); /// /// Removes all valid sessions for the user /// - /// + /// The integer id of the user. + /// The number of sessions that were cleared. int ClearLoginSessions(int userId); /// /// This is basically facets of UserStates key = state, value = count /// + /// A dictionary where the key is the and the value is the count of users in that state. IDictionary GetUserStates(); /// @@ -57,30 +59,107 @@ public interface IUserService : IMembershipUserService /// An attempt indicating if the operation was a success as well as a more detailed . Task> CreateAsync(Guid performingUserKey, UserCreateModel model, bool approveUser = false); + /// + /// Invites a new user to the system by sending an invitation email. + /// + /// The key of the user performing the operation. + /// The model containing the invitation details. + /// An attempt indicating if the operation was a success as well as a more detailed . Task> InviteAsync(Guid performingUserKey, UserInviteModel model); + /// + /// Verifies an invitation token for a user. + /// + /// The unique key of the user. + /// The invitation token to verify. + /// An attempt indicating if the verification was successful as well as a more detailed . Task> VerifyInviteAsync(Guid userKey, string token); + /// + /// Creates an initial password for a user after invitation verification. + /// + /// The unique key of the user. + /// The invitation token. + /// The password to set for the user. + /// An attempt indicating if the operation was a success as well as a more detailed . Task> CreateInitialPasswordAsync(Guid userKey, string token, string password); + /// + /// Updates an existing user. + /// + /// The key of the user performing the operation. + /// The model containing the updated user details. + /// An attempt containing the updated if successful, as well as a more detailed . Task> UpdateAsync(Guid performingUserKey, UserUpdateModel model); + /// + /// Sets the avatar for a user from a temporary file. + /// + /// The unique key of the user. + /// The key of the temporary file containing the avatar image. + /// A indicating the result of the operation. Task SetAvatarAsync(Guid userKey, Guid temporaryFileKey); + /// + /// Deletes multiple users by their keys. + /// + /// The key of the user performing the operation. + /// The set of user keys to delete. + /// A indicating the result of the operation. Task DeleteAsync(Guid performingUserKey, ISet keys); + /// + /// Deletes a single user by their key. + /// + /// The key of the user performing the operation. + /// The unique key of the user to delete. + /// A indicating the result of the operation. Task DeleteAsync(Guid performingUserKey, Guid key) => DeleteAsync(performingUserKey, new HashSet { key }); + /// + /// Disables multiple users by their keys. + /// + /// The key of the user performing the operation. + /// The set of user keys to disable. + /// A indicating the result of the operation. Task DisableAsync(Guid performingUserKey, ISet keys); + /// + /// Enables multiple users by their keys. + /// + /// The key of the user performing the operation. + /// The set of user keys to enable. + /// A indicating the result of the operation. Task EnableAsync(Guid performingUserKey, ISet keys); + /// + /// Unlocks users that have been locked out. + /// + /// The key of the user performing the operation. + /// The keys of the users to unlock. + /// An attempt containing the unlock result as well as a more detailed . Task> UnlockAsync(Guid performingUserKey, params Guid[] keys); + /// + /// Changes a user's password. + /// + /// The key of the user performing the operation. + /// The model containing the password change details. + /// An attempt containing the password changed result as well as a more detailed . Task> ChangePasswordAsync(Guid performingUserKey, ChangeUserPasswordModel model); + /// + /// Clears the avatar for a user. + /// + /// The unique key of the user. + /// A indicating the result of the operation. Task ClearAvatarAsync(Guid userKey); + /// + /// Gets all linked external logins for a user. + /// + /// The unique key of the user. + /// An attempt containing the collection of linked logins as well as a more detailed . Task, UserOperationStatus>> GetLinkedLoginsAsync(Guid userKey); /// @@ -92,6 +171,16 @@ public interface IUserService : IMembershipUserService /// All users that the user is allowed to see. Task?, UserOperationStatus>> GetAllAsync(Guid performingUserKey, int skip, int take) => throw new NotImplementedException(); + /// + /// Filters users based on the specified criteria. + /// + /// The key of the user performing the filter operation. + /// The filter criteria to apply. + /// The number of records to skip. Default is 0. + /// The number of records to take. Default is 100. + /// The field to order results by. Default is . + /// The direction to order results. Default is . + /// An attempt containing a paged model of filtered users as well as a more detailed . public Task, UserOperationStatus>> FilterAsync( Guid userKey, UserFilter filter, @@ -103,20 +192,20 @@ public Task, UserOperationStatus>> FilterAsync( /// /// Get paged users /// - /// - /// - /// - /// - /// - /// + /// The page index (zero-based). + /// The number of items per page. + /// The total number of records found (out). + /// The field to order by. + /// The direction to order by. + /// Optional array of user states to filter by. /// /// A filter to only include user that belong to these user groups /// /// /// A filter to only include users that do not belong to these user groups /// - /// - /// + /// Optional query filter. + /// An enumerable collection of objects. IEnumerable GetAll( long pageIndex, int pageSize, @@ -131,17 +220,17 @@ IEnumerable GetAll( /// /// Get paged users /// - /// - /// - /// - /// - /// - /// + /// The page index (zero-based). + /// The number of items per page. + /// The total number of records found (out). + /// The field to order by. + /// The direction to order by. + /// Optional array of user states to filter by. /// /// A filter to only include user that belong to these user groups /// - /// - /// + /// Optional string filter. + /// An enumerable collection of objects. IEnumerable GetAll( long pageIndex, int pageSize, @@ -184,6 +273,11 @@ IEnumerable GetAll( /// The found user, or null if nothing was found. Task GetAsync(Guid key) => Task.FromResult(GetAll(0, int.MaxValue, out _).FirstOrDefault(x=>x.Key == key)); + /// + /// Gets multiple users by their keys. + /// + /// The keys of the users to retrieve. + /// An enumerable collection of objects matching the specified keys. Task> GetAsync(IEnumerable keys) => Task.FromResult(GetAll(0, int.MaxValue, out _).Where(x => keys.Contains(x.Key))); /// @@ -254,7 +348,7 @@ IEnumerable GetAll( /// /// Get explicitly assigned permissions for groups and optional node Ids /// - /// + /// The user groups to get permissions for. /// /// Flag indicating if we want to include the default group permissions for each result if there are not explicit /// permissions set @@ -268,17 +362,19 @@ IEnumerable GetAll( /// /// User to check permissions for /// Path to check permissions for + /// An containing the calculated permissions. EntityPermissionSet GetPermissionsForPath(IUser? user, string? path); /// /// Gets the permissions for the provided groups and path /// - /// + /// The user groups to get permissions for. /// Path to check permissions for /// /// Flag indicating if we want to include the default group permissions for each result if there are not explicit /// permissions set /// + /// An containing the calculated permissions. EntityPermissionSet GetPermissionsForPath(IUserGroup[] groups, string path, bool fallbackToDefaultPermissions = false); /// @@ -300,7 +396,7 @@ IEnumerable GetAll( /// Assigns the same permission set for a single user group to any number of entities /// /// Id of the group - /// + /// The permission to assign. /// Specify the nodes to replace permissions for void AssignUserGroupPermission(int groupId, string permission, params int[] entityIds); @@ -327,6 +423,7 @@ IEnumerable GetAll( /// /// The unique key of the user. /// The reset password token. + /// An attempt indicating if the verification was successful as well as a more detailed . Task> VerifyPasswordResetAsync(Guid userKey, string token); /// @@ -335,23 +432,59 @@ IEnumerable GetAll( /// The unique key of the user. /// The reset password token. /// The new password of the user. + /// An attempt containing the password changed result as well as a more detailed . Task> ResetPasswordAsync(Guid userKey, string token, string password); /// /// Sends an email with a link to reset user's password. /// /// The email address of the user. + /// An attempt indicating if the operation was successful as well as a more detailed . Task> SendResetPasswordEmailAsync(string userEmail); + /// + /// Resends an invitation email to a user. + /// + /// The key of the user performing the operation. + /// The model containing the resend invitation details. + /// An attempt containing the invitation result as well as a more detailed . Task> ResendInvitationAsync(Guid performingUserKey, UserResendInviteModel model); + /// + /// Resets a user's password without requiring a token. + /// + /// The key of the user performing the operation. + /// The unique key of the user whose password will be reset. + /// An attempt containing the password changed result as well as a more detailed . Task> ResetPasswordAsync(Guid performingUserKey, Guid userKey); + /// + /// Adds a client ID to a user for OAuth client credentials authentication. + /// + /// The unique key of the user. + /// The client ID to add. + /// A indicating the result of the operation. Task AddClientIdAsync(Guid userKey, string clientId); + /// + /// Removes a client ID from a user. + /// + /// The unique key of the user. + /// The client ID to remove. + /// true if the client ID was successfully removed; otherwise, false. Task RemoveClientIdAsync(Guid userKey, string clientId); + /// + /// Finds a user by their client ID. + /// + /// The client ID to search for. + /// The associated with the client ID, or null if not found. Task FindByClientIdAsync(string clientId); + /// + /// Gets all client IDs associated with a user. + /// + /// The unique key of the user. + /// An enumerable collection of client IDs. Task> GetClientIdsAsync(Guid userKey); } diff --git a/src/Umbraco.Core/Services/IWebProfilerService.cs b/src/Umbraco.Core/Services/IWebProfilerService.cs index 5366c8781d25..eac7c6e276d9 100644 --- a/src/Umbraco.Core/Services/IWebProfilerService.cs +++ b/src/Umbraco.Core/Services/IWebProfilerService.cs @@ -2,8 +2,21 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Service for managing the web profiler (MiniProfiler) status. +/// public interface IWebProfilerService { + /// + /// Gets the current status of the web profiler. + /// + /// An containing the profiler enabled status and operation status. Task> GetStatus(); + + /// + /// Sets the status of the web profiler. + /// + /// A value indicating whether the profiler should be enabled. + /// An containing the new profiler status and operation status. Task> SetStatus(bool status); } diff --git a/src/Umbraco.Core/Services/IWebhookFiringService.cs b/src/Umbraco.Core/Services/IWebhookFiringService.cs index 47d01da4ec7c..d985ac7a5df9 100644 --- a/src/Umbraco.Core/Services/IWebhookFiringService.cs +++ b/src/Umbraco.Core/Services/IWebhookFiringService.cs @@ -1,8 +1,19 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Service for firing webhooks in response to events. +/// public interface IWebhookFiringService { + /// + /// Fires a webhook asynchronously. + /// + /// The to fire. + /// The alias of the event that triggered the webhook. + /// The payload to send with the webhook request. + /// A cancellation token to cancel the operation. + /// A task that represents the asynchronous operation. Task FireAsync(IWebhook webhook, string eventAlias, object? payload, CancellationToken cancellationToken); } diff --git a/src/Umbraco.Core/Services/IWebhookLogFactory.cs b/src/Umbraco.Core/Services/IWebhookLogFactory.cs index 87b43ab5ab50..68f5d489acbf 100644 --- a/src/Umbraco.Core/Services/IWebhookLogFactory.cs +++ b/src/Umbraco.Core/Services/IWebhookLogFactory.cs @@ -1,9 +1,23 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Factory for creating webhook log entries. +/// public interface IWebhookLogFactory { + /// + /// Creates a new entry based on the webhook request and response. + /// + /// The alias of the event that triggered the webhook. + /// The HTTP request message sent to the webhook endpoint. + /// The HTTP response message received, or null if no response was received. + /// The number of retry attempts made. + /// The exception that occurred during the request, or null if successful. + /// The that was fired. + /// A cancellation token to cancel the operation. + /// A task that represents the asynchronous operation, containing the created . Task CreateAsync( string eventAlias, HttpRequestMessage requestMessage, diff --git a/src/Umbraco.Core/Services/IWebhookLogService.cs b/src/Umbraco.Core/Services/IWebhookLogService.cs index ee404e38e446..b5299777d8f8 100644 --- a/src/Umbraco.Core/Services/IWebhookLogService.cs +++ b/src/Umbraco.Core/Services/IWebhookLogService.cs @@ -2,12 +2,33 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Service for managing webhook log entries. +/// public interface IWebhookLogService { + /// + /// Creates a new webhook log entry. + /// + /// The to create. + /// A task that represents the asynchronous operation, containing the created . Task CreateAsync(WebhookLog webhookLog); + /// + /// Gets a paged collection of all webhook logs. + /// + /// The number of items to skip. + /// The number of items to take. + /// A task that represents the asynchronous operation, containing a paged model of objects. Task> Get(int skip = 0, int take = int.MaxValue); + /// + /// Gets a paged collection of webhook logs for a specific webhook. + /// + /// The unique key of the webhook. + /// The number of items to skip. + /// The number of items to take. + /// A task that represents the asynchronous operation, containing a paged model of objects. // TODO (V16): Remove the default implementation on this method. async Task> Get(Guid webhookKey, int skip = 0, int take = int.MaxValue) { diff --git a/src/Umbraco.Core/Services/IWebhookRequestService.cs b/src/Umbraco.Core/Services/IWebhookRequestService.cs index b3b6396b01bc..f24109fe138e 100644 --- a/src/Umbraco.Core/Services/IWebhookRequestService.cs +++ b/src/Umbraco.Core/Services/IWebhookRequestService.cs @@ -1,7 +1,14 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing webhook requests. +/// +/// +/// Webhook requests are queued when events occur and are processed asynchronously +/// to send HTTP callbacks to configured webhook endpoints. +/// public interface IWebhookRequestService { /// diff --git a/src/Umbraco.Core/Services/IWebhookService.cs b/src/Umbraco.Core/Services/IWebhookService.cs index 8d6ade4b7652..500cd4bb4fb2 100644 --- a/src/Umbraco.Core/Services/IWebhookService.cs +++ b/src/Umbraco.Core/Services/IWebhookService.cs @@ -3,6 +3,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Service for managing webhooks. +/// public interface IWebhookService { /// diff --git a/src/Umbraco.Core/Services/IdKeyMap.cs b/src/Umbraco.Core/Services/IdKeyMap.cs index 65aa4c5d2574..a5ec89246cac 100644 --- a/src/Umbraco.Core/Services/IdKeyMap.cs +++ b/src/Umbraco.Core/Services/IdKeyMap.cs @@ -5,6 +5,25 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides bidirectional mapping between integer IDs and GUIDs (keys) for Umbraco entities. +/// +/// +/// +/// This class provides an efficient caching layer for ID/Key lookups. The cache assumes that +/// the id/guid map is unique; that is, if an id and a guid map to each other, then the id +/// will never map to another guid, and the guid will never map to another id. +/// +/// +/// Cache is cleared by MediaCacheRefresher, UnpublishedPageCacheRefresher, and other +/// refreshers - because id/guid map is unique, we only clear to avoid leaking memory, +/// as we don't risk caching obsolete values - and only when actually deleting. +/// +/// +/// External mappers can be registered (e.g., from NuCache) to provide lookups from +/// alternative sources before hitting the database. +/// +/// public class IdKeyMap : IIdKeyMap, IDisposable { private readonly ICoreScopeProvider _scopeProvider; @@ -41,6 +60,11 @@ public class IdKeyMap : IIdKeyMap, IDisposable _dictionary = new(); + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The repository for ID/Key mapping data access. public IdKeyMap(ICoreScopeProvider scopeProvider, IIdKeyMapRepository idKeyMapRepository) { _scopeProvider = scopeProvider; @@ -49,6 +73,7 @@ public IdKeyMap(ICoreScopeProvider scopeProvider, IIdKeyMapRepository idKeyMapRe private bool _disposedValue; + /// public void SetMapper(UmbracoObjectTypes umbracoObjectType, Func id2key, Func key2id) => _dictionary[umbracoObjectType] = (id2key, key2id); @@ -113,6 +138,7 @@ private Attempt PopulateAndGetKeyForId(int id, UmbracoObjectTypes umbracoO } #endif + /// public Attempt GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType) { if (key == Constants.System.RecycleBinContentKey && umbracoObjectType == UmbracoObjectTypes.Document) @@ -198,6 +224,11 @@ public Attempt GetIdForKey(Guid key, UmbracoObjectTypes umbracoObjectType) return Attempt.Succeed(val.Value); } + /// + /// Populates the cache with multiple ID/Key pairs for a specific object type. + /// + /// The collection of ID/Key pairs to cache. + /// The Umbraco object type for the pairs. internal void Populate(IEnumerable<(int id, Guid key)> pairs, UmbracoObjectTypes umbracoObjectType) { try @@ -218,6 +249,7 @@ internal void Populate(IEnumerable<(int id, Guid key)> pairs, UmbracoObjectTypes } } + /// public Attempt GetIdForUdi(Udi udi) { var guidUdi = udi as GuidUdi; @@ -230,6 +262,7 @@ public Attempt GetIdForUdi(Udi udi) return GetIdForKey(guidUdi.Guid, umbracoType); } + /// public Attempt GetUdiForId(int id, UmbracoObjectTypes umbracoObjectType) { Attempt keyAttempt = GetKeyForId(id, umbracoObjectType); @@ -240,6 +273,7 @@ public Attempt GetIdForUdi(Udi udi) : Attempt.Fail(); } + /// public Attempt GetKeyForId(int id, UmbracoObjectTypes umbracoObjectType) { if (id == Constants.System.RecycleBinContent && umbracoObjectType == UmbracoObjectTypes.Document) @@ -325,8 +359,10 @@ public Attempt GetKeyForId(int id, UmbracoObjectTypes umbracoObjectType) return Attempt.Succeed(val.Value); } - // invoked on UnpublishedPageCacheRefresher.RefreshAll - // anything else will use the id-specific overloads + /// + /// + /// Invoked on UnpublishedPageCacheRefresher.RefreshAll. For specific items, use the ID or Key specific overloads. + /// public void ClearCache() { try @@ -344,6 +380,7 @@ public void ClearCache() } } + /// public void ClearCache(int id) { try @@ -366,6 +403,7 @@ public void ClearCache(int id) } } + /// public void ClearCache(Guid key) { try @@ -388,6 +426,10 @@ public void ClearCache(Guid key) } } + /// + /// Releases the unmanaged resources used by the and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (!_disposedValue) @@ -403,16 +445,32 @@ protected virtual void Dispose(bool disposing) // ReSharper restore ClassNeverInstantiated.Local // ReSharper restore UnusedAutoPropertyAccessor.Local + + /// + /// Represents an identifier value with its associated Umbraco object type. + /// + /// The type of the identifier (int or Guid). private struct TypedId { + /// + /// Initializes a new instance of the struct. + /// + /// The identifier value. + /// The Umbraco object type. public TypedId(T id, UmbracoObjectTypes umbracoObjectType) { UmbracoObjectType = umbracoObjectType; Id = id; } + /// + /// Gets the Umbraco object type for this identifier. + /// public UmbracoObjectTypes UmbracoObjectType { get; } + /// + /// Gets the identifier value. + /// public T Id { get; } } @@ -427,6 +485,7 @@ private sealed class TypedIdDto public Guid NodeObjectType { get; set; } } + /// public void Dispose() => // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method diff --git a/src/Umbraco.Core/Services/ImportExport/ContentTypeImportService.cs b/src/Umbraco.Core/Services/ImportExport/ContentTypeImportService.cs index c1f97d8d40a4..8113974d3dc5 100644 --- a/src/Umbraco.Core/Services/ImportExport/ContentTypeImportService.cs +++ b/src/Umbraco.Core/Services/ImportExport/ContentTypeImportService.cs @@ -6,6 +6,9 @@ namespace Umbraco.Cms.Core.Services.ImportExport; +/// +/// Service implementation for importing content types (document types) from XML files. +/// public class ContentTypeImportService : IContentTypeImportService { private readonly IPackageDataInstallation _packageDataInstallation; @@ -14,6 +17,14 @@ public class ContentTypeImportService : IContentTypeImportService private readonly ICoreScopeProvider _coreScopeProvider; private readonly IUserIdKeyResolver _userIdKeyResolver; + /// + /// Initializes a new instance of the class. + /// + /// The package data installation service for importing document types. + /// The entity service for checking existence of entities. + /// The service for loading XML from temporary files. + /// The core scope provider for creating database scopes. + /// The resolver for converting user keys to user IDs. public ContentTypeImportService( IPackageDataInstallation packageDataInstallation, IEntityService entityService, @@ -29,12 +40,19 @@ public ContentTypeImportService( } /// - /// Imports the contentType + /// Imports a content type from a temporary file containing XML data. /// - /// - /// - /// the id of the contentType to overwrite, null if a new contentType should be created - /// + /// The unique identifier of the temporary file containing the content type XML definition. + /// The unique key of the user performing the import operation. + /// + /// Optional. The unique identifier of an existing content type to overwrite. + /// When null, a new content type will be created. + /// + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the imported on success, or null with an appropriate + /// on failure. + /// public async Task> Import( Guid temporaryFileId, Guid userKey, diff --git a/src/Umbraco.Core/Services/ImportExport/IContentTypeImportService.cs b/src/Umbraco.Core/Services/ImportExport/IContentTypeImportService.cs index 6df7c36d2476..a5b8374b23f8 100644 --- a/src/Umbraco.Core/Services/ImportExport/IContentTypeImportService.cs +++ b/src/Umbraco.Core/Services/ImportExport/IContentTypeImportService.cs @@ -3,7 +3,24 @@ namespace Umbraco.Cms.Core.Services.ImportExport; +/// +/// Service for importing content types (document types) from XML files. +/// public interface IContentTypeImportService { + /// + /// Imports a content type from a temporary file containing XML data. + /// + /// The unique identifier of the temporary file containing the content type XML definition. + /// The unique key of the user performing the import operation. + /// + /// Optional. The unique identifier of an existing content type to update. + /// When null, a new content type will be created. + /// + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the imported on success, or null with an appropriate + /// on failure. + /// Task> Import(Guid temporaryFileId, Guid userKey, Guid? contentTypeId = null); } diff --git a/src/Umbraco.Core/Services/ImportExport/IMediaTypeImportService.cs b/src/Umbraco.Core/Services/ImportExport/IMediaTypeImportService.cs index a23e07dfc88b..84162ff65bdf 100644 --- a/src/Umbraco.Core/Services/ImportExport/IMediaTypeImportService.cs +++ b/src/Umbraco.Core/Services/ImportExport/IMediaTypeImportService.cs @@ -3,8 +3,25 @@ namespace Umbraco.Cms.Core.Services.ImportExport; +/// +/// Service for importing media types from XML files. +/// public interface IMediaTypeImportService { + /// + /// Imports a media type from a temporary file containing XML data. + /// + /// The unique identifier of the temporary file containing the media type XML definition. + /// The unique key of the user performing the import operation. + /// + /// Optional. The unique identifier of an existing media type to update. + /// When null, a new media type will be created. + /// + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the imported on success, or null with an appropriate + /// on failure. + /// Task> Import( Guid temporaryFileId, Guid userKey, diff --git a/src/Umbraco.Core/Services/ImportExport/IMemberTypeImportService.cs b/src/Umbraco.Core/Services/ImportExport/IMemberTypeImportService.cs index 2a8e279a2c2a..905adcb3aa66 100644 --- a/src/Umbraco.Core/Services/ImportExport/IMemberTypeImportService.cs +++ b/src/Umbraco.Core/Services/ImportExport/IMemberTypeImportService.cs @@ -3,8 +3,25 @@ namespace Umbraco.Cms.Core.Services.ImportExport; +/// +/// Service for importing member types from XML files. +/// public interface IMemberTypeImportService { + /// + /// Imports a member type from a temporary file containing XML data. + /// + /// The unique identifier of the temporary file containing the member type XML definition. + /// The unique key of the user performing the import operation. + /// + /// Optional. The unique identifier of an existing member type to update. + /// When null, a new member type will be created. + /// + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the imported on success, or null with an appropriate + /// on failure. + /// Task> Import( Guid temporaryFileId, Guid userKey, diff --git a/src/Umbraco.Core/Services/ImportExport/ITemporaryFileToXmlImportService.cs b/src/Umbraco.Core/Services/ImportExport/ITemporaryFileToXmlImportService.cs index 5f2bf25c6211..5e946e69dc1b 100644 --- a/src/Umbraco.Core/Services/ImportExport/ITemporaryFileToXmlImportService.cs +++ b/src/Umbraco.Core/Services/ImportExport/ITemporaryFileToXmlImportService.cs @@ -5,15 +5,58 @@ namespace Umbraco.Cms.Core.Services.ImportExport; +/// +/// Service for loading and analyzing XML import data from temporary files. +/// +/// +/// This service provides functionality to convert temporary files containing XML definitions +/// into objects for further processing during content type imports. +/// public interface ITemporaryFileToXmlImportService { + /// + /// Loads the XML content from a temporary file and returns it as an . + /// + /// The unique identifier of the temporary file to load. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the loaded on success, or null with an appropriate + /// on failure. + /// + /// + /// Only if this method is called within a scope, the temporary file will be cleaned up if that scope completes. + /// Task> LoadXElementFromTemporaryFileAsync( Guid temporaryFileId); + /// + /// Determines the Umbraco entity type from an XML element. + /// + /// The XML element to analyze. + /// + /// An containing the value + /// on success, or a failed attempt if the entity type could not be determined. + /// Attempt GetEntityType(XElement entityElement); + /// + /// Analyzes a temporary file containing XML import data and returns information about the entity that would be imported. + /// + /// The unique identifier of the temporary file to analyze. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with an on success containing the entity type, alias, and key; + /// or null with an appropriate on failure. + /// + /// + /// As this method does not persist anything, no scope is created and the temporary file is not cleaned up. + /// Task> AnalyzeAsync( Guid temporaryFileId); + /// + /// Registers the temporary file for cleanup when the current scope completes successfully. + /// + /// The unique identifier of the temporary file to clean up. void CleanupFileIfScopeCompletes(Guid temporaryFileId); } diff --git a/src/Umbraco.Core/Services/ImportExport/MediaTypeImportService.cs b/src/Umbraco.Core/Services/ImportExport/MediaTypeImportService.cs index 09fdc0cb2706..ecc68290436c 100644 --- a/src/Umbraco.Core/Services/ImportExport/MediaTypeImportService.cs +++ b/src/Umbraco.Core/Services/ImportExport/MediaTypeImportService.cs @@ -6,6 +6,9 @@ namespace Umbraco.Cms.Core.Services.ImportExport; +/// +/// Service implementation for importing media types from XML files. +/// public class MediaTypeImportService : IMediaTypeImportService { private readonly IPackageDataInstallation _packageDataInstallation; @@ -14,6 +17,14 @@ public class MediaTypeImportService : IMediaTypeImportService private readonly ICoreScopeProvider _coreScopeProvider; private readonly IUserIdKeyResolver _userIdKeyResolver; + /// + /// Initializes a new instance of the class. + /// + /// The package data installation service for importing media types. + /// The entity service for checking existence of entities. + /// The service for loading XML from temporary files. + /// The core scope provider for creating database scopes. + /// The resolver for converting user keys to user IDs. public MediaTypeImportService( IPackageDataInstallation packageDataInstallation, IEntityService entityService, @@ -28,6 +39,7 @@ public MediaTypeImportService( _userIdKeyResolver = userIdKeyResolver; } + /// public async Task> Import( Guid temporaryFileId, Guid userKey, diff --git a/src/Umbraco.Core/Services/ImportExport/MemberTypeImportService.cs b/src/Umbraco.Core/Services/ImportExport/MemberTypeImportService.cs index c4ae564e11d9..997229e04f6e 100644 --- a/src/Umbraco.Core/Services/ImportExport/MemberTypeImportService.cs +++ b/src/Umbraco.Core/Services/ImportExport/MemberTypeImportService.cs @@ -6,6 +6,9 @@ namespace Umbraco.Cms.Core.Services.ImportExport; +/// +/// Service implementation for importing member types from XML files. +/// public class MemberTypeImportService : IMemberTypeImportService { private readonly IPackageDataInstallation _packageDataInstallation; @@ -14,6 +17,14 @@ public class MemberTypeImportService : IMemberTypeImportService private readonly ICoreScopeProvider _coreScopeProvider; private readonly IUserIdKeyResolver _userIdKeyResolver; + /// + /// Initializes a new instance of the class. + /// + /// The package data installation service for importing member types. + /// The entity service for checking existence of entities. + /// The service for loading XML from temporary files. + /// The core scope provider for creating database scopes. + /// The resolver for converting user keys to user IDs. public MemberTypeImportService( IPackageDataInstallation packageDataInstallation, IEntityService entityService, @@ -28,6 +39,7 @@ public MemberTypeImportService( _userIdKeyResolver = userIdKeyResolver; } + /// public async Task> Import( Guid temporaryFileId, Guid userKey, diff --git a/src/Umbraco.Core/Services/ImportExport/TemporaryFileToXmlImportService.cs b/src/Umbraco.Core/Services/ImportExport/TemporaryFileToXmlImportService.cs index a8aa8a1542f0..9af71cbc022e 100644 --- a/src/Umbraco.Core/Services/ImportExport/TemporaryFileToXmlImportService.cs +++ b/src/Umbraco.Core/Services/ImportExport/TemporaryFileToXmlImportService.cs @@ -9,12 +9,25 @@ namespace Umbraco.Cms.Core.Services.ImportExport; +/// +/// Service implementation for loading and analyzing XML import data from temporary files. +/// +/// +/// This service provides functionality to convert temporary files containing XML definitions +/// into objects for further processing during content type imports. +/// public class TemporaryFileToXmlImportService : ITemporaryFileToXmlImportService { private readonly ITemporaryFileService _temporaryFileService; private readonly IPackageDataInstallation _packageDataInstallation; private readonly ICoreScopeProvider _coreScopeProvider; + /// + /// Initializes a new instance of the class. + /// + /// The service for managing temporary files. + /// The package data installation service for extracting entity information from XML. + /// The core scope provider for creating database scopes. public TemporaryFileToXmlImportService( ITemporaryFileService temporaryFileService, IPackageDataInstallation packageDataInstallation, @@ -25,9 +38,18 @@ public TemporaryFileToXmlImportService( _coreScopeProvider = coreScopeProvider; } - /// - /// Only if this method is called within a scope, the temporary file will be cleaned up if that scope completes. - /// + /// + /// Loads the XML content from a temporary file and returns it as an . + /// + /// The unique identifier of the temporary file to load. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with the loaded on success, or null with an appropriate + /// on failure. + /// + /// + /// Only if this method is called within a scope, the temporary file will be cleaned up if that scope completes. + /// public async Task> LoadXElementFromTemporaryFileAsync( Guid temporaryFileId) { @@ -49,9 +71,18 @@ public TemporaryFileToXmlImportService( document.Root); } + /// public void CleanupFileIfScopeCompletes(Guid temporaryFileId) => _temporaryFileService.EnlistDeleteIfScopeCompletes(temporaryFileId, _coreScopeProvider); + /// + /// Determines the Umbraco entity type from an XML element. + /// + /// The XML element to analyze. + /// + /// An containing the value + /// on success, or a failed attempt if the entity type could not be determined. + /// public Attempt GetEntityType(XElement entityElement) { var entityType = entityElement.Name.ToString(); @@ -68,10 +99,21 @@ public Attempt GetEntityType(XElement entityElement) } /// - /// Reads the file trough the use of and returns basic information regarding the entity that would be imported if this file was processed by - /// or . + /// Analyzes a temporary file containing XML import data and returns information about the entity that would be imported. /// - /// As this method does not persist anything, no scope is created and the temporary file is not cleaned up, see remark in . + /// The unique identifier of the temporary file to analyze. + /// + /// A task that represents the asynchronous operation. The task result contains an + /// with an on success containing the entity type, alias, and key; + /// or null with an appropriate on failure. + /// + /// + /// As this method does not persist anything, no scope is created and the temporary file is not cleaned up. + /// This method reads the file through the use of and returns + /// basic information regarding the entity that would be imported if this file was processed by + /// or + /// . + /// public async Task> AnalyzeAsync( Guid temporaryFileId) { diff --git a/src/Umbraco.Core/Services/InstallationService.cs b/src/Umbraco.Core/Services/InstallationService.cs index 00bd00aa91e4..bbaecc122595 100644 --- a/src/Umbraco.Core/Services/InstallationService.cs +++ b/src/Umbraco.Core/Services/InstallationService.cs @@ -2,13 +2,21 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Service for logging installation information. +/// public class InstallationService : IInstallationService { private readonly IInstallationRepository _installationRepository; + /// + /// Initializes a new instance of the class. + /// + /// The installation repository. public InstallationService(IInstallationRepository installationRepository) => _installationRepository = installationRepository; + /// public async Task LogInstall(InstallLog installLog) => await _installationRepository.SaveInstallLogAsync(installLog); } diff --git a/src/Umbraco.Core/Services/Installer/IInstallService.cs b/src/Umbraco.Core/Services/Installer/IInstallService.cs index 5b0630d6e139..e878e2c666b3 100644 --- a/src/Umbraco.Core/Services/Installer/IInstallService.cs +++ b/src/Umbraco.Core/Services/Installer/IInstallService.cs @@ -1,15 +1,21 @@ -using Umbraco.Cms.Core.Installer; +using Umbraco.Cms.Core.Installer; using Umbraco.Cms.Core.Models.Installer; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services.Installer; +/// +/// Provides functionality for performing a fresh installation of Umbraco CMS. +/// public interface IInstallService { /// /// Runs all the steps in the , installing Umbraco /// /// InstallData containing the required data used to install - /// + /// + /// An containing the on success, + /// or an indicating the failure reason. + /// Task> InstallAsync(InstallData model); } diff --git a/src/Umbraco.Core/Services/Installer/IUpgradeService.cs b/src/Umbraco.Core/Services/Installer/IUpgradeService.cs index e92ca7e97583..7dff60c71c1e 100644 --- a/src/Umbraco.Core/Services/Installer/IUpgradeService.cs +++ b/src/Umbraco.Core/Services/Installer/IUpgradeService.cs @@ -1,13 +1,20 @@ -using Umbraco.Cms.Core.Installer; +using Umbraco.Cms.Core.Installer; using Umbraco.Cms.Core.Models.Installer; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services.Installer; +/// +/// Provides functionality for upgrading an existing Umbraco CMS installation to a newer version. +/// public interface IUpgradeService { /// /// Runs all the steps in the , upgrading Umbraco. /// + /// + /// An containing the on success, + /// or an indicating the failure reason. + /// Task> UpgradeAsync(); } diff --git a/src/Umbraco.Core/Services/Installer/InstallService.cs b/src/Umbraco.Core/Services/Installer/InstallService.cs index 026cb7f98dec..3deca1092808 100644 --- a/src/Umbraco.Core/Services/Installer/InstallService.cs +++ b/src/Umbraco.Core/Services/Installer/InstallService.cs @@ -1,16 +1,30 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Installer; using Umbraco.Cms.Core.Models.Installer; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services.Installer; +/// +/// Provides functionality for performing a fresh installation of Umbraco CMS. +/// +/// +/// This service orchestrates the installation process by executing all registered install steps +/// in the . It validates that the runtime is in the correct +/// state before proceeding with installation. +/// public class InstallService : IInstallService { private readonly ILogger _logger; private readonly NewInstallStepCollection _installSteps; private readonly IRuntimeState _runtimeState; + /// + /// Initializes a new instance of the class. + /// + /// The logger for recording installation progress and errors. + /// The collection of installation steps to execute. + /// The runtime state used to verify the system is ready for installation. public InstallService( ILogger logger, NewInstallStepCollection installSteps, diff --git a/src/Umbraco.Core/Services/Installer/UpgradeService.cs b/src/Umbraco.Core/Services/Installer/UpgradeService.cs index 1412eab63e67..cdf0dcfb7c9e 100644 --- a/src/Umbraco.Core/Services/Installer/UpgradeService.cs +++ b/src/Umbraco.Core/Services/Installer/UpgradeService.cs @@ -1,16 +1,30 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Installer; using Umbraco.Cms.Core.Models.Installer; using Umbraco.Cms.Core.Services.OperationStatus; namespace Umbraco.Cms.Core.Services.Installer; +/// +/// Provides functionality for upgrading an existing Umbraco CMS installation to a newer version. +/// +/// +/// This service orchestrates the upgrade process by executing all registered upgrade steps +/// in the . It validates that the runtime is in the correct +/// state before proceeding with the upgrade. +/// public class UpgradeService : IUpgradeService { private readonly UpgradeStepCollection _upgradeSteps; private readonly IRuntimeState _runtimeState; private readonly ILogger _logger; + /// + /// Initializes a new instance of the class. + /// + /// The collection of upgrade steps to execute. + /// The runtime state used to verify the system is ready for upgrade. + /// The logger for recording upgrade progress and errors. public UpgradeService( UpgradeStepCollection upgradeSteps, IRuntimeState runtimeState, diff --git a/src/Umbraco.Core/Services/KeyValueService.cs b/src/Umbraco.Core/Services/KeyValueService.cs index 3f81fa82a1d6..a5b847fa47a3 100644 --- a/src/Umbraco.Core/Services/KeyValueService.cs +++ b/src/Umbraco.Core/Services/KeyValueService.cs @@ -4,11 +4,19 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides key-value storage operations for persisting simple settings. +/// internal sealed class KeyValueService : IKeyValueService { private readonly IKeyValueRepository _repository; private readonly ICoreScopeProvider _scopeProvider; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The key-value repository. public KeyValueService(ICoreScopeProvider scopeProvider, IKeyValueRepository repository) { _scopeProvider = scopeProvider; diff --git a/src/Umbraco.Core/Services/LanguageService.cs b/src/Umbraco.Core/Services/LanguageService.cs index 96d4417fc494..1bf3499f79f7 100644 --- a/src/Umbraco.Core/Services/LanguageService.cs +++ b/src/Umbraco.Core/Services/LanguageService.cs @@ -9,6 +9,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Service for managing languages in Umbraco, including CRUD operations and validation. +/// internal sealed class LanguageService : RepositoryService, ILanguageService { private readonly ILanguageRepository _languageRepository; @@ -16,6 +19,16 @@ internal sealed class LanguageService : RepositoryService, ILanguageService private readonly IUserIdKeyResolver _userIdKeyResolver; private readonly IIsoCodeValidator _isoCodeValidator; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The language repository. + /// The audit service. + /// The user ID key resolver. + /// The ISO code validator. public LanguageService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -68,6 +81,7 @@ public Task> GetAllAsync() } } + /// public Task GetIsoCodesByIdsAsync(ICollection ids) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete:true); @@ -75,6 +89,7 @@ public Task GetIsoCodesByIdsAsync(ICollection ids) return Task.FromResult(_languageRepository.GetIsoCodesByIds(ids, throwOnNotFound: true)); } + /// public async Task> GetMultipleAsync(IEnumerable isoCodes) => (await GetAllAsync()).Where(x => isoCodes.Contains(x.IsoCode)); /// diff --git a/src/Umbraco.Core/Services/LocalizationService.cs b/src/Umbraco.Core/Services/LocalizationService.cs index 0e0d2ad922fd..92dde1cd9d15 100644 --- a/src/Umbraco.Core/Services/LocalizationService.cs +++ b/src/Umbraco.Core/Services/LocalizationService.cs @@ -23,6 +23,14 @@ internal class LocalizationService : RepositoryService, ILocalizationService private readonly IDictionaryItemService _dictionaryItemService; private readonly IUserIdKeyResolver _userIdKeyResolver; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The dictionary repository. + /// The language repository. [Obsolete("Please use constructor with language, dictionary and user services. Will be removed in V15")] public LocalizationService( ICoreScopeProvider provider, @@ -42,6 +50,17 @@ public LocalizationService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The logger factory. + /// The event messages factory. + /// The dictionary repository. + /// The language repository. + /// The language service. + /// The dictionary item service. + /// The user ID key resolver. [Obsolete("Please use ILanguageService and IDictionaryItemService for localization. Will be removed in V15.")] public LocalizationService( ICoreScopeProvider provider, @@ -340,6 +359,10 @@ public void Delete(ILanguage language, int userId = Constants.Security.SuperUser _languageService.DeleteAsync(language.IsoCode, currentUserKey).GetAwaiter().GetResult(); } + /// + /// Gets the dictionary item key map containing all dictionary item keys and their corresponding GUIDs. + /// + /// A dictionary mapping dictionary item keys to their GUIDs. [Obsolete("Please use IDictionaryItemService for dictionary item operations. Will be removed in V15.")] public Dictionary GetDictionaryItemKeyMap() { diff --git a/src/Umbraco.Core/Services/LocalizedTextService.cs b/src/Umbraco.Core/Services/LocalizedTextService.cs index 343224a6e913..56c3bf180e97 100644 --- a/src/Umbraco.Core/Services/LocalizedTextService.cs +++ b/src/Umbraco.Core/Services/LocalizedTextService.cs @@ -17,10 +17,10 @@ private readonly Lazy>>> _noAreaDictionarySourceLazy; /// - /// Initializes with a file sources instance + /// Initializes a new instance of the class with file sources. /// - /// - /// + /// The lazy-loaded file sources for localized text. + /// The logger instance. public LocalizedTextService( Lazy fileSources, ILogger logger) @@ -41,10 +41,10 @@ public LocalizedTextService( } /// - /// Initializes with an XML source + /// Initializes a new instance of the class with an XML source. /// - /// - /// + /// A dictionary mapping cultures to lazy-loaded XML documents containing translations. + /// The logger instance. public LocalizedTextService( IDictionary> source, ILogger logger) @@ -64,12 +64,12 @@ public LocalizedTextService( XmlSourceToNoAreaDictionary(source)); } - /// - /// Initializes with a source of a dictionary of culture -> areas -> sub dictionary of keys/values - /// - /// - /// - public LocalizedTextService( + /// + /// Initializes a new instance of the class with a dictionary source. + /// + /// A dictionary mapping cultures to lazy-loaded area dictionaries containing key/value translations. + /// The logger instance. + public LocalizedTextService( IDictionary>>> source, ILogger logger) { @@ -101,6 +101,7 @@ public LocalizedTextService( private IDictionary>> NoAreaDictionarySource => _noAreaDictionarySourceLazy.Value; + /// public string Localize(string? area, string? alias, CultureInfo? culture, IDictionary? tokens = null) { if (culture == null) @@ -227,6 +228,13 @@ public IDictionary> GetAllStoredValuesByArea return valueForCulture.Value; } + /// + /// Localizes a key by parsing the area and alias from the key string. + /// + /// The key in the format "area/alias" or just "alias". + /// The culture to localize for. + /// Optional token replacements. This can be null. + /// The localized string, or the key wrapped in brackets if not found. public string Localize(string key, CultureInfo culture, IDictionary? tokens = null) { if (culture == null) diff --git a/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs b/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs index 32b52565d4cb..97158acdada4 100644 --- a/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs +++ b/src/Umbraco.Core/Services/LocalizedTextServiceExtensions.cs @@ -12,10 +12,25 @@ namespace Umbraco.Extensions; /// public static class LocalizedTextServiceExtensions { + /// + /// Localizes a key using an enum value and the current thread culture. + /// + /// The enum type. + /// The localized text service. + /// The area/category of the localization key. + /// The enum value representing the localization key. + /// The localized string. public static string Localize(this ILocalizedTextService manager, string area, T key) where T : Enum => manager.Localize(area, key.ToString(), Thread.CurrentThread.CurrentUICulture); + /// + /// Localizes a key using the current thread culture. + /// + /// The localized text service. + /// The area/category of the localization key. + /// The alias/key to localize. + /// The localized string. public static string Localize(this ILocalizedTextService manager, string? area, string? alias) => manager.Localize(area, alias, Thread.CurrentThread.CurrentUICulture); @@ -42,6 +57,13 @@ public static string Localize(this ILocalizedTextService manager, string? area, public static string Localize(this ILocalizedTextService manager, string area, string alias, CultureInfo culture, string?[] tokens) => manager.Localize(area, alias, culture, ConvertToDictionaryVars(tokens)); + /// + /// Translates text using the Umbraco dictionary, falling back to localized text service. + /// + /// The localized text service. + /// The culture dictionary. + /// The text to translate. If it starts with '#', it will be looked up in the dictionary. + /// The translated text, or the original text if no translation is found. public static string? UmbracoDictionaryTranslate( this ILocalizedTextService manager, ICultureDictionary cultureDictionary, diff --git a/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs b/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs index e1b9d7e1af66..c321aa063564 100644 --- a/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs +++ b/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs @@ -28,11 +28,16 @@ public class LocalizedTextServiceFileSources private readonly Lazy>> _xmlSources; /// + /// Initializes a new instance of the class. /// This is used to configure the file sources with the main file sources shipped with Umbraco and also including - /// supplemental/plugin based - /// localization files. The supplemental files will be loaded in and merged in after the primary files. + /// supplemental/plugin based localization files. The supplemental files will be loaded in and merged in after the primary files. /// The supplemental files must be named with the 4 letter culture name with a hyphen such as : en-AU.xml /// + /// The logger. + /// The application caches. + /// The directory containing the primary localization files. + /// The supplementary file sources to merge with primary files. + /// The directory contents provider. public LocalizedTextServiceFileSources( ILogger logger, AppCaches appCaches, @@ -144,8 +149,11 @@ public LocalizedTextServiceFileSources( } /// - /// Constructor + /// Initializes a new instance of the class with default settings. /// + /// The logger. + /// The application caches. + /// The directory containing the localization files. public LocalizedTextServiceFileSources(ILogger logger, AppCaches appCaches, DirectoryInfo fileSourceFolder) : this(logger, appCaches, fileSourceFolder, Enumerable.Empty(), new NotFoundDirectoryContents()) { @@ -186,6 +194,14 @@ private IEnumerable GetLanguageFiles() return result; } + /// + /// Attempts to convert a 2-letter culture code to its 4-letter equivalent. + /// + /// The 2-letter culture code to convert. + /// An attempt containing the 4-letter culture info if successful. + /// + /// This is a workaround because language files are stored with 2-letter culture names that actually contain 4-letter cultures. + /// // TODO: See other notes in this class, this is purely a hack because we store 2 letter culture file names that contain 4 letter cultures :( public Attempt TryConvert2LetterCultureTo4Letter(string twoLetterCulture) { @@ -202,6 +218,14 @@ private IEnumerable GetLanguageFiles() : Attempt.Fail(); } + /// + /// Attempts to convert a 4-letter culture to its 2-letter equivalent. + /// + /// The culture to convert. + /// An attempt containing the 2-letter culture code if successful. + /// + /// This is a workaround because language files are stored with 2-letter culture names that actually contain 4-letter cultures. + /// // TODO: See other notes in this class, this is purely a hack because we store 2 letter culture file names that contain 4 letter cultures :( public Attempt TryConvert4LetterCultureTo2Letter(CultureInfo culture) { diff --git a/src/Umbraco.Core/Services/LocalizedTextServiceSupplementaryFileSource.cs b/src/Umbraco.Core/Services/LocalizedTextServiceSupplementaryFileSource.cs index 433bf06f77e9..90954904cfbe 100644 --- a/src/Umbraco.Core/Services/LocalizedTextServiceSupplementaryFileSource.cs +++ b/src/Umbraco.Core/Services/LocalizedTextServiceSupplementaryFileSource.cs @@ -2,16 +2,32 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Represents a supplementary file source for localized text services, allowing plugins and extensions +/// to provide additional or overriding localization keys. +/// public class LocalizedTextServiceSupplementaryFileSource { - + /// + /// Initializes a new instance of the class. + /// + /// The file information for the supplementary localization file. + /// + /// If set to true, keys in this file will overwrite core localization keys. + /// public LocalizedTextServiceSupplementaryFileSource(IFileInfo file, bool overwriteCoreKeys) { FileInfo = file ?? throw new ArgumentNullException(nameof(file)); OverwriteCoreKeys = overwriteCoreKeys; } + /// + /// Gets the file information for this supplementary localization file. + /// public IFileInfo FileInfo { get; } + /// + /// Gets a value indicating whether keys in this file should overwrite core localization keys. + /// public bool OverwriteCoreKeys { get; } } diff --git a/src/Umbraco.Core/Services/Locking/ContentTypeLocks.cs b/src/Umbraco.Core/Services/Locking/ContentTypeLocks.cs index 377d4f446d50..801f928ad698 100644 --- a/src/Umbraco.Core/Services/Locking/ContentTypeLocks.cs +++ b/src/Umbraco.Core/Services/Locking/ContentTypeLocks.cs @@ -1,9 +1,30 @@ -namespace Umbraco.Cms.Core.Services.Locking; +namespace Umbraco.Cms.Core.Services.Locking; +/// +/// Provides lock identifiers for content type operations to ensure thread-safe access. +/// +/// +/// This class defines the lock IDs required for read and write operations on content types. +/// The order of locks is critical to prevent deadlocks when multiple locks are acquired. +/// internal static class ContentTypeLocks { + /// + /// Gets the lock identifiers required for read operations on content types. + /// + /// + /// An array containing . + /// // beware! order is important to avoid deadlocks internal static int[] ReadLockIds { get; } = { Constants.Locks.ContentTypes }; + /// + /// Gets the lock identifiers required for write operations on content types. + /// + /// + /// An array containing and + /// in the order they must be acquired. + /// + // beware! order is important to avoid deadlocks internal static int[] WriteLockIds { get; } = { Constants.Locks.ContentTree, Constants.Locks.ContentTypes }; } diff --git a/src/Umbraco.Core/Services/Locking/MediaTypeLocks.cs b/src/Umbraco.Core/Services/Locking/MediaTypeLocks.cs index 04456da3958f..a5ecea06ef0c 100644 --- a/src/Umbraco.Core/Services/Locking/MediaTypeLocks.cs +++ b/src/Umbraco.Core/Services/Locking/MediaTypeLocks.cs @@ -1,9 +1,30 @@ -namespace Umbraco.Cms.Core.Services.Locking; +namespace Umbraco.Cms.Core.Services.Locking; +/// +/// Provides lock identifiers for media type operations to ensure thread-safe access. +/// +/// +/// This class defines the lock IDs required for read and write operations on media types. +/// The order of locks is critical to prevent deadlocks when multiple locks are acquired. +/// internal static class MediaTypeLocks { + /// + /// Gets the lock identifiers required for read operations on media types. + /// + /// + /// An array containing . + /// // beware! order is important to avoid deadlocks internal static int[] ReadLockIds { get; } = { Constants.Locks.MediaTypes }; + /// + /// Gets the lock identifiers required for write operations on media types. + /// + /// + /// An array containing and + /// in the order they must be acquired. + /// + // beware! order is important to avoid deadlocks internal static int[] WriteLockIds { get; } = { Constants.Locks.MediaTree, Constants.Locks.MediaTypes }; } diff --git a/src/Umbraco.Core/Services/Locking/MemberTypeLocks.cs b/src/Umbraco.Core/Services/Locking/MemberTypeLocks.cs index 5c852d51770c..034207614827 100644 --- a/src/Umbraco.Core/Services/Locking/MemberTypeLocks.cs +++ b/src/Umbraco.Core/Services/Locking/MemberTypeLocks.cs @@ -1,9 +1,30 @@ namespace Umbraco.Cms.Core.Services.Locking; +/// +/// Provides lock identifiers for member type operations to ensure thread-safe access. +/// +/// +/// This class defines the lock IDs required for read and write operations on member types. +/// The order of locks is critical to prevent deadlocks when multiple locks are acquired. +/// internal static class MemberTypeLocks { + /// + /// Gets the lock identifiers required for read operations on member types. + /// + /// + /// An array containing . + /// // beware! order is important to avoid deadlocks internal static int[] ReadLockIds { get; } = { Constants.Locks.MemberTypes }; + /// + /// Gets the lock identifiers required for write operations on member types. + /// + /// + /// An array containing and + /// in the order they must be acquired. + /// + // beware! order is important to avoid deadlocks internal static int[] WriteLockIds { get; } = { Constants.Locks.MemberTree, Constants.Locks.MemberTypes }; } diff --git a/src/Umbraco.Core/Services/MediaEditingService.cs b/src/Umbraco.Core/Services/MediaEditingService.cs index ec9177c150bd..01a29f84dae9 100644 --- a/src/Umbraco.Core/Services/MediaEditingService.cs +++ b/src/Umbraco.Core/Services/MediaEditingService.cs @@ -10,11 +10,30 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Implements the for creating, updating, deleting, +/// and managing items through the editing API. +/// internal sealed class MediaEditingService : ContentEditingServiceWithSortingBase, IMediaEditingService { private readonly ILogger> _logger; + /// + /// Initializes a new instance of the class. + /// + /// The for media operations. + /// The for media type operations. + /// The collection of property editors. + /// The for data type operations. + /// The logger for this service. + /// The for database scope management. + /// The for resolving user IDs. + /// The for sorting operations. + /// The for media validation. + /// The options monitor for . + /// The for relation operations. + /// The collection of content type filters. public MediaEditingService( IMediaService contentService, IMediaTypeService contentTypeService, @@ -46,12 +65,14 @@ public MediaEditingService( /// protected override string? RelateParentOnDeleteAlias => Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias; + /// public Task GetAsync(Guid key) { IMedia? media = ContentService.GetById(key); return Task.FromResult(media); } + /// public async Task> ValidateUpdateAsync(Guid key, MediaUpdateModel updateModel) { IMedia? media = ContentService.GetById(key); @@ -60,9 +81,11 @@ public async Task public async Task> ValidateCreateAsync(MediaCreateModel createModel) => await ValidatePropertiesAsync(createModel, createModel.ContentTypeKey); + /// public async Task> CreateAsync(MediaCreateModel createModel, Guid userKey) { Attempt result = await MapCreate(createModel); @@ -91,6 +114,7 @@ public async Task> Cre : Attempt.FailWithStatus(operationStatus, new MediaCreateResult { Content = media }); } + /// public async Task> UpdateAsync(Guid key, MediaUpdateModel updateModel, Guid userKey) { IMedia? media = ContentService.GetById(key); @@ -117,42 +141,56 @@ public async Task> Upd : Attempt.FailWithStatus(operationStatus, new MediaUpdateResult { Content = media }); } + /// public async Task> MoveToRecycleBinAsync(Guid key, Guid userKey) => await HandleMoveToRecycleBinAsync(key, userKey); + /// public async Task> DeleteAsync(Guid key, Guid userKey) => await HandleDeleteAsync(key, userKey,false); + /// public async Task> DeleteFromRecycleBinAsync(Guid key, Guid userKey) => await HandleDeleteAsync(key, userKey, true); + /// public async Task> MoveAsync(Guid key, Guid? parentKey, Guid userKey) => await HandleMoveAsync(key, parentKey, userKey); + /// public async Task> RestoreAsync(Guid key, Guid? parentKey, Guid userKey) => await HandleMoveAsync(key, parentKey, userKey, true); + /// public async Task SortAsync(Guid? parentKey, IEnumerable sortingModels, Guid userKey) => await HandleSortAsync(parentKey, sortingModels, userKey); + /// protected override IMedia New(string? name, int parentId, IMediaType mediaType) => new Models.Media(name, parentId, mediaType); + /// protected override OperationResult? Move(IMedia media, int newParentId, int userId) => ContentService.Move(media, newParentId, userId).Result; + /// + /// Copy is not supported for media items. protected override IMedia? Copy(IMedia media, int newParentId, bool relateToOriginal, bool includeDescendants, int userId) => throw new NotSupportedException("Copy is not supported for media"); + /// protected override OperationResult? MoveToRecycleBin(IMedia media, int userId) => ContentService.MoveToRecycleBin(media, userId).Result; + /// protected override OperationResult? Delete(IMedia media, int userId) => ContentService.Delete(media, userId).Result; + /// protected override IEnumerable GetPagedChildren(int parentId, int pageIndex, int pageSize, out long total) => ContentService.GetPagedChildren(parentId, pageIndex, pageSize, out total); + /// protected override ContentEditingOperationStatus Sort(IEnumerable items, int userId) { bool result = ContentService.Sort(items, userId); @@ -161,6 +199,12 @@ protected override ContentEditingOperationStatus Sort(IEnumerable items, : ContentEditingOperationStatus.CancelledByNotification; } + /// + /// Saves a media item to the repository. + /// + /// The item to save. + /// The identifier of the user performing the save operation. + /// A indicating the outcome of the save operation. private ContentEditingOperationStatus Save(IMedia media, int userId) { try diff --git a/src/Umbraco.Core/Services/MediaImportService.cs b/src/Umbraco.Core/Services/MediaImportService.cs index ca5af17a73b7..a52953b61f0b 100644 --- a/src/Umbraco.Core/Services/MediaImportService.cs +++ b/src/Umbraco.Core/Services/MediaImportService.cs @@ -9,6 +9,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Service for importing media files into the Umbraco media library. +/// internal sealed class MediaImportService : IMediaImportService { private readonly IShortStringHelper _shortStringHelper; @@ -20,6 +23,17 @@ internal sealed class MediaImportService : IMediaImportService private readonly AppCaches _appCaches; private readonly IUserService _userService; + /// + /// Initializes a new instance of the class. + /// + /// The short string helper for file name sanitization. + /// The media file manager. + /// The media service. + /// The media URL generators collection. + /// The content type base service provider. + /// The entity service. + /// The application caches. + /// The user service. public MediaImportService( IShortStringHelper shortStringHelper, MediaFileManager mediaFileManager, @@ -40,6 +54,7 @@ public MediaImportService( _userService = userService; } + /// public async Task ImportAsync(string fileName, Stream fileStream, Guid? parentId, string? mediaTypeAlias, Guid userKey) { if (fileStream.CanRead == false) diff --git a/src/Umbraco.Core/Services/MediaPermissionService.cs b/src/Umbraco.Core/Services/MediaPermissionService.cs index 28276c0f56c3..b5d124cbb7bd 100644 --- a/src/Umbraco.Core/Services/MediaPermissionService.cs +++ b/src/Umbraco.Core/Services/MediaPermissionService.cs @@ -12,6 +12,12 @@ internal sealed class MediaPermissionService : IMediaPermissionService private readonly IEntityService _entityService; private readonly AppCaches _appCaches; + /// + /// Initializes a new instance of the class. + /// + /// The media service. + /// The entity service. + /// The application caches. public MediaPermissionService( IMediaService mediaService, IEntityService entityService, diff --git a/src/Umbraco.Core/Services/MediaService.cs b/src/Umbraco.Core/Services/MediaService.cs index df60ceee6ebc..f699d6758b58 100644 --- a/src/Umbraco.Core/Services/MediaService.cs +++ b/src/Umbraco.Core/Services/MediaService.cs @@ -33,6 +33,19 @@ public class MediaService : RepositoryService, IMediaService #region Constructors + /// + /// Initializes a new instance of the class. + /// + /// The for database scope management. + /// The for media file operations. + /// The for creating loggers. + /// The for creating event messages. + /// The for media persistence. + /// The for audit logging. + /// The for media type persistence. + /// The for entity operations. + /// The for string operations. + /// The for resolving user IDs. public MediaService( ICoreScopeProvider provider, MediaFileManager mediaFileManager, @@ -55,6 +68,19 @@ public MediaService( _userIdKeyResolver = userIdKeyResolver; } + /// + /// Initializes a new instance of the class. + /// + /// The for database scope management. + /// The for media file operations. + /// The for creating loggers. + /// The for creating event messages. + /// The for media persistence. + /// The audit repository (obsolete, not used). + /// The for media type persistence. + /// The for entity operations. + /// The for string operations. + /// The for resolving user IDs. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public MediaService( ICoreScopeProvider provider, @@ -81,6 +107,20 @@ public MediaService( { } + /// + /// Initializes a new instance of the class. + /// + /// The for database scope management. + /// The for media file operations. + /// The for creating loggers. + /// The for creating event messages. + /// The for media persistence. + /// The for audit logging. + /// The audit repository (obsolete, not used). + /// The for media type persistence. + /// The for entity operations. + /// The for string operations. + /// The for resolving user IDs. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public MediaService( ICoreScopeProvider provider, @@ -112,6 +152,11 @@ public MediaService( #region Count + /// + /// Counts the total number of media items, optionally filtered by media type alias. + /// + /// Optional alias of the to filter by. + /// The total count of media items matching the criteria. public int Count(string? mediaTypeAlias = null) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -119,6 +164,12 @@ public int Count(string? mediaTypeAlias = null) return _mediaRepository.Count(mediaTypeAlias); } + /// + /// Counts the total number of media items that are not in the recycle bin, + /// optionally filtered by media type alias. + /// + /// Optional alias of the to filter by. + /// The total count of non-trashed media items matching the criteria. public int CountNotTrashed(string? mediaTypeAlias = null) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -145,6 +196,13 @@ public int CountNotTrashed(string? mediaTypeAlias = null) return _mediaRepository.Count(query); } + /// + /// Counts the number of direct children of a media item, + /// optionally filtered by media type alias. + /// + /// The identifier of the parent media item. + /// Optional alias of the to filter by. + /// The count of direct children matching the criteria. public int CountChildren(int parentId, string? mediaTypeAlias = null) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -154,6 +212,13 @@ public int CountChildren(int parentId, string? mediaTypeAlias = null) } } + /// + /// Counts all descendants of a media item, + /// optionally filtered by media type alias. + /// + /// The identifier of the parent media item. + /// Optional alias of the to filter by. + /// The count of all descendants matching the criteria. public int CountDescendants(int parentId, string? mediaTypeAlias = null) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -365,6 +430,14 @@ public IMedia CreateMediaWithIdentity(string name, IMedia parent, string mediaTy return media; } + /// + /// Creates a media item, optionally persisting it to the database. + /// + /// The current database scope. + /// The media item to create. + /// The parent media item, or null for root-level media. + /// The identifier of the user creating the media. + /// If true, the media will be persisted to the database; otherwise, it will only be initialized in memory. private void CreateMedia(ICoreScope scope, Core.Models.Media media, IMedia? parent, int userId, bool withIdentity) { EventMessages eventMessages = EventMessagesFactory.Get(); @@ -639,6 +712,11 @@ public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageS return GetPagedLocked(GetPagedDescendantQuery(null), pageIndex, pageSize, out totalChildren, filter, ordering); } + /// + /// Creates a query for retrieving descendants of a media item by path. + /// + /// The path of the parent media item, or null to get all media. + /// A query for the descendants. private IQuery? GetPagedDescendantQuery(string? mediaPath) { IQuery? query = Query(); @@ -650,6 +728,16 @@ public IEnumerable GetPagedDescendants(int id, long pageIndex, int pageS return query; } + /// + /// Gets a paged collection of media items matching the specified query while holding a lock. + /// + /// The query to execute. + /// The zero-based page index. + /// The number of items per page. + /// When this method returns, contains the total number of matching items. + /// Optional additional filter query. + /// The ordering specification. + /// A collection of media items for the requested page. private IEnumerable GetPagedLocked(IQuery? query, long pageIndex, int pageSize, out long totalChildren, IQuery? filter, Ordering ordering) { if (pageIndex < 0) @@ -890,6 +978,12 @@ public bool HasChildren(int id) return OperationResult.Attempt.Succeed(messages); } + /// + /// Deletes a media item and all its descendants while holding a write lock. + /// + /// The current database scope. + /// The media item to delete. + /// The event messages to include in notifications. private void DeleteLocked(ICoreScope scope, IMedia media, EventMessages evtMsgs) { void DoDelete(IMedia c) @@ -935,6 +1029,14 @@ public void DeleteVersions(int id, DateTime versionDate, int userId = Constants. scope.Complete(); } + /// + /// Deletes versions of a media item prior to a specific date. + /// + /// The current database scope. + /// If true, acquires a write lock before deleting. + /// The identifier of the media item. + /// The date before which versions should be deleted. + /// The identifier of the user performing the delete operation. private void DeleteVersions(ICoreScope scope, bool wlock, int id, DateTime versionDate, int userId = Constants.Security.SuperUserId) { EventMessages evtMsgs = EventMessagesFactory.Get(); @@ -1098,8 +1200,22 @@ public void DeleteVersion(int id, int versionId, bool deletePriorVersions, int u return OperationResult.Attempt.Succeed(messages); } - // MUST be called from within WriteLock - // trash indicates whether we are trashing, un-trashing, or not changing anything + /// + /// Performs a move operation on a media item while holding a write lock. + /// + /// The media item to move. + /// The identifier of the new parent. + /// The new parent media item, or null for root-level. + /// The identifier of the user performing the move. + /// A collection to record the original paths of moved items. + /// + /// If true, marks items as trashed; if false, marks items as not trashed; + /// if null, leaves the trashed status unchanged. + /// + /// + /// MUST be called from within WriteLock. + /// The trash parameter indicates whether we are trashing, un-trashing, or not changing anything. + /// private void PerformMoveLocked(IMedia media, int parentId, IMedia? parent, int userId, ICollection<(IMedia, string)> moves, bool? trash) { // Needed to update the in-memory navigation structure @@ -1150,6 +1266,14 @@ private void PerformMoveLocked(IMedia media, int parentId, IMedia? parent, int u while (total > pageSize); } + /// + /// Performs the actual save of a media item during a move operation while holding a write lock. + /// + /// The media item to save. + /// + /// If true, marks the item as trashed; if false, marks the item as not trashed; + /// if null, leaves the trashed status unchanged. + /// private void PerformMoveMediaLocked(IMedia media, bool? trash) { if (trash.HasValue) @@ -1160,6 +1284,11 @@ private void PerformMoveMediaLocked(IMedia media, bool? trash) _mediaRepository.Save(media); } + /// + /// Empties the Recycle Bin by deleting all items that reside in the bin. + /// + /// The unique identifier of the user emptying the Recycle Bin. + /// A task that represents the asynchronous operation. The task result contains an indicating the outcome. public async Task EmptyRecycleBinAsync(Guid userId) => EmptyRecycleBin(await _userIdKeyResolver.GetAsync(userId)); @@ -1201,6 +1330,10 @@ public OperationResult EmptyRecycleBin(int userId = Constants.Security.SuperUser return OperationResult.Succeed(messages); } + /// + /// Checks whether the Recycle Bin contains any media items. + /// + /// true if the Recycle Bin contains media items; otherwise, false. public bool RecycleBinSmells() { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -1271,6 +1404,11 @@ public bool Sort(IEnumerable items, int userId = Constants.Security.Supe } + /// + /// Checks the data integrity of the media tree and optionally fixes detected issues. + /// + /// The options specifying how to check and fix data integrity. + /// A containing details of any detected and fixed issues. public ContentDataIntegrityReport CheckDataIntegrity(ContentDataIntegrityReportOptions options) { using (ICoreScope scope = ScopeProvider.CreateCoreScope()) @@ -1295,9 +1433,25 @@ public ContentDataIntegrityReport CheckDataIntegrity(ContentDataIntegrityReportO #region Private Methods + /// + /// Records an audit entry for a media operation. + /// + /// The type of audit entry. + /// The identifier of the user performing the action. + /// The identifier of the affected media object. + /// Optional message describing the action. private void Audit(AuditType type, int userId, int objectId, string? message = null) => AuditAsync(type, userId, objectId, message).GetAwaiter().GetResult(); + /// + /// Records an audit entry for a media operation asynchronously. + /// + /// The type of audit entry. + /// The identifier of the user performing the action. + /// The identifier of the affected media object. + /// Optional message describing the action. + /// Optional additional parameters for the audit entry. + /// A task representing the asynchronous operation. private async Task AuditAsync(AuditType type, int userId, int objectId, string? message = null, string? parameters = null) { Guid userKey = await _userIdKeyResolver.GetAsync(userId); @@ -1315,6 +1469,11 @@ await _auditService.AddAsync( #region File Management + /// + /// Gets a stream containing the content of a media file. + /// + /// The path to the media file. + /// A containing the file content, or if the file does not exist or cannot be opened. public Stream GetMediaFileContentStream(string filepath) { if (_mediaFileManager.FileSystem.FileExists(filepath) == false) @@ -1332,16 +1491,30 @@ public Stream GetMediaFileContentStream(string filepath) } } + /// + /// Sets the content of a media file. + /// + /// The path where the file should be stored. + /// A containing the file content to write. public void SetMediaFileContent(string filepath, Stream stream) { _mediaFileManager.FileSystem.AddFile(filepath, stream, true); } + /// + /// Deletes a media file from storage. + /// + /// The path of the file to delete. public void DeleteMediaFile(string filepath) { _mediaFileManager.FileSystem.DeleteFile(filepath); } + /// + /// Gets the size of a media file in bytes. + /// + /// The path to the media file. + /// The size of the file in bytes. public long GetMediaFileSize(string filepath) { return _mediaFileManager.FileSystem.GetSize(filepath); @@ -1437,6 +1610,14 @@ public void DeleteMediaOfType(int mediaTypeId, int userId = Constants.Security.S DeleteMediaOfTypes(new[] { mediaTypeId }, userId); } + /// + /// Gets a media type by its alias. + /// + /// The alias of the media type to retrieve. + /// The matching the specified alias. + /// Thrown when is null. + /// Thrown when is empty or whitespace. + /// Thrown when no media type matches the specified alias. private IMediaType GetMediaType(string mediaTypeAlias) { if (mediaTypeAlias == null) diff --git a/src/Umbraco.Core/Services/MediaServiceExtensions.cs b/src/Umbraco.Core/Services/MediaServiceExtensions.cs index e7d01f122e52..77a379992a37 100644 --- a/src/Umbraco.Core/Services/MediaServiceExtensions.cs +++ b/src/Umbraco.Core/Services/MediaServiceExtensions.cs @@ -17,6 +17,13 @@ namespace Umbraco.Extensions; /// public static class MediaServiceExtensions { + /// + /// Gets a collection of media items by their UDIs. + /// + /// The media service. + /// The collection of UDIs to retrieve. + /// A collection of media items. + /// Thrown when a UDI is not of type . public static IEnumerable GetByIds(this IMediaService mediaService, IEnumerable ids) { var guids = new List(); @@ -34,6 +41,16 @@ public static IEnumerable GetByIds(this IMediaService mediaService, IEnu return mediaService.GetByIds(guids.Select(x => x.Guid)); } + /// + /// Creates a new media item under a parent specified by UDI. + /// + /// The media service. + /// The name of the new media item. + /// The UDI of the parent media item. + /// The alias of the media type. + /// The ID of the user creating the media item. + /// The newly created media item. + /// Thrown when the UDI is not of type . public static IMedia CreateMedia(this IMediaService mediaService, string name, Udi parentId, string mediaTypeAlias, int userId = Constants.Security.SuperUserId) { if (parentId is not GuidUdi guidUdi) diff --git a/src/Umbraco.Core/Services/MediaTypeContainerService.cs b/src/Umbraco.Core/Services/MediaTypeContainerService.cs index 548b38b70db0..30a0e768c985 100644 --- a/src/Umbraco.Core/Services/MediaTypeContainerService.cs +++ b/src/Umbraco.Core/Services/MediaTypeContainerService.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence.Repositories; @@ -7,8 +7,24 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing media type containers (folders). +/// +/// +/// Media type containers allow organizing media types into a hierarchical folder structure. +/// internal sealed class MediaTypeContainerService : EntityTypeContainerService, IMediaTypeContainerService { + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for unit of work operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for media type container data access. + /// The audit service for recording audit entries. + /// The entity repository for entity operations. + /// The resolver for converting user IDs to keys. public MediaTypeContainerService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -21,11 +37,15 @@ public MediaTypeContainerService( { } + /// protected override Guid ContainedObjectType => Constants.ObjectTypes.MediaType; + /// protected override UmbracoObjectTypes ContainerObjectType => UmbracoObjectTypes.MediaTypeContainer; + /// protected override int[] ReadLockIds => MediaTypeLocks.ReadLockIds; + /// protected override int[] WriteLockIds => MediaTypeLocks.WriteLockIds; } diff --git a/src/Umbraco.Core/Services/MediaTypeService.cs b/src/Umbraco.Core/Services/MediaTypeService.cs index 22166dfdae22..84e9a4aeb03d 100644 --- a/src/Umbraco.Core/Services/MediaTypeService.cs +++ b/src/Umbraco.Core/Services/MediaTypeService.cs @@ -13,8 +13,25 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Represents the Media Type Service, which provides operations for managing entities. +/// public class MediaTypeService : ContentTypeServiceBase, IMediaTypeService { + /// + /// Initializes a new instance of the class. + /// + /// The for database scope management. + /// The for creating loggers. + /// The for creating event messages. + /// The for media operations. + /// The for media type persistence. + /// The for audit logging. + /// The for media type container operations. + /// The for entity operations. + /// The for publishing events. + /// The for resolving user IDs. + /// The collection of content type filters. public MediaTypeService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -42,6 +59,20 @@ public MediaTypeService( MediaService = mediaService; } + /// + /// Initializes a new instance of the class. + /// + /// The for database scope management. + /// The for creating loggers. + /// The for creating event messages. + /// The for media operations. + /// The for media type persistence. + /// The audit repository (obsolete, not used). + /// The for media type container operations. + /// The for entity operations. + /// The for publishing events. + /// The for resolving user IDs. + /// The collection of content type filters. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public MediaTypeService( ICoreScopeProvider provider, @@ -70,6 +101,21 @@ public MediaTypeService( { } + /// + /// Initializes a new instance of the class. + /// + /// The for database scope management. + /// The for creating loggers. + /// The for creating event messages. + /// The for media operations. + /// The for media type persistence. + /// The for audit logging. + /// The audit repository (obsolete, not used). + /// The for media type container operations. + /// The for entity operations. + /// The for publishing events. + /// The for resolving user IDs. + /// The collection of content type filters. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public MediaTypeService( ICoreScopeProvider provider, @@ -99,14 +145,21 @@ public MediaTypeService( { } + /// protected override int[] ReadLockIds => MediaTypeLocks.ReadLockIds; + /// protected override int[] WriteLockIds => MediaTypeLocks.WriteLockIds; + /// protected override Guid ContainedObjectType => Constants.ObjectTypes.MediaType; + /// + /// Gets the used for media operations. + /// private IMediaService MediaService { get; } + /// protected override void DeleteItemsOfTypes(IEnumerable typeIds) { foreach (var typeId in typeIds) @@ -115,51 +168,63 @@ protected override void DeleteItemsOfTypes(IEnumerable typeIds) } } + /// protected override bool CanDelete(IMediaType item) => item.IsSystemMediaType() is false; #region Notifications + /// protected override SavingNotification GetSavingNotification( IMediaType item, EventMessages eventMessages) => new MediaTypeSavingNotification(item, eventMessages); + /// protected override SavingNotification GetSavingNotification( IEnumerable items, EventMessages eventMessages) => new MediaTypeSavingNotification(items, eventMessages); + /// protected override SavedNotification GetSavedNotification( IMediaType item, EventMessages eventMessages) => new MediaTypeSavedNotification(item, eventMessages); + /// protected override SavedNotification GetSavedNotification( IEnumerable items, EventMessages eventMessages) => new MediaTypeSavedNotification(items, eventMessages); + /// protected override DeletingNotification GetDeletingNotification( IMediaType item, EventMessages eventMessages) => new MediaTypeDeletingNotification(item, eventMessages); + /// protected override DeletingNotification GetDeletingNotification( IEnumerable items, EventMessages eventMessages) => new MediaTypeDeletingNotification(items, eventMessages); + /// protected override DeletedNotification GetDeletedNotification( IEnumerable items, EventMessages eventMessages) => new MediaTypeDeletedNotification(items, eventMessages); + /// protected override MovingNotification GetMovingNotification( MoveEventInfo moveInfo, EventMessages eventMessages) => new MediaTypeMovingNotification(moveInfo, eventMessages); + /// protected override MovedNotification GetMovedNotification( IEnumerable> moveInfo, EventMessages eventMessages) => new MediaTypeMovedNotification(moveInfo, eventMessages); + /// protected override ContentTypeChangeNotification GetContentTypeChangedNotification( IEnumerable> changes, EventMessages eventMessages) => new MediaTypeChangedNotification(changes, eventMessages); + /// protected override ContentTypeRefreshNotification GetContentTypeRefreshedNotification( IEnumerable> changes, EventMessages eventMessages) => new MediaTypeRefreshedNotification(changes, eventMessages); diff --git a/src/Umbraco.Core/Services/MediaValidationService.cs b/src/Umbraco.Core/Services/MediaValidationService.cs index 0b46e61a877e..73905a71a673 100644 --- a/src/Umbraco.Core/Services/MediaValidationService.cs +++ b/src/Umbraco.Core/Services/MediaValidationService.cs @@ -1,15 +1,24 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentEditing; namespace Umbraco.Cms.Core.Services; +/// +/// Service for validating media content properties against their media type definitions. +/// internal sealed class MediaValidationService : ContentValidationServiceBase, IMediaValidationService { + /// + /// Initializes a new instance of the class. + /// + /// The property validation service. + /// The language service. public MediaValidationService(IPropertyValidationService propertyValidationService, ILanguageService languageService) : base(propertyValidationService, languageService) { } + /// public async Task ValidatePropertiesAsync( ContentEditingModelBase contentEditingModelBase, IMediaType mediaType, diff --git a/src/Umbraco.Core/Services/MemberContentEditingService.cs b/src/Umbraco.Core/Services/MemberContentEditingService.cs index 8ec58ae34338..313de68c4e0f 100644 --- a/src/Umbraco.Core/Services/MemberContentEditingService.cs +++ b/src/Umbraco.Core/Services/MemberContentEditingService.cs @@ -12,12 +12,35 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for editing member content in Umbraco. +/// +/// +/// This service handles member content editing operations including validation, updating, +/// and deleting members. It extends the base content editing service with member-specific +/// functionality such as handling sensitive property access control. +/// internal sealed class MemberContentEditingService : ContentEditingServiceBase, IMemberContentEditingService { private readonly ILogger> _logger; private readonly IUserService _userService; + /// + /// Initializes a new instance of the class. + /// + /// The member service for member operations. + /// The member type service for member type operations. + /// The collection of property editors. + /// The data type service for data type operations. + /// The logger instance for logging operations. + /// The core scope provider for managing database transactions. + /// The resolver for converting user keys to IDs. + /// The service for validating member content. + /// The user service for user operations. + /// The options monitor for content settings. + /// The relation service for managing content relations. + /// The collection of content type filters. public MemberContentEditingService( IMemberService contentService, IMemberTypeService contentTypeService, @@ -37,9 +60,11 @@ public MemberContentEditingService( _userService = userService; } + /// public async Task> ValidateAsync(MemberEditingModelBase editingModel, Guid memberTypeKey) => await ValidatePropertiesAsync(editingModel, memberTypeKey); + /// public async Task> UpdateAsync(IMember member, MemberEditingModelBase updateModel, Guid userKey) { IMemberType memberType = await ContentTypeService.GetAsync(member.ContentType.Key) @@ -76,24 +101,38 @@ public async Task> Up : Attempt.FailWithStatus(operationStatus, new MemberUpdateResult { Content = member }); } + /// public async Task> DeleteAsync(Guid key, Guid userKey) => await HandleDeleteAsync(key, userKey, false); + /// protected override IMember New(string? name, int parentId, IMemberType memberType) => throw new NotSupportedException("Member creation is not supported by this service. This should never be called."); + /// protected override OperationResult? Move(IMember member, int newParentId, int userId) => throw new InvalidOperationException("Move is not supported for members"); + /// protected override IMember? Copy(IMember member, int newParentId, bool relateToOriginal, bool includeDescendants, int userId) => throw new NotSupportedException("Copy is not supported for Member"); + /// protected override OperationResult? MoveToRecycleBin(IMember member, int userId) => throw new InvalidOperationException("Recycle bin is not supported for members"); + /// protected override OperationResult? Delete(IMember member, int userId) => ContentService.Delete(member, userId).Result; + /// + /// Saves the specified member with the given user ID. + /// + /// The member to save. + /// The ID of the user performing the save operation. + /// + /// The operation status indicating success or failure of the save operation. + /// private ContentEditingOperationStatus Save(IMember member, int userId) { try @@ -116,6 +155,17 @@ private ContentEditingOperationStatus Save(IMember member, int userId) } } + /// + /// Validates that the user has access to modify the sensitive properties included in the update model. + /// + /// The member being updated. + /// The member type defining the property structure. + /// The update model containing properties to be modified. + /// The user performing the update. + /// + /// true if the user has access to all sensitive properties in the update model or has access to sensitive data; + /// otherwise, false if the user is attempting to modify sensitive properties without proper access. + /// private bool ValidateAccessToSensitiveProperties(IMember member, IMemberType memberType, MemberEditingModelBase updateModel, IUser user) { if (user.HasAccessToSensitiveData()) @@ -131,6 +181,16 @@ private bool ValidateAccessToSensitiveProperties(IMember member, IMemberType mem .Any() is false; } + /// + /// Finds the sensitive property values that need to be retained during an update for users without sensitive data access. + /// + /// The member whose sensitive properties should be retained. + /// The member type defining which properties are sensitive. + /// The user performing the update. + /// + /// A dictionary mapping property aliases to their current values for sensitive properties, + /// or an empty dictionary if the user has access to sensitive data. + /// private Dictionary FindSensitivePropertiesToRetain(IMember member, IMemberType memberType, IUser user) { if (user.HasAccessToSensitiveData()) @@ -143,6 +203,11 @@ private bool ValidateAccessToSensitiveProperties(IMember member, IMemberType mem return sensitivePropertyAliases.ToDictionary(alias => alias, alias => member.GetValue(alias)); } + /// + /// Restores the retained sensitive property values to the member after a base update operation. + /// + /// The member to restore sensitive properties on. + /// The dictionary of sensitive property values to restore. private void RetainSensitiveProperties(IMember member, Dictionary sensitivePropertyValues) { foreach (KeyValuePair sensitiveProperty in sensitivePropertyValues) diff --git a/src/Umbraco.Core/Services/MemberGroupService.cs b/src/Umbraco.Core/Services/MemberGroupService.cs index 2fda732b3ac3..343e94f7aa96 100644 --- a/src/Umbraco.Core/Services/MemberGroupService.cs +++ b/src/Umbraco.Core/Services/MemberGroupService.cs @@ -8,18 +8,35 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing member groups in Umbraco. +/// +/// +/// This service handles CRUD operations for member groups, which are used to organize +/// and categorize members for access control and content personalization purposes. +/// internal sealed class MemberGroupService : RepositoryService, IMemberGroupService { private readonly IMemberGroupRepository _memberGroupRepository; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The repository for member group operations. public MemberGroupService(ICoreScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, IMemberGroupRepository memberGroupRepository) : base(provider, loggerFactory, eventMessagesFactory) => _memberGroupRepository = memberGroupRepository; + /// public IEnumerable GetAll() => GetAllAsync().GetAwaiter().GetResult(); + /// public IEnumerable GetByIds(IEnumerable ids) => GetByIdsAsync(ids).GetAwaiter().GetResult(); + /// public IMemberGroup? GetById(int id) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -28,10 +45,13 @@ public MemberGroupService(ICoreScopeProvider provider, ILoggerFactory loggerFact } } + /// public IMemberGroup? GetById(Guid id) => GetAsync(id).GetAwaiter().GetResult(); + /// public IMemberGroup? GetByName(string? name) => name is null ? null : GetByNameAsync(name).GetAwaiter().GetResult(); + /// public void Save(IMemberGroup memberGroup) { if (string.IsNullOrWhiteSpace(memberGroup.Name)) @@ -58,6 +78,7 @@ public void Save(IMemberGroup memberGroup) } } + /// public void Delete(IMemberGroup memberGroup) => DeleteAsync(memberGroup.Key).GetAwaiter().GetResult(); /// @@ -81,6 +102,7 @@ public Task> GetAllAsync() return Task.FromResult(_memberGroupRepository.GetMany()); } + /// public Task> GetByIdsAsync(IEnumerable ids) { if (ids.Any() == false) @@ -156,6 +178,7 @@ public Task> GetByIdsAsync(IEnumerable ids) return Attempt.SucceedWithStatus(MemberGroupOperationStatus.Success, memberGroup); } + /// public async Task> UpdateAsync(IMemberGroup memberGroup) { if (string.IsNullOrWhiteSpace(memberGroup.Name)) @@ -188,6 +211,14 @@ public Task> GetByIdsAsync(IEnumerable ids) return Attempt.SucceedWithStatus(MemberGroupOperationStatus.Success, memberGroup); } + /// + /// Determines whether a member group with the same name already exists. + /// + /// The member group to check for name duplication. + /// + /// A task that represents the asynchronous operation. + /// The task result is true if a member group with the same name exists; otherwise, false. + /// private async Task NameAlreadyExistsAsync(IMemberGroup memberGroup) { IMemberGroup? existingMemberGroup = await GetByNameAsync(memberGroup.Name!); diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs index 1d6fd9a48402..83d992edd79f 100644 --- a/src/Umbraco.Core/Services/MemberService.cs +++ b/src/Umbraco.Core/Services/MemberService.cs @@ -28,6 +28,19 @@ public class MemberService : RepositoryService, IMemberService #region Constructor + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database operations. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The service for managing member groups. + /// The repository for member data access. + /// The repository for member type data access. + /// The repository for member group data access. + /// The service for audit logging. + /// The lazy-loaded service for mapping between IDs and keys. + /// The resolver for user ID to key mapping. public MemberService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -50,6 +63,18 @@ public MemberService( _memberGroupService = memberGroupService ?? throw new ArgumentNullException(nameof(memberGroupService)); } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database operations. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The service for managing member groups. + /// The repository for member data access. + /// The repository for member type data access. + /// The repository for member group data access. + /// The repository for audit data access (obsolete). + /// The lazy-loaded service for mapping between IDs and keys. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public MemberService( ICoreScopeProvider provider, @@ -75,6 +100,20 @@ public MemberService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database operations. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The service for managing member groups. + /// The repository for member data access. + /// The repository for member type data access. + /// The repository for member group data access. + /// The service for audit logging. + /// The repository for audit data access (obsolete). + /// The lazy-loaded service for mapping between IDs and keys. + /// The resolver for user ID to key mapping. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public MemberService( ICoreScopeProvider provider, @@ -158,6 +197,7 @@ public int Count(string? memberTypeAlias = null) #region Create + /// public async Task> FilterAsync( MemberFilter memberFilter, string orderBy = "username", @@ -245,15 +285,19 @@ IMember IMembershipMemberService.CreateWithIdentity(string username, st IMember IMembershipMemberService.CreateWithIdentity(string username, string email, string passwordValue, string memberTypeAlias, bool isApproved) => CreateMemberWithIdentity(username, email, username, passwordValue, memberTypeAlias, isApproved); + /// public IMember CreateMemberWithIdentity(string username, string email, string memberTypeAlias) => CreateMemberWithIdentity(username, email, username, string.Empty, memberTypeAlias); + /// public IMember CreateMemberWithIdentity(string username, string email, string memberTypeAlias, bool isApproved) => CreateMemberWithIdentity(username, email, username, string.Empty, memberTypeAlias, isApproved); + /// public IMember CreateMemberWithIdentity(string username, string email, string name, string memberTypeAlias) => CreateMemberWithIdentity(username, email, name, string.Empty, memberTypeAlias); + /// public IMember CreateMemberWithIdentity(string username, string email, string name, string memberTypeAlias, bool isApproved) => CreateMemberWithIdentity(username, email, name, string.Empty, memberTypeAlias, isApproved); @@ -292,6 +336,7 @@ public IMember CreateMemberWithIdentity(string username, string email, string na } } + /// public IMember CreateMemberWithIdentity(string username, string email, IMemberType memberType) => CreateMemberWithIdentity(username, email, username, string.Empty, memberType); @@ -308,6 +353,7 @@ public IMember CreateMemberWithIdentity(string username, string email, IMemberTy public IMember CreateMemberWithIdentity(string username, string email, IMemberType memberType, bool isApproved) => CreateMemberWithIdentity(username, email, username, string.Empty, memberType, isApproved); + /// public IMember CreateMemberWithIdentity(string username, string email, string name, IMemberType memberType) => CreateMemberWithIdentity(username, email, name, string.Empty, memberType); @@ -409,6 +455,7 @@ public IEnumerable GetAll(long pageIndex, int pageSize, out long totalR return _memberRepository.GetPage(null, pageIndex, pageSize, out totalRecords, null, Ordering.By("LoginName")); } + /// public IEnumerable GetAll( int skip, int take, @@ -419,6 +466,7 @@ public IEnumerable GetAll( string filter = "") => GetAll(skip, take, out totalRecords, orderBy, orderDirection, true, memberTypeAlias, filter); + /// public IEnumerable GetAll( long pageIndex, int pageSize, @@ -803,12 +851,19 @@ public bool Exists(string username) #region Save + /// + /// Sets the last login date for a member. + /// + /// The username of the member. + /// The date and time of the last login. + /// This method is not implemented. public void SetLastLogin(string username, DateTime date) => throw new NotImplementedException(); /// public Attempt Save(IMember member, int userId = Constants.Security.SuperUserId) => Save(member, PublishNotificationSaveOptions.All, userId); + /// public Attempt Save(IMember member, PublishNotificationSaveOptions publishNotificationSaveOptions, int userId = Constants.Security.SuperUserId) { // trimming username and email to make sure we have no trailing space @@ -865,6 +920,7 @@ public bool Exists(string username) return OperationResult.Attempt.Succeed(evtMsgs); } + /// public void Save(IMember member) => Save(member, Constants.Security.SuperUserId); @@ -991,6 +1047,7 @@ private void DeleteLocked(ICoreScope scope, IMember member, EventMessages evtMsg #region Roles + /// public void AddRole(string roleName) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -1024,6 +1081,7 @@ public IEnumerable GetAllRoles(int memberId) return result.Select(x => x.Name).WhereNotNull().Distinct(); } + /// public IEnumerable GetAllRoles(string username) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -1032,6 +1090,7 @@ public IEnumerable GetAllRoles(string username) return result.Where(x => x.Name != null).Select(x => x.Name).Distinct()!; } + /// public IEnumerable GetAllRolesIds() { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -1039,6 +1098,7 @@ public IEnumerable GetAllRolesIds() return _memberGroupRepository.GetMany().Select(x => x.Id).Distinct(); } + /// public IEnumerable GetAllRolesIds(int memberId) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -1047,6 +1107,7 @@ public IEnumerable GetAllRolesIds(int memberId) return result.Select(x => x.Id).Distinct(); } + /// public IEnumerable GetAllRolesIds(string username) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -1055,6 +1116,7 @@ public IEnumerable GetAllRolesIds(string username) return result.Select(x => x.Id).Distinct(); } + /// public IEnumerable GetMembersInRole(string roleName) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -1062,6 +1124,7 @@ public IEnumerable GetMembersInRole(string roleName) return _memberRepository.GetByMemberGroup(roleName); } + /// public IEnumerable FindMembersInRole(string roleName, string usernameToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -1069,6 +1132,7 @@ public IEnumerable FindMembersInRole(string roleName, string usernameTo return _memberRepository.FindMembersInRole(roleName, usernameToMatch, matchType); } + /// public bool DeleteRole(string roleName, bool throwIfBeingUsed) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -1099,8 +1163,10 @@ public bool DeleteRole(string roleName, bool throwIfBeingUsed) return found?.Length > 0; } + /// public void AssignRole(string username, string roleName) => AssignRoles(new[] { username }, new[] { roleName }); + /// public void AssignRoles(string[] usernames, string[] roleNames) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -1111,8 +1177,10 @@ public void AssignRoles(string[] usernames, string[] roleNames) scope.Complete(); } + /// public void DissociateRole(string username, string roleName) => DissociateRoles(new[] { username }, new[] { roleName }); + /// public void DissociateRoles(string[] usernames, string[] roleNames) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -1123,8 +1191,10 @@ public void DissociateRoles(string[] usernames, string[] roleNames) scope.Complete(); } + /// public void AssignRole(int memberId, string roleName) => AssignRoles(new[] { memberId }, new[] { roleName }); + /// public void AssignRoles(int[] memberIds, string[] roleNames) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -1134,8 +1204,10 @@ public void AssignRoles(int[] memberIds, string[] roleNames) scope.Complete(); } + /// public void DissociateRole(int memberId, string roleName) => DissociateRoles(new[] { memberId }, new[] { roleName }); + /// public void DissociateRoles(int[] memberIds, string[] roleNames) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -1145,6 +1217,7 @@ public void DissociateRoles(int[] memberIds, string[] roleNames) scope.Complete(); } + /// public void ReplaceRoles(string[] usernames, string[] roleNames) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -1155,6 +1228,7 @@ public void ReplaceRoles(string[] usernames, string[] roleNames) scope.Complete(); } + /// public void ReplaceRoles(int[] memberIds, string[] roleNames) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -1171,6 +1245,12 @@ public void ReplaceRoles(int[] memberIds, string[] roleNames) // NOTE: at the time of writing we do not have MemberTreeChangeNotification to publish changes as a result of a data integrity // check. we cannot support this feature until such notification exists. // see the content or media services for implementation details if this is ever going to be a relevant feature for members. + /// + /// Checks the data integrity of the member tree. + /// + /// The options for the data integrity report. + /// A containing the results of the check. + /// Data integrity checks are not implemented for members. public ContentDataIntegrityReport CheckDataIntegrity(ContentDataIntegrityReportOptions options) => throw new InvalidOperationException("Data integrity checks are not (yet) implemented for members."); diff --git a/src/Umbraco.Core/Services/MemberTwoFactorLoginService.cs b/src/Umbraco.Core/Services/MemberTwoFactorLoginService.cs index db09478dab0e..ede51cff56c1 100644 --- a/src/Umbraco.Core/Services/MemberTwoFactorLoginService.cs +++ b/src/Umbraco.Core/Services/MemberTwoFactorLoginService.cs @@ -10,6 +10,13 @@ internal sealed class MemberTwoFactorLoginService : TwoFactorLoginServiceBase, I { private readonly IMemberService _memberService; + /// + /// Initializes a new instance of the class. + /// + /// The two-factor login service. + /// The collection of two-factor providers. + /// The member service. + /// The core scope provider. public MemberTwoFactorLoginService( ITwoFactorLoginService twoFactorLoginService, IEnumerable twoFactorSetupGenerators, diff --git a/src/Umbraco.Core/Services/MemberTypeContainerService.cs b/src/Umbraco.Core/Services/MemberTypeContainerService.cs index e75d9cd603d1..912e767791ec 100644 --- a/src/Umbraco.Core/Services/MemberTypeContainerService.cs +++ b/src/Umbraco.Core/Services/MemberTypeContainerService.cs @@ -7,8 +7,24 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing member type containers (folders). +/// +/// +/// Member type containers allow organizing member types into a hierarchical folder structure. +/// internal sealed class MemberTypeContainerService : EntityTypeContainerService, IMemberTypeContainerService { + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for unit of work operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for member type container data access. + /// The audit service for recording audit entries. + /// The entity repository for entity operations. + /// The resolver for converting user IDs to keys. public MemberTypeContainerService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -21,11 +37,15 @@ public MemberTypeContainerService( { } + /// protected override Guid ContainedObjectType => Constants.ObjectTypes.MemberType; + /// protected override UmbracoObjectTypes ContainerObjectType => UmbracoObjectTypes.MemberTypeContainer; + /// protected override int[] ReadLockIds => MemberTypeLocks.ReadLockIds; + /// protected override int[] WriteLockIds => MemberTypeLocks.WriteLockIds; } diff --git a/src/Umbraco.Core/Services/MemberTypeService.cs b/src/Umbraco.Core/Services/MemberTypeService.cs index 228a10a026d3..d91ce005e182 100644 --- a/src/Umbraco.Core/Services/MemberTypeService.cs +++ b/src/Umbraco.Core/Services/MemberTypeService.cs @@ -12,10 +12,32 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing member types in Umbraco. +/// +/// +/// This service handles operations for member types, which define the structure and properties +/// available for members in the system. It extends the base content type service functionality +/// with member-specific behavior. +/// public class MemberTypeService : ContentTypeServiceBase, IMemberTypeService { private readonly IMemberTypeRepository _memberTypeRepository; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The member service for member-related operations. + /// The repository for member type operations. + /// The service for audit logging. + /// The repository for member type container operations. + /// The repository for entity operations. + /// The event aggregator for publishing notifications. + /// The resolver for converting user keys to IDs. + /// The collection of content type filters. public MemberTypeService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -44,6 +66,20 @@ public MemberTypeService( _memberTypeRepository = memberTypeRepository; } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The member service for member-related operations. + /// The repository for member type operations. + /// The repository for audit logging (obsolete). + /// The repository for member type container operations. + /// The repository for entity operations. + /// The event aggregator for publishing notifications. + /// The resolver for converting user keys to IDs. + /// The collection of content type filters. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public MemberTypeService( ICoreScopeProvider provider, @@ -72,6 +108,21 @@ public MemberTypeService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The member service for member-related operations. + /// The repository for member type operations. + /// The service for audit logging. + /// The repository for audit logging (obsolete). + /// The repository for member type container operations. + /// The repository for entity operations. + /// The event aggregator for publishing notifications. + /// The resolver for converting user keys to IDs. + /// The collection of content type filters. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public MemberTypeService( ICoreScopeProvider provider, @@ -102,14 +153,27 @@ public MemberTypeService( } // beware! order is important to avoid deadlocks + /// protected override int[] ReadLockIds { get; } = { Constants.Locks.MemberTypes }; + /// protected override int[] WriteLockIds { get; } = { Constants.Locks.MemberTree, Constants.Locks.MemberTypes }; + /// protected override Guid ContainedObjectType => Constants.ObjectTypes.MemberType; + /// + /// Gets the member service used for member-related operations. + /// private IMemberService MemberService { get; } + /// + /// Gets the alias of the default member type. + /// + /// + /// The alias of the member type named "Member" if it exists; otherwise, the alias of the first available member type. + /// + /// Thrown when no member types are available in the system. public string GetDefault() { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -134,6 +198,10 @@ public string GetDefault() } } + /// + /// Deletes all members that use the specified member type IDs. + /// + /// The IDs of the member types whose members should be deleted. protected override void DeleteItemsOfTypes(IEnumerable typeIds) { foreach (var typeId in typeIds) @@ -144,46 +212,57 @@ protected override void DeleteItemsOfTypes(IEnumerable typeIds) #region Notifications + /// protected override SavingNotification GetSavingNotification( IMemberType item, EventMessages eventMessages) => new MemberTypeSavingNotification(item, eventMessages); + /// protected override SavingNotification GetSavingNotification( IEnumerable items, EventMessages eventMessages) => new MemberTypeSavingNotification(items, eventMessages); + /// protected override SavedNotification GetSavedNotification( IMemberType item, EventMessages eventMessages) => new MemberTypeSavedNotification(item, eventMessages); + /// protected override SavedNotification GetSavedNotification( IEnumerable items, EventMessages eventMessages) => new MemberTypeSavedNotification(items, eventMessages); + /// protected override DeletingNotification GetDeletingNotification( IMemberType item, EventMessages eventMessages) => new MemberTypeDeletingNotification(item, eventMessages); + /// protected override DeletingNotification GetDeletingNotification( IEnumerable items, EventMessages eventMessages) => new MemberTypeDeletingNotification(items, eventMessages); + /// protected override DeletedNotification GetDeletedNotification( IEnumerable items, EventMessages eventMessages) => new MemberTypeDeletedNotification(items, eventMessages); + /// protected override MovingNotification GetMovingNotification( MoveEventInfo moveInfo, EventMessages eventMessages) => new MemberTypeMovingNotification(moveInfo, eventMessages); + /// protected override MovedNotification GetMovedNotification( IEnumerable> moveInfo, EventMessages eventMessages) => new MemberTypeMovedNotification(moveInfo, eventMessages); + /// protected override ContentTypeChangeNotification GetContentTypeChangedNotification( IEnumerable> changes, EventMessages eventMessages) => new MemberTypeChangedNotification(changes, eventMessages); + /// protected override ContentTypeRefreshNotification GetContentTypeRefreshedNotification( IEnumerable> changes, EventMessages eventMessages) => new MemberTypeRefreshedNotification(changes, eventMessages); diff --git a/src/Umbraco.Core/Services/MemberValidationService.cs b/src/Umbraco.Core/Services/MemberValidationService.cs index db9e97587adb..21f929f1cc2f 100644 --- a/src/Umbraco.Core/Services/MemberValidationService.cs +++ b/src/Umbraco.Core/Services/MemberValidationService.cs @@ -1,15 +1,24 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.ContentEditing; namespace Umbraco.Cms.Core.Services; +/// +/// Service for validating member content properties against their member type definitions. +/// internal sealed class MemberValidationService : ContentValidationServiceBase, IMemberValidationService { + /// + /// Initializes a new instance of the class. + /// + /// The property validation service. + /// The language service. public MemberValidationService(IPropertyValidationService propertyValidationService, ILanguageService languageService) : base(propertyValidationService, languageService) { } + /// public async Task ValidatePropertiesAsync( ContentEditingModelBase contentEditingModelBase, IMemberType memberType, diff --git a/src/Umbraco.Core/Services/MetricsConsentService.cs b/src/Umbraco.Core/Services/MetricsConsentService.cs index 143d3ca3aa49..cd07918600b7 100644 --- a/src/Umbraco.Core/Services/MetricsConsentService.cs +++ b/src/Umbraco.Core/Services/MetricsConsentService.cs @@ -5,8 +5,14 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Service for managing telemetry consent levels for Umbraco analytics. +/// public class MetricsConsentService : IMetricsConsentService { + /// + /// The key used to store the analytics level in the key-value store. + /// internal const string Key = "UmbracoAnalyticsLevel"; private readonly IKeyValueService _keyValueService; @@ -14,6 +20,13 @@ public class MetricsConsentService : IMetricsConsentService private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; private readonly IUserService _userService; + /// + /// Initializes a new instance of the class. + /// + /// The key-value service for storing consent settings. + /// The logger. + /// The back office security accessor. + /// The user service. public MetricsConsentService( IKeyValueService keyValueService, ILogger logger, @@ -26,6 +39,7 @@ public MetricsConsentService( _userService = userService; } + /// public TelemetryLevel GetConsentLevel() { var analyticsLevelString = _keyValueService.GetValue(Key); @@ -39,6 +53,7 @@ public TelemetryLevel GetConsentLevel() return analyticsLevel; } + /// public Task SetConsentLevelAsync(TelemetryLevel telemetryLevel) { _logger.LogInformation("Telemetry level set to {telemetryLevel}", telemetryLevel); diff --git a/src/Umbraco.Core/Services/Navigation/ContentNavigationServiceBase.cs b/src/Umbraco.Core/Services/Navigation/ContentNavigationServiceBase.cs index bb849c61e779..31f81773f727 100644 --- a/src/Umbraco.Core/Services/Navigation/ContentNavigationServiceBase.cs +++ b/src/Umbraco.Core/Services/Navigation/ContentNavigationServiceBase.cs @@ -7,6 +7,17 @@ namespace Umbraco.Cms.Core.Services.Navigation; +/// +/// Abstract base class for content navigation services that provides common functionality +/// for managing hierarchical navigation structures for content and media items. +/// +/// The type of content type, must implement . +/// The type of content type service, must implement . +/// +/// This class maintains two navigation structures: a main structure for active content +/// and a recycle bin structure for trashed content. Both structures use concurrent +/// dictionaries to ensure thread-safe operations. +/// internal abstract class ContentNavigationServiceBase where TContentType : class, IContentTypeComposition where TContentTypeService : IContentTypeBaseService @@ -20,6 +31,12 @@ internal abstract class ContentNavigationServiceBase _roots = []; private HashSet _recycleBinRoots = []; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The repository for accessing navigation data. + /// The content type service for retrieving content type information. protected ContentNavigationServiceBase(ICoreScopeProvider coreScopeProvider, INavigationRepository navigationRepository, TContentTypeService typeService) { _coreScopeProvider = coreScopeProvider; @@ -38,12 +55,39 @@ protected ContentNavigationServiceBase(ICoreScopeProvider coreScopeProvider, INa /// public abstract Task RebuildBinAsync(); + /// + /// Attempts to get the parent key of a child node in the main navigation structure. + /// + /// The unique identifier of the child node. + /// + /// When this method returns, contains the parent's unique identifier if the child exists; + /// otherwise, null. The value will be null if the child is at root level. + /// + /// true if the child node exists in the structure; otherwise, false. public bool TryGetParentKey(Guid childKey, out Guid? parentKey) => TryGetParentKeyFromStructure(_navigationStructure, childKey, out parentKey); + /// + /// Attempts to get all root-level node keys from the main navigation structure. + /// + /// + /// When this method returns, contains the collection of root node keys ordered by sort order. + /// + /// true if the operation succeeds; otherwise, false. public bool TryGetRootKeys(out IEnumerable rootKeys) => TryGetRootKeysFromStructure(_roots, out rootKeys); + /// + /// Attempts to get all root-level node keys of a specific content type from the main navigation structure. + /// + /// The alias of the content type to filter by. + /// + /// When this method returns, contains the collection of root node keys of the specified + /// content type, ordered by sort order; or an empty collection if the content type doesn't exist. + /// + /// + /// true if the content type exists and root keys were retrieved; otherwise, false. + /// public bool TryGetRootKeysOfType(string contentTypeAlias, out IEnumerable rootKeys) { if (TryGetContentTypeKey(contentTypeAlias, out Guid? contentTypeKey)) @@ -56,9 +100,30 @@ public bool TryGetRootKeysOfType(string contentTypeAlias, out IEnumerable return false; } + /// + /// Attempts to get all child node keys of a parent node in the main navigation structure. + /// + /// The unique identifier of the parent node. + /// + /// When this method returns, contains the collection of child node keys ordered by sort order; + /// or an empty collection if the parent doesn't exist. + /// + /// true if the parent node exists in the structure; otherwise, false. public bool TryGetChildrenKeys(Guid parentKey, out IEnumerable childrenKeys) => TryGetChildrenKeysFromStructure(_navigationStructure, parentKey, out childrenKeys); + /// + /// Attempts to get all child node keys of a specific content type under a parent node. + /// + /// The unique identifier of the parent node. + /// The alias of the content type to filter by. + /// + /// When this method returns, contains the collection of child node keys of the specified + /// content type, ordered by sort order; or an empty collection if the parent or content type doesn't exist. + /// + /// + /// true if the parent and content type exist and children were retrieved; otherwise, false. + /// public bool TryGetChildrenKeysOfType(Guid parentKey, string contentTypeAlias, out IEnumerable childrenKeys) { if (TryGetContentTypeKey(contentTypeAlias, out Guid? contentTypeKey)) @@ -71,9 +136,30 @@ public bool TryGetChildrenKeysOfType(Guid parentKey, string contentTypeAlias, ou return false; } + /// + /// Attempts to get all descendant node keys of a parent node in the main navigation structure. + /// + /// The unique identifier of the parent node. + /// + /// When this method returns, contains the collection of all descendant node keys + /// (children, grandchildren, etc.) in depth-first order; or an empty collection if the parent doesn't exist. + /// + /// true if the parent node exists in the structure; otherwise, false. public bool TryGetDescendantsKeys(Guid parentKey, out IEnumerable descendantsKeys) => TryGetDescendantsKeysFromStructure(_navigationStructure, parentKey, out descendantsKeys); + /// + /// Attempts to get all descendant node keys of a specific content type under a parent node. + /// + /// The unique identifier of the parent node. + /// The alias of the content type to filter by. + /// + /// When this method returns, contains the collection of descendant node keys of the specified + /// content type; or an empty collection if the parent or content type doesn't exist. + /// + /// + /// true if the parent and content type exist and descendants were retrieved; otherwise, false. + /// public bool TryGetDescendantsKeysOfType(Guid parentKey, string contentTypeAlias, out IEnumerable descendantsKeys) { if (TryGetContentTypeKey(contentTypeAlias, out Guid? contentTypeKey)) @@ -86,9 +172,30 @@ public bool TryGetDescendantsKeysOfType(Guid parentKey, string contentTypeAlias, return false; } + /// + /// Attempts to get all ancestor node keys of a child node in the main navigation structure. + /// + /// The unique identifier of the child node. + /// + /// When this method returns, contains the collection of ancestor node keys + /// (parent, grandparent, etc.) starting from the immediate parent; or an empty collection if the child doesn't exist. + /// + /// true if the child node exists in the structure; otherwise, false. public bool TryGetAncestorsKeys(Guid childKey, out IEnumerable ancestorsKeys) => TryGetAncestorsKeysFromStructure(_navigationStructure, childKey, out ancestorsKeys); + /// + /// Attempts to get all ancestor node keys of a specific content type for a given node. + /// + /// The unique identifier of the node to find ancestors for. + /// The alias of the content type to filter by. + /// + /// When this method returns, contains the collection of ancestor node keys of the specified + /// content type; or an empty collection if the node or content type doesn't exist. + /// + /// + /// true if the node and content type exist and ancestors were retrieved; otherwise, false. + /// public bool TryGetAncestorsKeysOfType(Guid parentKey, string contentTypeAlias, out IEnumerable ancestorsKeys) { if (TryGetContentTypeKey(contentTypeAlias, out Guid? contentTypeKey)) @@ -101,9 +208,31 @@ public bool TryGetAncestorsKeysOfType(Guid parentKey, string contentTypeAlias, o return false; } + /// + /// Attempts to get all sibling node keys of a node in the main navigation structure. + /// + /// The unique identifier of the node. + /// + /// When this method returns, contains the collection of sibling node keys + /// (nodes with the same parent, excluding the node itself), ordered by sort order; + /// or an empty collection if the node doesn't exist. + /// + /// true if the node exists in the structure; otherwise, false. public bool TryGetSiblingsKeys(Guid key, out IEnumerable siblingsKeys) => TryGetSiblingsKeysFromStructure(_navigationStructure, key, out siblingsKeys); + /// + /// Attempts to get all sibling node keys of a specific content type for a given node. + /// + /// The unique identifier of the node. + /// The alias of the content type to filter by. + /// + /// When this method returns, contains the collection of sibling node keys of the specified + /// content type, ordered by sort order; or an empty collection if the node or content type doesn't exist. + /// + /// + /// true if the node and content type exist and siblings were retrieved; otherwise, false. + /// public bool TryGetSiblingsKeysOfType(Guid key, string contentTypeAlias, out IEnumerable siblingsKeys) { if (TryGetContentTypeKey(contentTypeAlias, out Guid? contentTypeKey)) @@ -116,21 +245,75 @@ public bool TryGetSiblingsKeysOfType(Guid key, string contentTypeAlias, out IEnu return false; } + /// + /// Attempts to get the parent key of a child node in the recycle bin navigation structure. + /// + /// The unique identifier of the child node in the recycle bin. + /// + /// When this method returns, contains the parent's unique identifier if the child exists in the bin; + /// otherwise, null. The value will be null if the child is at bin root level. + /// + /// true if the child node exists in the recycle bin; otherwise, false. public bool TryGetParentKeyInBin(Guid childKey, out Guid? parentKey) => TryGetParentKeyFromStructure(_recycleBinNavigationStructure, childKey, out parentKey); + /// + /// Attempts to get all child node keys of a parent node in the recycle bin navigation structure. + /// + /// The unique identifier of the parent node in the recycle bin. + /// + /// When this method returns, contains the collection of child node keys ordered by sort order; + /// or an empty collection if the parent doesn't exist in the bin. + /// + /// true if the parent node exists in the recycle bin; otherwise, false. public bool TryGetChildrenKeysInBin(Guid parentKey, out IEnumerable childrenKeys) => TryGetChildrenKeysFromStructure(_recycleBinNavigationStructure, parentKey, out childrenKeys); + /// + /// Attempts to get all descendant node keys of a parent node in the recycle bin navigation structure. + /// + /// The unique identifier of the parent node in the recycle bin. + /// + /// When this method returns, contains the collection of all descendant node keys in the bin; + /// or an empty collection if the parent doesn't exist. + /// + /// true if the parent node exists in the recycle bin; otherwise, false. public bool TryGetDescendantsKeysInBin(Guid parentKey, out IEnumerable descendantsKeys) => TryGetDescendantsKeysFromStructure(_recycleBinNavigationStructure, parentKey, out descendantsKeys); + /// + /// Attempts to get all ancestor node keys of a child node in the recycle bin navigation structure. + /// + /// The unique identifier of the child node in the recycle bin. + /// + /// When this method returns, contains the collection of ancestor node keys in the bin; + /// or an empty collection if the child doesn't exist. + /// + /// true if the child node exists in the recycle bin; otherwise, false. public bool TryGetAncestorsKeysInBin(Guid childKey, out IEnumerable ancestorsKeys) => TryGetAncestorsKeysFromStructure(_recycleBinNavigationStructure, childKey, out ancestorsKeys); + /// + /// Attempts to get all sibling node keys of a node in the recycle bin navigation structure. + /// + /// The unique identifier of the node in the recycle bin. + /// + /// When this method returns, contains the collection of sibling node keys in the bin, + /// ordered by sort order; or an empty collection if the node doesn't exist. + /// + /// true if the node exists in the recycle bin; otherwise, false. public bool TryGetSiblingsKeysInBin(Guid key, out IEnumerable siblingsKeys) => TryGetSiblingsKeysFromStructure(_recycleBinNavigationStructure, key, out siblingsKeys); + /// + /// Attempts to get the hierarchical level of a content node in the main navigation structure. + /// + /// The unique identifier of the content node. + /// + /// When this method returns, contains the level of the node (1 for root-level nodes, + /// 2 for their children, etc.); or null if the node doesn't exist. + /// + /// true if the node exists and its level was determined; otherwise, false. public bool TryGetLevel(Guid contentKey, [NotNullWhen(true)] out int? level) { level = 1; @@ -154,6 +337,14 @@ public bool TryGetLevel(Guid contentKey, [NotNullWhen(true)] out int? level) return true; } + /// + /// Moves a node and all its descendants from the main navigation structure to the recycle bin. + /// + /// The unique identifier of the node to move to the recycle bin. + /// + /// true if the node and its descendants were successfully moved to the recycle bin; + /// otherwise, false if the node doesn't exist. + /// public bool MoveToBin(Guid key) { if (TryRemoveNodeFromParentInStructure(_navigationStructure, key, out NavigationNode? nodeToRemove) is false || nodeToRemove is null) @@ -170,6 +361,21 @@ public bool MoveToBin(Guid key) _navigationStructure.TryRemove(key, out _); } + /// + /// Adds a new node to the main navigation structure. + /// + /// The unique identifier of the new node. + /// The unique identifier of the node's content type. + /// + /// The unique identifier of the parent node. If null, the node is added at root level. + /// + /// + /// The sort order for the new node. Required when adding nodes at root level. + /// + /// + /// true if the node was successfully added; otherwise, false if the parent + /// doesn't exist or a node with the same key already exists. + /// public bool Add(Guid key, Guid contentTypeKey, Guid? parentKey = null, int? sortOrder = null) { NavigationNode? parentNode = null; @@ -197,6 +403,17 @@ public bool Add(Guid key, Guid contentTypeKey, Guid? parentKey = null, int? sort return true; } + /// + /// Moves an existing node to a new location in the main navigation structure. + /// + /// The unique identifier of the node to move. + /// + /// The unique identifier of the new parent node. If null, the node is moved to root level. + /// + /// + /// true if the node was successfully moved; otherwise, false if the node doesn't exist, + /// the target parent doesn't exist, or the node is being moved to itself. + /// public bool Move(Guid key, Guid? targetParentKey = null) { if (_navigationStructure.TryGetValue(key, out NavigationNode? nodeToMove) is false) @@ -236,6 +453,14 @@ public bool Move(Guid key, Guid? targetParentKey = null) return true; } + /// + /// Updates the sort order of a node in the main navigation structure. + /// + /// The unique identifier of the node to update. + /// The new sort order value. + /// + /// true if the sort order was successfully updated; otherwise, false if the node doesn't exist. + /// public bool UpdateSortOrder(Guid key, int newSortOrder) { if (_navigationStructure.TryGetValue(key, out NavigationNode? node) is false) @@ -248,6 +473,14 @@ public bool UpdateSortOrder(Guid key, int newSortOrder) return true; } + /// + /// Permanently removes a node and all its descendants from the recycle bin navigation structure. + /// + /// The unique identifier of the node to remove from the recycle bin. + /// + /// true if the node and its descendants were successfully removed from the recycle bin; + /// otherwise, false if the node doesn't exist in the bin. + /// public bool RemoveFromBin(Guid key) { if (TryRemoveNodeFromParentInStructure(_recycleBinNavigationStructure, key, out NavigationNode? nodeToRemove) is false || nodeToRemove is null) @@ -262,6 +495,18 @@ public bool RemoveFromBin(Guid key) return _recycleBinNavigationStructure.TryRemove(key, out _); } + /// + /// Restores a node and all its descendants from the recycle bin to the main navigation structure. + /// + /// The unique identifier of the node to restore. + /// + /// The unique identifier of the target parent node in the main structure. + /// If null, the node is restored to root level. + /// + /// + /// true if the node and its descendants were successfully restored; + /// otherwise, false if the node doesn't exist in the bin or the target parent doesn't exist. + /// public bool RestoreFromBin(Guid key, Guid? targetParentKey = null) { if (_recycleBinNavigationStructure.TryGetValue(key, out NavigationNode? nodeToRestore) is false) diff --git a/src/Umbraco.Core/Services/Navigation/DocumentNavigationService.cs b/src/Umbraco.Core/Services/Navigation/DocumentNavigationService.cs index 0f550be206f4..160e7f318527 100644 --- a/src/Umbraco.Core/Services/Navigation/DocumentNavigationService.cs +++ b/src/Umbraco.Core/Services/Navigation/DocumentNavigationService.cs @@ -4,16 +4,33 @@ namespace Umbraco.Cms.Core.Services.Navigation; +/// +/// Provides navigation services for document (content) items, including querying and managing +/// the document navigation structure and its recycle bin. +/// +/// +/// This service extends +/// and implements both and +/// to provide a complete set of navigation operations for document content. +/// internal sealed class DocumentNavigationService : ContentNavigationServiceBase, IDocumentNavigationQueryService, IDocumentNavigationManagementService { + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The repository for accessing navigation data. + /// The content type service for retrieving content type information. public DocumentNavigationService(ICoreScopeProvider coreScopeProvider, INavigationRepository navigationRepository, IContentTypeService contentTypeService) : base(coreScopeProvider, navigationRepository, contentTypeService) { } + /// public override async Task RebuildAsync() => await HandleRebuildAsync(Constants.Locks.ContentTree, Constants.ObjectTypes.Document, false); + /// public override async Task RebuildBinAsync() => await HandleRebuildAsync(Constants.Locks.ContentTree, Constants.ObjectTypes.Document, true); } diff --git a/src/Umbraco.Core/Services/Navigation/IDocumentNavigationManagementService.cs b/src/Umbraco.Core/Services/Navigation/IDocumentNavigationManagementService.cs index 789256329ee5..0c257cd6fa26 100644 --- a/src/Umbraco.Core/Services/Navigation/IDocumentNavigationManagementService.cs +++ b/src/Umbraco.Core/Services/Navigation/IDocumentNavigationManagementService.cs @@ -1,5 +1,14 @@ namespace Umbraco.Cms.Core.Services.Navigation; +/// +/// Provides management operations for the document navigation structure. +/// +/// +/// This interface combines and +/// to provide a complete +/// set of management operations for document navigation, including adding, moving, +/// and managing documents in the recycle bin. +/// public interface IDocumentNavigationManagementService : INavigationManagementService, IRecycleBinNavigationManagementService { } diff --git a/src/Umbraco.Core/Services/Navigation/IDocumentNavigationQueryService.cs b/src/Umbraco.Core/Services/Navigation/IDocumentNavigationQueryService.cs index d8fb5e0c2951..56e0e1bee74b 100644 --- a/src/Umbraco.Core/Services/Navigation/IDocumentNavigationQueryService.cs +++ b/src/Umbraco.Core/Services/Navigation/IDocumentNavigationQueryService.cs @@ -1,5 +1,14 @@ namespace Umbraco.Cms.Core.Services.Navigation; +/// +/// Provides query operations for the document navigation structure. +/// +/// +/// This interface combines and +/// to provide a complete +/// set of query operations for document navigation, including traversing +/// the main structure and the recycle bin. +/// public interface IDocumentNavigationQueryService : INavigationQueryService, IRecycleBinNavigationQueryService { } diff --git a/src/Umbraco.Core/Services/Navigation/IMediaNavigationManagementService.cs b/src/Umbraco.Core/Services/Navigation/IMediaNavigationManagementService.cs index 95cb1c96168b..10a46022c649 100644 --- a/src/Umbraco.Core/Services/Navigation/IMediaNavigationManagementService.cs +++ b/src/Umbraco.Core/Services/Navigation/IMediaNavigationManagementService.cs @@ -1,5 +1,14 @@ namespace Umbraco.Cms.Core.Services.Navigation; +/// +/// Provides management operations for the media navigation structure. +/// +/// +/// This interface combines and +/// to provide a complete +/// set of management operations for media navigation, including adding, moving, +/// and managing media items in the recycle bin. +/// public interface IMediaNavigationManagementService : INavigationManagementService, IRecycleBinNavigationManagementService { } diff --git a/src/Umbraco.Core/Services/Navigation/IMediaNavigationQueryService.cs b/src/Umbraco.Core/Services/Navigation/IMediaNavigationQueryService.cs index e3f46f421148..5bf52b296876 100644 --- a/src/Umbraco.Core/Services/Navigation/IMediaNavigationQueryService.cs +++ b/src/Umbraco.Core/Services/Navigation/IMediaNavigationQueryService.cs @@ -1,5 +1,14 @@ namespace Umbraco.Cms.Core.Services.Navigation; +/// +/// Provides query operations for the media navigation structure. +/// +/// +/// This interface combines and +/// to provide a complete +/// set of query operations for media navigation, including traversing +/// the main structure and the recycle bin. +/// public interface IMediaNavigationQueryService : INavigationQueryService, IRecycleBinNavigationQueryService { } diff --git a/src/Umbraco.Core/Services/Navigation/INavigationManagementService.cs b/src/Umbraco.Core/Services/Navigation/INavigationManagementService.cs index cf3d172278bb..36725565cd09 100644 --- a/src/Umbraco.Core/Services/Navigation/INavigationManagementService.cs +++ b/src/Umbraco.Core/Services/Navigation/INavigationManagementService.cs @@ -4,12 +4,17 @@ namespace Umbraco.Cms.Core.Services.Navigation; /// Placeholder for sharing logic between the document and media navigation services /// for managing the navigation structure. /// +/// +/// This interface defines methods for managing the main navigation structure, +/// including rebuilding, adding, moving, and managing content nodes. +/// public interface INavigationManagementService { /// /// Rebuilds the entire navigation structure by refreshing the navigation tree based /// on the current state of the underlying repository. /// + /// A task representing the asynchronous rebuild operation. Task RebuildAsync(); /// diff --git a/src/Umbraco.Core/Services/Navigation/INavigationQueryService.cs b/src/Umbraco.Core/Services/Navigation/INavigationQueryService.cs index 6ea28c85112a..0849ba7616be 100644 --- a/src/Umbraco.Core/Services/Navigation/INavigationQueryService.cs +++ b/src/Umbraco.Core/Services/Navigation/INavigationQueryService.cs @@ -7,20 +7,91 @@ namespace Umbraco.Cms.Core.Services.Navigation; /// Placeholder for sharing logic between the document and media navigation services /// for querying the navigation structure. /// +/// +/// This interface defines methods for traversing and querying the main navigation structure, +/// including operations for retrieving parent, children, descendants, ancestors, siblings, +/// and level information for content nodes. +/// public interface INavigationQueryService { + /// + /// Attempts to get the parent key of a child node. + /// + /// The unique identifier of the child node. + /// + /// When this method returns, contains the parent's unique identifier if the child exists; + /// otherwise, null. The value will be null if the child is at root level. + /// + /// true if the child node exists in the structure; otherwise, false. bool TryGetParentKey(Guid childKey, out Guid? parentKey); + /// + /// Attempts to get all root-level node keys. + /// + /// + /// When this method returns, contains the collection of root node keys ordered by sort order. + /// + /// true if the operation succeeds; otherwise, false. bool TryGetRootKeys(out IEnumerable rootKeys); + /// + /// Attempts to get all root-level node keys of a specific content type. + /// + /// The alias of the content type to filter by. + /// + /// When this method returns, contains the collection of root node keys of the specified + /// content type, ordered by sort order; or an empty collection if the content type doesn't exist. + /// + /// + /// true if the content type exists and root keys were retrieved; otherwise, false. + /// bool TryGetRootKeysOfType(string contentTypeAlias, out IEnumerable rootKeys); + /// + /// Attempts to get all child node keys of a parent node. + /// + /// The unique identifier of the parent node. + /// + /// When this method returns, contains the collection of child node keys ordered by sort order; + /// or an empty collection if the parent doesn't exist. + /// + /// true if the parent node exists in the structure; otherwise, false. bool TryGetChildrenKeys(Guid parentKey, out IEnumerable childrenKeys); + /// + /// Attempts to get all child node keys of a specific content type under a parent node. + /// + /// The unique identifier of the parent node. + /// The alias of the content type to filter by. + /// + /// When this method returns, contains the collection of child node keys of the specified + /// content type, ordered by sort order; or an empty collection if the parent or content type doesn't exist. + /// + /// + /// true if the parent and content type exist and children were retrieved; otherwise, false. + /// bool TryGetChildrenKeysOfType(Guid parentKey, string contentTypeAlias, out IEnumerable childrenKeys); + /// + /// Attempts to get all descendant node keys of a parent node. + /// + /// The unique identifier of the parent node. + /// + /// When this method returns, contains the collection of all descendant node keys + /// (children, grandchildren, etc.); or an empty collection if the parent doesn't exist. + /// + /// true if the parent node exists in the structure; otherwise, false. bool TryGetDescendantsKeys(Guid parentKey, out IEnumerable descendantsKeys); + /// + /// Attempts to get all descendant node keys including the parent node itself. + /// + /// The unique identifier of the parent node. + /// + /// When this method returns, contains the parent's key followed by all its descendant keys; + /// or an empty collection if the parent doesn't exist. + /// + /// true if the parent node exists in the structure; otherwise, false. bool TryGetDescendantsKeysOrSelfKeys(Guid parentKey, out IEnumerable descendantsOrSelfKeys) { if (TryGetDescendantsKeys(parentKey, out IEnumerable? descendantsKeys)) @@ -33,10 +104,40 @@ bool TryGetDescendantsKeysOrSelfKeys(Guid parentKey, out IEnumerable desce return false; } + /// + /// Attempts to get all descendant node keys of a specific content type under a parent node. + /// + /// The unique identifier of the parent node. + /// The alias of the content type to filter by. + /// + /// When this method returns, contains the collection of descendant node keys of the specified + /// content type; or an empty collection if the parent or content type doesn't exist. + /// + /// + /// true if the parent and content type exist and descendants were retrieved; otherwise, false. + /// bool TryGetDescendantsKeysOfType(Guid parentKey, string contentTypeAlias, out IEnumerable descendantsKeys); + /// + /// Attempts to get all ancestor node keys of a child node. + /// + /// The unique identifier of the child node. + /// + /// When this method returns, contains the collection of ancestor node keys + /// (parent, grandparent, etc.); or an empty collection if the child doesn't exist. + /// + /// true if the child node exists in the structure; otherwise, false. bool TryGetAncestorsKeys(Guid childKey, out IEnumerable ancestorsKeys); + /// + /// Attempts to get all ancestor node keys including the child node itself. + /// + /// The unique identifier of the child node. + /// + /// When this method returns, contains the child's key followed by all its ancestor keys; + /// or an empty collection if the child doesn't exist. + /// + /// true if the child node exists in the structure; otherwise, false. bool TryGetAncestorsOrSelfKeys(Guid childKey, out IEnumerable ancestorsOrSelfKeys) { if (TryGetAncestorsKeys(childKey, out IEnumerable? ancestorsKeys)) @@ -49,11 +150,53 @@ bool TryGetAncestorsOrSelfKeys(Guid childKey, out IEnumerable ancestorsOrS return false; } + /// + /// Attempts to get all ancestor node keys of a specific content type for a given node. + /// + /// The unique identifier of the node to find ancestors for. + /// The alias of the content type to filter by. + /// + /// When this method returns, contains the collection of ancestor node keys of the specified + /// content type; or an empty collection if the node or content type doesn't exist. + /// + /// + /// true if the node and content type exist and ancestors were retrieved; otherwise, false. + /// bool TryGetAncestorsKeysOfType(Guid parentKey, string contentTypeAlias, out IEnumerable ancestorsKeys); + /// + /// Attempts to get all sibling node keys of a node. + /// + /// The unique identifier of the node. + /// + /// When this method returns, contains the collection of sibling node keys + /// (excluding the node itself), ordered by sort order; or an empty collection if the node doesn't exist. + /// + /// true if the node exists in the structure; otherwise, false. bool TryGetSiblingsKeys(Guid key, out IEnumerable siblingsKeys); + /// + /// Attempts to get all sibling node keys of a specific content type for a given node. + /// + /// The unique identifier of the node. + /// The alias of the content type to filter by. + /// + /// When this method returns, contains the collection of sibling node keys of the specified + /// content type, ordered by sort order; or an empty collection if the node or content type doesn't exist. + /// + /// + /// true if the node and content type exist and siblings were retrieved; otherwise, false. + /// bool TryGetSiblingsKeysOfType(Guid key, string contentTypeAlias, out IEnumerable siblingsKeys); + /// + /// Attempts to get the hierarchical level of a content node. + /// + /// The unique identifier of the content node. + /// + /// When this method returns, contains the level of the node (1 for root-level nodes, + /// 2 for their children, etc.); or null if the node doesn't exist. + /// + /// true if the node exists and its level was determined; otherwise, false. bool TryGetLevel(Guid contentKey, [NotNullWhen(true)] out int? level); } diff --git a/src/Umbraco.Core/Services/Navigation/IRecycleBinNavigationManagementService.cs b/src/Umbraco.Core/Services/Navigation/IRecycleBinNavigationManagementService.cs index 07c415136291..ded0e22180c8 100644 --- a/src/Umbraco.Core/Services/Navigation/IRecycleBinNavigationManagementService.cs +++ b/src/Umbraco.Core/Services/Navigation/IRecycleBinNavigationManagementService.cs @@ -4,12 +4,17 @@ namespace Umbraco.Cms.Core.Services.Navigation; /// Placeholder for sharing logic between the document and media navigation services /// for managing the recycle bin navigation structure. /// +/// +/// This interface defines methods for managing items in the recycle bin, +/// including rebuilding, removing, and restoring items. +/// public interface IRecycleBinNavigationManagementService { /// /// Rebuilds the recycle bin navigation structure by fetching the latest trashed nodes /// from the underlying repository. /// + /// A task representing the asynchronous rebuild operation. Task RebuildBinAsync(); /// diff --git a/src/Umbraco.Core/Services/Navigation/IRecycleBinNavigationQueryService.cs b/src/Umbraco.Core/Services/Navigation/IRecycleBinNavigationQueryService.cs index 12578d5875c3..a48d512d2ead 100644 --- a/src/Umbraco.Core/Services/Navigation/IRecycleBinNavigationQueryService.cs +++ b/src/Umbraco.Core/Services/Navigation/IRecycleBinNavigationQueryService.cs @@ -6,14 +6,54 @@ namespace Umbraco.Cms.Core.Services.Navigation; /// Placeholder for sharing logic between the document and media navigation services /// for querying the recycle bin navigation structure. /// +/// +/// This interface defines methods for traversing and querying the recycle bin +/// navigation structure, including parent, children, descendants, ancestors, and siblings. +/// public interface IRecycleBinNavigationQueryService { + /// + /// Attempts to get the parent key of a child node in the recycle bin. + /// + /// The unique identifier of the child node. + /// + /// When this method returns, contains the parent's unique identifier if the child exists; + /// otherwise, null. The value will be null if the child is at bin root level. + /// + /// true if the child node exists in the recycle bin; otherwise, false. bool TryGetParentKeyInBin(Guid childKey, out Guid? parentKey); + /// + /// Attempts to get all child node keys of a parent node in the recycle bin. + /// + /// The unique identifier of the parent node. + /// + /// When this method returns, contains the collection of child node keys ordered by sort order; + /// or an empty collection if the parent doesn't exist. + /// + /// true if the parent node exists in the recycle bin; otherwise, false. bool TryGetChildrenKeysInBin(Guid parentKey, out IEnumerable childrenKeys); + /// + /// Attempts to get all descendant node keys of a parent node in the recycle bin. + /// + /// The unique identifier of the parent node. + /// + /// When this method returns, contains the collection of all descendant node keys; + /// or an empty collection if the parent doesn't exist. + /// + /// true if the parent node exists in the recycle bin; otherwise, false. bool TryGetDescendantsKeysInBin(Guid parentKey, out IEnumerable descendantsKeys); + /// + /// Attempts to get all descendant node keys including the node itself in the recycle bin. + /// + /// The unique identifier of the node. + /// + /// When this method returns, contains the node's key followed by all its descendant keys; + /// or an empty collection if the node doesn't exist. + /// + /// true if the node exists in the recycle bin; otherwise, false. bool TryGetDescendantsKeysOrSelfKeysInBin(Guid childKey, out IEnumerable descendantsOrSelfKeys) { if (TryGetDescendantsKeysInBin(childKey, out IEnumerable? descendantsKeys)) @@ -27,7 +67,25 @@ bool TryGetDescendantsKeysOrSelfKeysInBin(Guid childKey, out IEnumerable d } + /// + /// Attempts to get all ancestor node keys of a child node in the recycle bin. + /// + /// The unique identifier of the child node. + /// + /// When this method returns, contains the collection of ancestor node keys + /// (parent, grandparent, etc.); or an empty collection if the child doesn't exist. + /// + /// true if the child node exists in the recycle bin; otherwise, false. bool TryGetAncestorsKeysInBin(Guid childKey, out IEnumerable ancestorsKeys); + /// + /// Attempts to get all sibling node keys of a node in the recycle bin. + /// + /// The unique identifier of the node. + /// + /// When this method returns, contains the collection of sibling node keys + /// (excluding the node itself), ordered by sort order; or an empty collection if the node doesn't exist. + /// + /// true if the node exists in the recycle bin; otherwise, false. bool TryGetSiblingsKeysInBin(Guid key, out IEnumerable siblingsKeys); } diff --git a/src/Umbraco.Core/Services/Navigation/MediaNavigationService.cs b/src/Umbraco.Core/Services/Navigation/MediaNavigationService.cs index 5a0c3c47d6d5..dfaabc771350 100644 --- a/src/Umbraco.Core/Services/Navigation/MediaNavigationService.cs +++ b/src/Umbraco.Core/Services/Navigation/MediaNavigationService.cs @@ -4,16 +4,33 @@ namespace Umbraco.Cms.Core.Services.Navigation; +/// +/// Provides navigation services for media items, including querying and managing +/// the media navigation structure and its recycle bin. +/// +/// +/// This service extends +/// and implements both and +/// to provide a complete set of navigation operations for media content. +/// internal sealed class MediaNavigationService : ContentNavigationServiceBase, IMediaNavigationQueryService, IMediaNavigationManagementService { + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The repository for accessing navigation data. + /// The media type service for retrieving media type information. public MediaNavigationService(ICoreScopeProvider coreScopeProvider, INavigationRepository navigationRepository, IMediaTypeService mediaTypeService) : base(coreScopeProvider, navigationRepository, mediaTypeService) { } + /// public override async Task RebuildAsync() => await HandleRebuildAsync(Constants.Locks.MediaTree, Constants.ObjectTypes.Media, false); + /// public override async Task RebuildBinAsync() => await HandleRebuildAsync(Constants.Locks.MediaTree, Constants.ObjectTypes.Media, true); } diff --git a/src/Umbraco.Core/Services/Navigation/NavigationInitializationNotificationHandler.cs b/src/Umbraco.Core/Services/Navigation/NavigationInitializationNotificationHandler.cs index 693c3bf6aa52..1d2538981b50 100644 --- a/src/Umbraco.Core/Services/Navigation/NavigationInitializationNotificationHandler.cs +++ b/src/Umbraco.Core/Services/Navigation/NavigationInitializationNotificationHandler.cs @@ -8,12 +8,23 @@ namespace Umbraco.Cms.Core.Services.Navigation; /// Responsible for seeding the in-memory navigation structures at application's startup /// by rebuild the navigation structures. /// +/// +/// This handler listens for the and +/// triggers a rebuild of both document and media navigation structures, including their +/// respective recycle bins. +/// public sealed class NavigationInitializationNotificationHandler : INotificationAsyncHandler { private readonly IRuntimeState _runtimeState; private readonly IDocumentNavigationManagementService _documentNavigationManagementService; private readonly IMediaNavigationManagementService _mediaNavigationManagementService; + /// + /// Initializes a new instance of the class. + /// + /// The runtime state service for checking the current runtime level. + /// The document navigation management service. + /// The media navigation management service. public NavigationInitializationNotificationHandler( IRuntimeState runtimeState, IDocumentNavigationManagementService documentNavigationManagementService, @@ -24,6 +35,18 @@ public NavigationInitializationNotificationHandler( _mediaNavigationManagementService = mediaNavigationManagementService; } + /// + /// Handles the by rebuilding + /// the navigation structures for documents and media. + /// + /// The notification instance. + /// A cancellation token to observe while waiting for the task to complete. + /// A task representing the asynchronous operation. + /// + /// This method only executes when the runtime level is at or above . + /// It rebuilds both the main navigation structures and the recycle bin structures for + /// documents and media. + /// public async Task HandleAsync(PostRuntimePremigrationsUpgradeNotification notification, CancellationToken cancellationToken) { if(_runtimeState.Level < RuntimeLevel.Upgrade) diff --git a/src/Umbraco.Core/Services/NodeCountService.cs b/src/Umbraco.Core/Services/NodeCountService.cs index cf7417058e0e..25d8442c1154 100644 --- a/src/Umbraco.Core/Services/NodeCountService.cs +++ b/src/Umbraco.Core/Services/NodeCountService.cs @@ -4,23 +4,37 @@ namespace Umbraco.Cms.Infrastructure.Services.Implement; +/// +/// Provides services for counting nodes in the Umbraco content tree. +/// +/// +/// This service is typically used for dashboard statistics, licensing checks, +/// and other scenarios where total counts of content, media, or other node types are needed. +/// public class NodeCountService : INodeCountService { private readonly INodeCountRepository _nodeCountRepository; private readonly ICoreScopeProvider _scopeProvider; + /// + /// Initializes a new instance of the class. + /// + /// The repository for node count operations. + /// The core scope provider for database operations. public NodeCountService(INodeCountRepository nodeCountRepository, ICoreScopeProvider scopeProvider) { _nodeCountRepository = nodeCountRepository; _scopeProvider = scopeProvider; } + /// public int GetNodeCount(Guid nodeType) { using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true); return _nodeCountRepository.GetNodeCount(nodeType); } + /// public int GetMediaCount() { using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true); diff --git a/src/Umbraco.Core/Services/NoopSegmentService.cs b/src/Umbraco.Core/Services/NoopSegmentService.cs index 5b1f65029b15..f6a0a00460dd 100644 --- a/src/Umbraco.Core/Services/NoopSegmentService.cs +++ b/src/Umbraco.Core/Services/NoopSegmentService.cs @@ -3,8 +3,13 @@ namespace Umbraco.Cms.Core.Services; +/// +/// A no-operation implementation of that returns empty results. +/// Used as a default when no segment provider is configured. +/// public class NoopSegmentService : ISegmentService { + /// public Task?, SegmentOperationStatus>> GetPagedSegmentsAsync(int skip = 0, int take = 100) { return Task.FromResult(Attempt.SucceedWithStatus?, SegmentOperationStatus>( diff --git a/src/Umbraco.Core/Services/NotificationService.cs b/src/Umbraco.Core/Services/NotificationService.cs index 89c6e6e4ed9b..fe97f35a4a76 100644 --- a/src/Umbraco.Core/Services/NotificationService.cs +++ b/src/Umbraco.Core/Services/NotificationService.cs @@ -17,6 +17,10 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing and sending notifications to users +/// when content is modified. +/// public class NotificationService : INotificationService { // manage notifications @@ -34,6 +38,19 @@ public class NotificationService : INotificationService private readonly ICoreScopeProvider _uowProvider; private readonly IUserService _userService; + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for unit of work operations. + /// The user service for retrieving user information. + /// The content service for accessing content versions. + /// The localization service for language operations. + /// The logger for diagnostic output. + /// The IO helper for resolving paths. + /// The repository for notification data access. + /// The global settings options. + /// The content settings options. + /// The email sender for delivering notifications. public NotificationService( ICoreScopeProvider provider, IUserService userService, @@ -597,8 +614,18 @@ private void Process(BlockingCollection notificationRequest } } + /// + /// Represents a notification request to be processed. + /// private sealed class NotificationRequest { + /// + /// Initializes a new instance of the class. + /// + /// The email message to send. + /// The action that triggered the notification. + /// The name of the user receiving the notification. + /// The email address of the user receiving the notification. public NotificationRequest(EmailMessage mail, string? action, string? userName, string? email) { Mail = mail; @@ -607,12 +634,24 @@ public NotificationRequest(EmailMessage mail, string? action, string? userName, Email = email; } + /// + /// Gets the email message to send. + /// public EmailMessage Mail { get; } + /// + /// Gets the action that triggered the notification. + /// public string? Action { get; } + /// + /// Gets the name of the user receiving the notification. + /// public string? UserName { get; } + /// + /// Gets the email address of the user receiving the notification. + /// public string? Email { get; } } diff --git a/src/Umbraco.Core/Services/OperationResult.cs b/src/Umbraco.Core/Services/OperationResult.cs index 919077919c4b..145d8da2a61d 100644 --- a/src/Umbraco.Core/Services/OperationResult.cs +++ b/src/Umbraco.Core/Services/OperationResult.cs @@ -18,6 +18,12 @@ namespace Umbraco.Cms.Core.Services; public class OperationResult where TResultType : struct { + /// + /// Static constructor that validates the type parameter constraints. + /// + /// + /// Thrown when is not an enum or its underlying type is not . + /// static OperationResult() { // ensure that TResultType is an enum and the underlying type is byte @@ -37,6 +43,8 @@ static OperationResult() /// /// Initializes a new instance of the class. /// + /// The result status of the operation. + /// The event messages produced by the operation, or null if none. public OperationResult(TResultType result, EventMessages? eventMessages) { Result = result; @@ -116,14 +124,31 @@ public OperationResult(OperationResultType result, EventMessages eventMessages) { } + /// + /// Creates a successful operation result. + /// + /// The event messages produced by the operation. + /// A new instance indicating success. public static OperationResult Succeed(EventMessages eventMessages) => new OperationResult(OperationResultType.Success, eventMessages); + /// + /// Creates a cancelled operation result. + /// + /// The event messages produced by the operation. + /// A new instance indicating the operation was cancelled by an event. public static OperationResult Cancel(EventMessages eventMessages) => new OperationResult(OperationResultType.FailedCancelledByEvent, eventMessages); // TODO: this exists to support services that still return Attempt // these services should directly return an OperationResult, and then this static class should be deleted + /// + /// Provides factory methods for creating instances wrapping objects. + /// + /// + /// This static class exists to support services that still return Attempt<OperationResult>. + /// These services should directly return an , and then this static class should be deleted. + /// public static class Attempt { /// @@ -134,20 +159,49 @@ public static class Attempt public static Attempt Succeed(EventMessages eventMessages) => Core.Attempt.Succeed(new OperationResult(OperationResultType.Success, eventMessages)); + /// + /// Creates a successful operation attempt with a typed value. + /// + /// The type of the entity value. + /// The event messages produced by the operation. + /// A new attempt instance indicating success. public static Attempt?> Succeed(EventMessages eventMessages) => Core.Attempt.Succeed( new OperationResult(OperationResultType.Success, eventMessages)); + /// + /// Creates a successful operation attempt with a typed value and entity. + /// + /// The type of the entity value. + /// The event messages produced by the operation. + /// The entity value associated with the operation. + /// A new attempt instance indicating success. public static Attempt?> Succeed(EventMessages eventMessages, TValue value) => Core.Attempt.Succeed( new OperationResult(OperationResultType.Success, eventMessages, value)); + /// + /// Creates a successful operation attempt with a custom status type. + /// + /// The type of the status enumeration. + /// The status type indicating the operation result. + /// The event messages produced by the operation. + /// A new attempt instance indicating success. public static Attempt?> Succeed( TStatusType statusType, EventMessages eventMessages) where TStatusType : struct => Core.Attempt.Succeed(new OperationResult(statusType, eventMessages)); + /// + /// Creates a successful operation attempt with a custom status type and entity value. + /// + /// The type of the status enumeration. + /// The type of the entity value. + /// The status type indicating the operation result. + /// The event messages produced by the operation. + /// The entity value associated with the operation. + /// A new attempt instance indicating success. public static Attempt?> Succeed( TStatusType statusType, EventMessages eventMessages, TValue value) where TStatusType : struct => @@ -169,12 +223,25 @@ public static Attempt?> public static Attempt Cancel(EventMessages eventMessages) => Core.Attempt.Fail(new OperationResult(OperationResultType.FailedCancelledByEvent, eventMessages)); + /// + /// Creates a failed operation attempt indicating that the operation was cancelled, with a typed value. + /// + /// The type of the entity value. + /// The event messages produced by the operation. + /// A new attempt instance indicating cancellation. public static Attempt?> Cancel(EventMessages eventMessages) => Core.Attempt.Fail( new OperationResult( OperationResultType.FailedCancelledByEvent, eventMessages)); + /// + /// Creates a failed operation attempt indicating that the operation was cancelled, with a typed value and entity. + /// + /// The type of the entity value. + /// The event messages produced by the operation. + /// The entity value associated with the operation. + /// A new attempt instance indicating cancellation. public static Attempt?> Cancel(EventMessages eventMessages, TValue value) => Core.Attempt.Fail( new OperationResult(OperationResultType.FailedCancelledByEvent, eventMessages, value)); @@ -193,17 +260,39 @@ public static Attempt?> exception); } + /// + /// Creates a failed operation attempt indicating that an exception was thrown, with a typed value. + /// + /// The type of the entity value. + /// The event messages produced by the operation. + /// The exception that caused the operation to fail. + /// A new attempt instance indicating failure due to an exception. public static Attempt?> Fail(EventMessages eventMessages, Exception exception) => Core.Attempt.Fail( new OperationResult(OperationResultType.FailedExceptionThrown, eventMessages), exception); + /// + /// Creates a failed operation attempt with a custom status type. + /// + /// The type of the status enumeration. + /// The status type indicating the failure reason. + /// The event messages produced by the operation. + /// A new attempt instance indicating failure. public static Attempt?> Fail( TStatusType statusType, EventMessages eventMessages) where TStatusType : struct => Core.Attempt.Fail(new OperationResult(statusType, eventMessages)); + /// + /// Creates a failed operation attempt with a custom status type and exception. + /// + /// The type of the status enumeration. + /// The status type indicating the failure reason. + /// The event messages produced by the operation. + /// The exception that caused the operation to fail. + /// A new attempt instance indicating failure. public static Attempt?> Fail( TStatusType statusType, EventMessages eventMessages, @@ -211,12 +300,29 @@ public static Attempt?> where TStatusType : struct => Core.Attempt.Fail(new OperationResult(statusType, eventMessages), exception); + /// + /// Creates a failed operation attempt with a custom status type and typed value. + /// + /// The type of the status enumeration. + /// The type of the entity value. + /// The status type indicating the failure reason. + /// The event messages produced by the operation. + /// A new attempt instance indicating failure. public static Attempt?> Fail( TStatusType statusType, EventMessages eventMessages) where TStatusType : struct => Core.Attempt.Fail(new OperationResult(statusType, eventMessages)); + /// + /// Creates a failed operation attempt with a custom status type, typed value, and entity. + /// + /// The type of the status enumeration. + /// The type of the entity value. + /// The status type indicating the failure reason. + /// The event messages produced by the operation. + /// The entity value associated with the operation. + /// A new attempt instance indicating failure. public static Attempt?> Fail( TStatusType statusType, EventMessages eventMessages, @@ -224,6 +330,15 @@ public static Attempt?> where TStatusType : struct => Core.Attempt.Fail(new OperationResult(statusType, eventMessages, value)); + /// + /// Creates a failed operation attempt with a custom status type, typed value, and exception. + /// + /// The type of the status enumeration. + /// The type of the entity value. + /// The status type indicating the failure reason. + /// The event messages produced by the operation. + /// The exception that caused the operation to fail. + /// A new attempt instance indicating failure. public static Attempt?> Fail( TStatusType statusType, EventMessages eventMessages, @@ -231,6 +346,16 @@ public static Attempt?> where TStatusType : struct => Core.Attempt.Fail(new OperationResult(statusType, eventMessages), exception); + /// + /// Creates a failed operation attempt with a custom status type, typed value, entity, and exception. + /// + /// The type of the status enumeration. + /// The type of the entity value. + /// The status type indicating the failure reason. + /// The event messages produced by the operation. + /// The entity value associated with the operation. + /// The exception that caused the operation to fail. + /// A new attempt instance indicating failure. public static Attempt?> Fail( TStatusType statusType, EventMessages eventMessages, @@ -239,6 +364,12 @@ public static Attempt?> where TStatusType : struct => Core.Attempt.Fail(new OperationResult(statusType, eventMessages, value), exception); + /// + /// Creates a failed operation attempt indicating that the operation cannot be performed. + /// + /// The type of the entity value. + /// The event messages produced by the operation. + /// A new attempt instance indicating the operation cannot be performed. public static Attempt?> Cannot(EventMessages eventMessages) => Core.Attempt.Fail( new OperationResult(OperationResultType.FailedCannot, eventMessages)); diff --git a/src/Umbraco.Core/Services/OperationStatus/ApiContentQueryOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ApiContentQueryOperationStatus.cs index 2e8da1a0b1c1..e68f91be518c 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ApiContentQueryOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ApiContentQueryOperationStatus.cs @@ -1,9 +1,27 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of an API content query operation. +/// public enum ApiContentQueryOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The specified filter option was not found. + /// FilterOptionNotFound, + + /// + /// The specified selector option was not found. + /// SelectorOptionNotFound, + + /// + /// The specified sort option was not found. + /// SortOptionNotFound } diff --git a/src/Umbraco.Core/Services/OperationStatus/ApiMediaQueryOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ApiMediaQueryOperationStatus.cs index f031a37b9187..5a9f45131d1e 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ApiMediaQueryOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ApiMediaQueryOperationStatus.cs @@ -1,9 +1,27 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of an API media query operation. +/// public enum ApiMediaQueryOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The specified filter option was not found. + /// FilterOptionNotFound, + + /// + /// The specified selector option was not found. + /// SelectorOptionNotFound, + + /// + /// The specified sort option was not found. + /// SortOptionNotFound } diff --git a/src/Umbraco.Core/Services/OperationStatus/AuditLogOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/AuditLogOperationStatus.cs index c21a412e49cc..7f664cec943f 100644 --- a/src/Umbraco.Core/Services/OperationStatus/AuditLogOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/AuditLogOperationStatus.cs @@ -1,7 +1,17 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of an audit log operation. +/// public enum AuditLogOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The specified user was not found. + /// UserNotFound, } diff --git a/src/Umbraco.Core/Services/OperationStatus/ContentCollectionOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ContentCollectionOperationStatus.cs index 90980a2f350c..b697157b60d9 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ContentCollectionOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ContentCollectionOperationStatus.cs @@ -1,16 +1,62 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a content collection operation. +/// public enum ContentCollectionOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The specified collection was not found. + /// CollectionNotFound, + + /// + /// The content item is not configured as a collection. + /// ContentNotCollection, + + /// + /// The specified content item was not found. + /// ContentNotFound, + + /// + /// The specified content type was not found. + /// ContentTypeNotFound, + + /// + /// The data type is not configured for collection use. + /// DataTypeNotCollection, + + /// + /// The data type is not a content property. + /// DataTypeNotContentProperty, + + /// + /// The specified data type was not found. + /// DataTypeNotFound, + + /// + /// The data type does not have an associated content type. + /// DataTypeWithoutContentType, + + /// + /// Required properties are missing from the collection configuration. + /// MissingPropertiesInCollectionConfiguration, + + /// + /// The specified order by field is not part of the collection configuration. + /// OrderByNotPartOfCollectionConfiguration } diff --git a/src/Umbraco.Core/Services/OperationStatus/ContentEditingOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ContentEditingOperationStatus.cs index afb0e8149487..d99293fb7a70 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ContentEditingOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ContentEditingOperationStatus.cs @@ -1,27 +1,117 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a content editing operation. +/// public enum ContentEditingOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The specified content type was not found. + /// ContentTypeNotFound, + + /// + /// The content's culture variance does not match the content type's culture variance setting. + /// ContentTypeCultureVarianceMismatch, + + /// + /// The content's segment variance does not match the content type's segment variance setting. + /// ContentTypeSegmentVarianceMismatch, + + /// + /// The specified content item was not found. + /// NotFound, + + /// + /// The specified parent content item was not found. + /// ParentNotFound, + + /// + /// The specified parent is invalid for this operation. + /// ParentInvalid, + + /// + /// The operation is not allowed due to permission or structural constraints. + /// NotAllowed, + + /// + /// The specified template was not found. + /// TemplateNotFound, + + /// + /// The specified template is not allowed for this content type. + /// TemplateNotAllowed, + + /// + /// The specified property type was not found on the content type. + /// PropertyTypeNotFound, + + /// + /// The content item is in the recycle bin and cannot be edited. + /// InTrash, + + /// + /// The content item is not in the recycle bin. + /// NotInTrash, + + /// + /// The sorting operation contains invalid data. + /// SortingInvalid, + + /// + /// One or more property values failed validation. + /// PropertyValidationError, + + /// + /// The specified culture is invalid or not configured. + /// InvalidCulture, + + /// + /// A content item with the same key already exists. + /// DuplicateKey, + + /// + /// A content item with the same name already exists at this level. + /// DuplicateName, + + /// + /// An unknown error occurred during the operation. + /// Unknown, + + /// + /// The content item cannot be deleted because it is referenced by other items. + /// CannotDeleteWhenReferenced, + + /// + /// The content item cannot be moved to the recycle bin because it is referenced by other items. + /// CannotMoveToRecycleBinWhenReferenced, } diff --git a/src/Umbraco.Core/Services/OperationStatus/ContentPublishingOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ContentPublishingOperationStatus.cs index 329aa0d2249c..e09f1fdaf322 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ContentPublishingOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ContentPublishingOperationStatus.cs @@ -1,32 +1,143 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a content publishing operation. +/// public enum ContentPublishingOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The specified content item was not found. + /// ContentNotFound, + + /// + /// The operation was cancelled by an event handler. + /// CancelledByEvent, + + /// + /// The content item is invalid and cannot be published. + /// ContentInvalid, + + /// + /// There is nothing to publish for the content item. + /// NothingToPublish, + + /// + /// A mandatory culture is missing from the content item. + /// MandatoryCultureMissing, + + /// + /// The content item has expired and cannot be published. + /// HasExpired, + + /// + /// The specified culture has expired and cannot be published. + /// CultureHasExpired, + + /// + /// The content item is awaiting release and cannot be published immediately. + /// AwaitingRelease, + + /// + /// The specified culture is awaiting release and cannot be published immediately. + /// CultureAwaitingRelease, + + /// + /// The content item is in the recycle bin and cannot be published. + /// InTrash, + + /// + /// The specified culture is invalid or not configured. + /// InvalidCulture, + + /// + /// Cannot publish invariant content when the content type is configured as variant. + /// CannotPublishInvariantWhenVariant, + + /// + /// Cannot publish variant content when the content type is not configured as variant. + /// CannotPublishVariantWhenNotVariant, + + /// + /// The specified culture is missing from the content item. + /// CultureMissing, + + /// + /// The content path is not published; parent content must be published first. + /// PathNotPublished, + + /// + /// A concurrency violation occurred; the content was modified by another operation. + /// ConcurrencyViolation, + + /// + /// The content item has unsaved changes that must be saved before publishing. + /// UnsavedChanges, + + /// + /// The unpublish time must be after the publish time. + /// UnpublishTimeNeedsToBeAfterPublishTime, + + /// + /// The unpublish time must be in the future. + /// UpublishTimeNeedsToBeInFuture, + + /// + /// The publish time must be in the future. + /// PublishTimeNeedsToBeInFuture, + + /// + /// The branch publishing operation failed. + /// FailedBranch, - Failed, // unspecified failure (can happen on unpublish at the time of writing) + + /// + /// An unspecified failure occurred during the operation. + /// + // unspecified failure (can happen on unpublish at the time of writing) + Failed, + + /// + /// An unknown error occurred during the operation. + /// Unknown, + + /// + /// The content item cannot be unpublished because it is referenced by other items. + /// CannotUnpublishWhenReferenced, + + /// + /// The publishing operation was accepted for processing. + /// Accepted, + + /// + /// The task result for the publishing operation was not found. + /// TaskResultNotFound, } diff --git a/src/Umbraco.Core/Services/OperationStatus/ContentQueryOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ContentQueryOperationStatus.cs index 6dcf7433e6d8..4a41b44a02b3 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ContentQueryOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ContentQueryOperationStatus.cs @@ -1,8 +1,22 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a content query operation. +/// public enum ContentQueryOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The specified content item was not found. + /// ContentNotFound, + + /// + /// An unknown error occurred during the operation. + /// Unknown, } diff --git a/src/Umbraco.Core/Services/OperationStatus/ContentTypeImportOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ContentTypeImportOperationStatus.cs index 93fb9b390418..271052d80c30 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ContentTypeImportOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ContentTypeImportOperationStatus.cs @@ -1,12 +1,42 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a content type import operation. +/// public enum ContentTypeImportOperationStatus { + /// + /// The import operation completed successfully and created a new content type. + /// SuccessCreated, + + /// + /// The import operation completed successfully and updated an existing content type. + /// SuccessUpdated, + + /// + /// The temporary file for import was not found. + /// TemporaryFileNotFound, + + /// + /// The temporary file could not be converted to the expected format. + /// TemporaryFileConversionFailure, + + /// + /// A document type with the same alias already exists. + /// DocumentTypeExists, + + /// + /// The ID in the import file does not match the target content type ID. + /// IdMismatch, + + /// + /// The type in the import file does not match the expected content type. + /// TypeMismatch, } diff --git a/src/Umbraco.Core/Services/OperationStatus/ContentTypeOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ContentTypeOperationStatus.cs index 7d7948b91fb2..3483772a7bd0 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ContentTypeOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ContentTypeOperationStatus.cs @@ -1,29 +1,127 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a content type operation. +/// public enum ContentTypeOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// A content type with the same alias already exists. + /// DuplicateAlias, + + /// + /// The content type alias is invalid. + /// InvalidAlias, + + /// + /// The property type alias is invalid. + /// InvalidPropertyTypeAlias, + + /// + /// A property type with the same alias already exists on this content type. + /// DuplicatePropertyTypeAlias, + + /// + /// The specified data type was not found. + /// DataTypeNotFound, + + /// + /// The inheritance configuration is invalid. + /// InvalidInheritance, + + /// + /// The composition configuration is invalid. + /// InvalidComposition, + + /// + /// The specified parent content type is invalid. + /// InvalidParent, + + /// + /// The container name is invalid. + /// InvalidContainerName, + + /// + /// The container type is invalid for this operation. + /// InvalidContainerType, + + /// + /// The specified container is missing. + /// MissingContainer, + + /// + /// A container with the same name already exists at this level. + /// DuplicateContainer, + + /// + /// The specified content type was not found. + /// NotFound, + + /// + /// The operation is not allowed due to permission or structural constraints. + /// NotAllowed, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The property type alias cannot be the same as the content type alias. + /// PropertyTypeAliasCannotEqualContentTypeAlias, + + /// + /// The content type name cannot be empty. + /// NameCannotBeEmpty, + + /// + /// The content type name exceeds the maximum allowed length. + /// NameTooLong, + + /// + /// Cannot change the element flag because the document type has existing content. + /// InvalidElementFlagDocumentHasContent, + + /// + /// Cannot change the element flag because the element type is used in property editor configuration. + /// InvalidElementFlagElementIsUsedInPropertyEditorConfiguration, + + /// + /// The element flag setting is incompatible with the parent content type. + /// InvalidElementFlagComparedToParent, + + /// + /// An unknown error occurred during the operation. + /// Unknown, + + /// + /// The specified template alias is invalid. + /// InvalidTemplateAlias, } diff --git a/src/Umbraco.Core/Services/OperationStatus/ContentTypeStructureOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ContentTypeStructureOperationStatus.cs index a4c7c5c9f2aa..b1bd72996e49 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ContentTypeStructureOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ContentTypeStructureOperationStatus.cs @@ -1,10 +1,32 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a content type structure operation. +/// public enum ContentTypeStructureOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The specified container was not found. + /// ContainerNotFound, + + /// + /// The operation is not allowed due to path restrictions. + /// NotAllowedByPath, + + /// + /// The specified content type was not found. + /// NotFound } diff --git a/src/Umbraco.Core/Services/OperationStatus/ContentVersionOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ContentVersionOperationStatus.cs index b138d0841620..d95558583956 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ContentVersionOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ContentVersionOperationStatus.cs @@ -1,11 +1,37 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a content version operation. +/// public enum ContentVersionOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The specified content version was not found. + /// NotFound, + + /// + /// The specified content item was not found. + /// ContentNotFound, + + /// + /// The skip or take parameters are invalid for pagination. + /// InvalidSkipTake, + + /// + /// The rollback operation failed. + /// RollBackFailed, + + /// + /// The rollback operation was canceled by a notification handler. + /// RollBackCanceled } diff --git a/src/Umbraco.Core/Services/OperationStatus/DataTypeOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/DataTypeOperationStatus.cs index 34178a85c479..55ea00095734 100644 --- a/src/Umbraco.Core/Services/OperationStatus/DataTypeOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/DataTypeOperationStatus.cs @@ -1,16 +1,62 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a data type operation. +/// public enum DataTypeOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The data type configuration is invalid. + /// InvalidConfiguration, + + /// + /// The data type name is invalid or empty. + /// InvalidName, + + /// + /// The data type ID is invalid. + /// InvalidId, + + /// + /// A data type with the same key already exists. + /// DuplicateKey, + + /// + /// The specified data type was not found. + /// NotFound, + + /// + /// The specified parent container was not found. + /// ParentNotFound, + + /// + /// The specified parent is not a valid container. + /// ParentNotContainer, + + /// + /// The specified property editor was not found. + /// PropertyEditorNotFound, + + /// + /// The data type cannot be deleted because it is a system data type or is in use. + /// NonDeletable } diff --git a/src/Umbraco.Core/Services/OperationStatus/DictionaryItemOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/DictionaryItemOperationStatus.cs index 4081a22185f7..dd91c626e994 100644 --- a/src/Umbraco.Core/Services/OperationStatus/DictionaryItemOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/DictionaryItemOperationStatus.cs @@ -1,13 +1,47 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a dictionary item operation. +/// public enum DictionaryItemOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// A dictionary item with the same key already exists. + /// DuplicateItemKey, + + /// + /// The specified dictionary item was not found. + /// ItemNotFound, + + /// + /// The specified parent dictionary item was not found. + /// ParentNotFound, + + /// + /// The dictionary item ID is invalid. + /// InvalidId, + + /// + /// A dictionary item with the same unique key already exists. + /// DuplicateKey, + + /// + /// The specified parent dictionary item is invalid. + /// InvalidParent } diff --git a/src/Umbraco.Core/Services/OperationStatus/DomainOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/DomainOperationStatus.cs index ba19e2bc3fa9..fa418fc364d9 100644 --- a/src/Umbraco.Core/Services/OperationStatus/DomainOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/DomainOperationStatus.cs @@ -1,12 +1,42 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a domain operation. +/// public enum DomainOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The specified content item was not found. + /// ContentNotFound, + + /// + /// The specified language was not found. + /// LanguageNotFound, + + /// + /// A domain with the same name already exists. + /// DuplicateDomainName, + + /// + /// The domain name conflicts with an existing domain. + /// ConflictingDomainName, + + /// + /// The domain name is invalid. + /// InvalidDomainName } diff --git a/src/Umbraco.Core/Services/OperationStatus/EntityContainerOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/EntityContainerOperationStatus.cs index 1d583564480d..bdbc42487f1a 100644 --- a/src/Umbraco.Core/Services/OperationStatus/EntityContainerOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/EntityContainerOperationStatus.cs @@ -1,14 +1,52 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of an entity container (folder) operation. +/// public enum EntityContainerOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The object type is invalid for container operations. + /// InvalidObjectType, + + /// + /// The container ID is invalid. + /// InvalidId, + + /// + /// A container with the same key already exists. + /// DuplicateKey, + + /// + /// The specified container was not found. + /// NotFound, + + /// + /// The specified parent container was not found. + /// ParentNotFound, + + /// + /// The container is not empty and cannot be deleted. + /// NotEmpty, + + /// + /// A container with the same name already exists at this level. + /// DuplicateName } diff --git a/src/Umbraco.Core/Services/OperationStatus/ExternalLoginOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ExternalLoginOperationStatus.cs index 59bc2f6a6495..1309af23e20c 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ExternalLoginOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ExternalLoginOperationStatus.cs @@ -1,18 +1,72 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of an external login operation. +/// public enum ExternalLoginOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The specified user was not found. + /// UserNotFound, + + /// + /// An unknown error occurred during the operation. + /// Unknown, + + /// + /// The external identity was not found. + /// IdentityNotFound, + + /// + /// The authentication options for the provider were not found. + /// AuthenticationOptionsNotFound, + + /// + /// Unlinking external logins is disabled for this provider. + /// UnlinkingDisabled, + + /// + /// The provider key is invalid. + /// InvalidProviderKey, + + /// + /// The authentication scheme was not found. + /// AuthenticationSchemeNotFound, + + /// + /// The user is not authorized to perform this operation. + /// Unauthorized, + + /// + /// The external login information was not found. + /// ExternalInfoNotFound, + + /// + /// An identity operation failure occurred. + /// IdentityFailure, + + /// + /// The user secret was not found. + /// UserSecretNotFound, + + /// + /// The provided secret is invalid. + /// InvalidSecret } diff --git a/src/Umbraco.Core/Services/OperationStatus/GetReferencesOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/GetReferencesOperationStatus.cs index 2ba0e80dc8e0..7618be71cdfb 100644 --- a/src/Umbraco.Core/Services/OperationStatus/GetReferencesOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/GetReferencesOperationStatus.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a get references operation. +/// public enum GetReferencesOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The specified content item was not found. + /// ContentNotFound } diff --git a/src/Umbraco.Core/Services/OperationStatus/InstallOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/InstallOperationStatus.cs index 44011a2d39b0..64303e24c39e 100644 --- a/src/Umbraco.Core/Services/OperationStatus/InstallOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/InstallOperationStatus.cs @@ -1,11 +1,37 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of an installation operation. +/// public enum InstallOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The specified database provider is unknown or not supported. + /// UnknownDatabaseProvider, + + /// + /// The database connection string is missing. + /// MissingConnectionString, + + /// + /// The database provider name is missing. + /// MissingProviderName, + + /// + /// The database connection could not be established. + /// DatabaseConnectionFailed, + + /// + /// The installation process failed. + /// InstallFailed, } diff --git a/src/Umbraco.Core/Services/OperationStatus/LanguageOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/LanguageOperationStatus.cs index b8664ab7ed1c..80e26f726382 100644 --- a/src/Umbraco.Core/Services/OperationStatus/LanguageOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/LanguageOperationStatus.cs @@ -1,14 +1,52 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a language operation. +/// public enum LanguageOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The fallback language configuration is invalid. + /// InvalidFallback, + + /// + /// The specified language was not found. + /// NotFound, + + /// + /// The default language is missing and cannot be removed. + /// MissingDefault, + + /// + /// A language with the same ISO code already exists. + /// DuplicateIsoCode, + + /// + /// The ISO code is invalid or not recognized. + /// InvalidIsoCode, + + /// + /// The fallback language ISO code is invalid or not recognized. + /// InvalidFallbackIsoCode, + + /// + /// The language ID is invalid. + /// InvalidId } diff --git a/src/Umbraco.Core/Services/OperationStatus/LogViewerOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/LogViewerOperationStatus.cs index b929d80e049c..d969aa3b8793 100644 --- a/src/Umbraco.Core/Services/OperationStatus/LogViewerOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/LogViewerOperationStatus.cs @@ -1,9 +1,27 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a log viewer operation. +/// public enum LogViewerOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The specified saved log search was not found. + /// NotFoundLogSearch, + + /// + /// A saved log search with the same name already exists. + /// DuplicateLogSearch, + + /// + /// The operation was cancelled because the log file size exceeds the allowed limit. + /// CancelledByLogsSizeValidation } diff --git a/src/Umbraco.Core/Services/OperationStatus/MediaTypeImportOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/MediaTypeImportOperationStatus.cs index 2ca85e832b33..73a424f2d4d9 100644 --- a/src/Umbraco.Core/Services/OperationStatus/MediaTypeImportOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/MediaTypeImportOperationStatus.cs @@ -1,12 +1,42 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a media type import operation. +/// public enum MediaTypeImportOperationStatus { + /// + /// The media type was successfully created from the import. + /// SuccessCreated, + + /// + /// The media type was successfully updated from the import. + /// SuccessUpdated, + + /// + /// The temporary file containing the import data was not found. + /// TemporaryFileNotFound, + + /// + /// The temporary file could not be converted to a valid import format. + /// TemporaryFileConversionFailure, + + /// + /// A media type with the same identifier already exists. + /// MediaTypeExists, + + /// + /// The import data contains a type that does not match the expected media type. + /// TypeMismatch, + + /// + /// The identifier in the import data does not match the expected identifier. + /// IdMismatch } diff --git a/src/Umbraco.Core/Services/OperationStatus/MemberEditingOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/MemberEditingOperationStatus.cs index 94ce821441fd..f0c5ec87b094 100644 --- a/src/Umbraco.Core/Services/OperationStatus/MemberEditingOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/MemberEditingOperationStatus.cs @@ -1,20 +1,82 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a member editing operation. +/// public enum MemberEditingOperationStatus { + /// + /// The member editing operation completed successfully. + /// Success, + + /// + /// The specified member was not found. + /// MemberNotFound, + + /// + /// The specified member type was not found. + /// MemberTypeNotFound, + + /// + /// Failed to unlock the member account. + /// UnlockFailed, + + /// + /// Failed to disable two-factor authentication for the member. + /// DisableTwoFactorFailed, + + /// + /// Failed to assign or remove roles for the member. + /// RoleAssignmentFailed, + + /// + /// Failed to change the member's password. + /// PasswordChangeFailed, + + /// + /// The provided password does not meet the password requirements. + /// InvalidPassword, + + /// + /// The provided member name is invalid or empty. + /// InvalidName, + + /// + /// The provided username is invalid or empty. + /// InvalidUsername, + + /// + /// The provided email address is invalid or empty. + /// InvalidEmail, + + /// + /// A member with the same username already exists. + /// DuplicateUsername, + + /// + /// A member with the same email address already exists. + /// DuplicateEmail, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotificationHandler, + + /// + /// An unknown error occurred during the operation. + /// Unknown, } diff --git a/src/Umbraco.Core/Services/OperationStatus/MemberEditingStatus.cs b/src/Umbraco.Core/Services/OperationStatus/MemberEditingStatus.cs index ca29e521eacd..f75d478de655 100644 --- a/src/Umbraco.Core/Services/OperationStatus/MemberEditingStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/MemberEditingStatus.cs @@ -1,8 +1,17 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the combined status of a member editing operation, including both content and member-specific statuses. +/// public sealed class MemberEditingStatus { + /// + /// Gets or sets the content editing operation status component. + /// public ContentEditingOperationStatus ContentEditingOperationStatus { get; set; } = ContentEditingOperationStatus.Unknown; + /// + /// Gets or sets the member editing operation status component. + /// public MemberEditingOperationStatus MemberEditingOperationStatus { get; set; } = MemberEditingOperationStatus.Unknown; } diff --git a/src/Umbraco.Core/Services/OperationStatus/MemberGroupOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/MemberGroupOperationStatus.cs index 8345aeecfd3b..66a045d0aab2 100644 --- a/src/Umbraco.Core/Services/OperationStatus/MemberGroupOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/MemberGroupOperationStatus.cs @@ -1,11 +1,37 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a member group operation. +/// public enum MemberGroupOperationStatus { + /// + /// The member group operation completed successfully. + /// Success, + + /// + /// The specified member group was not found. + /// NotFound, + + /// + /// The member group name cannot be empty. + /// CannotHaveEmptyName, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// A member group with the same name already exists. + /// DuplicateName, + + /// + /// A member group with the same key already exists. + /// DuplicateKey, } diff --git a/src/Umbraco.Core/Services/OperationStatus/MemberTypeImportOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/MemberTypeImportOperationStatus.cs index 26af22d9bd52..b918ff7117ec 100644 --- a/src/Umbraco.Core/Services/OperationStatus/MemberTypeImportOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/MemberTypeImportOperationStatus.cs @@ -1,12 +1,42 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a member type import operation. +/// public enum MemberTypeImportOperationStatus { + /// + /// The member type was successfully created from the import. + /// SuccessCreated, + + /// + /// The member type was successfully updated from the import. + /// SuccessUpdated, + + /// + /// The temporary file containing the import data was not found. + /// TemporaryFileNotFound, + + /// + /// The temporary file could not be converted to a valid import format. + /// TemporaryFileConversionFailure, + + /// + /// A member type with the same identifier already exists. + /// MemberTypeExists, + + /// + /// The import data contains a type that does not match the expected member type. + /// TypeMismatch, + + /// + /// The identifier in the import data does not match the expected identifier. + /// IdMismatch } diff --git a/src/Umbraco.Core/Services/OperationStatus/OEmbedOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/OEmbedOperationStatus.cs index 0681eb776876..a9f9e8db6012 100644 --- a/src/Umbraco.Core/Services/OperationStatus/OEmbedOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/OEmbedOperationStatus.cs @@ -1,9 +1,27 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of an oEmbed operation for retrieving embedded content. +/// public enum OEmbedOperationStatus { + /// + /// The oEmbed operation completed successfully and embedded content was retrieved. + /// Success, + + /// + /// No oEmbed provider was found that supports the requested URL. + /// NoSupportedProvider, + + /// + /// The oEmbed provider returned an invalid or unparseable result. + /// ProviderReturnedInvalidResult, + + /// + /// An unexpected exception occurred during the oEmbed operation. + /// UnexpectedException } diff --git a/src/Umbraco.Core/Services/OperationStatus/PackageMigrationOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/PackageMigrationOperationStatus.cs index 10806fe37833..aacede8b0642 100644 --- a/src/Umbraco.Core/Services/OperationStatus/PackageMigrationOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/PackageMigrationOperationStatus.cs @@ -1,8 +1,22 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a package migration operation. +/// public enum PackageMigrationOperationStatus { + /// + /// The package migration completed successfully. + /// Success, + + /// + /// The specified package migration was not found. + /// NotFound, + + /// + /// The operation was cancelled because a migration step failed. + /// CancelledByFailedMigration } diff --git a/src/Umbraco.Core/Services/OperationStatus/PackageOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/PackageOperationStatus.cs index 6b6fcb54a6a0..5b96e2a89e38 100644 --- a/src/Umbraco.Core/Services/OperationStatus/PackageOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/PackageOperationStatus.cs @@ -1,9 +1,27 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a package operation. +/// public enum PackageOperationStatus { + /// + /// The package operation completed successfully. + /// Success, + + /// + /// The specified package was not found. + /// NotFound, + + /// + /// A package item with the same name already exists. + /// DuplicateItemName, + + /// + /// The provided package name is invalid. + /// InvalidName } diff --git a/src/Umbraco.Core/Services/OperationStatus/PartialViewFolderOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/PartialViewFolderOperationStatus.cs index f00bba2ae75d..c8d1713be70f 100644 --- a/src/Umbraco.Core/Services/OperationStatus/PartialViewFolderOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/PartialViewFolderOperationStatus.cs @@ -1,11 +1,37 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a partial view folder operation. +/// public enum PartialViewFolderOperationStatus { + /// + /// The partial view folder operation completed successfully. + /// Success, + + /// + /// A partial view folder with the same name already exists at the specified location. + /// AlreadyExists, + + /// + /// The specified partial view folder was not found. + /// NotFound, + + /// + /// The partial view folder cannot be deleted because it is not empty. + /// NotEmpty, + + /// + /// The parent folder was not found. + /// ParentNotFound, + + /// + /// The provided folder name is invalid. + /// InvalidName, } diff --git a/src/Umbraco.Core/Services/OperationStatus/PartialViewOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/PartialViewOperationStatus.cs index f057da529e39..4093240c315c 100644 --- a/src/Umbraco.Core/Services/OperationStatus/PartialViewOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/PartialViewOperationStatus.cs @@ -1,13 +1,47 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a partial view operation. +/// public enum PartialViewOperationStatus { + /// + /// The partial view operation completed successfully. + /// Success, + + /// + /// A partial view with the same name already exists at the specified location. + /// AlreadyExists, + + /// + /// The parent folder was not found. + /// ParentNotFound, + + /// + /// The provided partial view name is invalid. + /// InvalidName, + + /// + /// The file extension is not valid for a partial view. + /// InvalidFileExtension, + + /// + /// The resulting file path exceeds the maximum allowed length. + /// PathTooLong, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The specified partial view was not found. + /// NotFound } diff --git a/src/Umbraco.Core/Services/OperationStatus/PropertyTypeOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/PropertyTypeOperationStatus.cs index fe36f61b7917..5209599f8e81 100644 --- a/src/Umbraco.Core/Services/OperationStatus/PropertyTypeOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/PropertyTypeOperationStatus.cs @@ -1,7 +1,17 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a property type operation. +/// public enum PropertyTypeOperationStatus { + /// + /// The property type operation completed successfully. + /// Success, + + /// + /// The content type associated with the property type was not found. + /// ContentTypeNotFound, } diff --git a/src/Umbraco.Core/Services/OperationStatus/PublicAccessOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/PublicAccessOperationStatus.cs index ed41ee8c7015..cb8051559a84 100644 --- a/src/Umbraco.Core/Services/OperationStatus/PublicAccessOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/PublicAccessOperationStatus.cs @@ -1,13 +1,47 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a public access operation. +/// public enum PublicAccessOperationStatus { + /// + /// The public access operation completed successfully. + /// Success, + + /// + /// The content node to be protected was not found. + /// ContentNotFound, + + /// + /// The login page content node was not found. + /// LoginNodeNotFound, + + /// + /// The error page content node was not found. + /// ErrorNodeNotFound, + + /// + /// No allowed member groups or members were specified for the access rule. + /// NoAllowedEntities, + + /// + /// The access rule is ambiguous due to conflicting member and member group restrictions. + /// AmbiguousRule, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The specified public access entry was not found. + /// EntryNotFound, } diff --git a/src/Umbraco.Core/Services/OperationStatus/RelationOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/RelationOperationStatus.cs index 0a2946c12ea4..7508ac8d07d8 100644 --- a/src/Umbraco.Core/Services/OperationStatus/RelationOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/RelationOperationStatus.cs @@ -1,7 +1,17 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a relation operation. +/// public enum RelationOperationStatus { + /// + /// The relation operation completed successfully. + /// Success, + + /// + /// The specified relation type was not found. + /// RelationTypeNotFound, } diff --git a/src/Umbraco.Core/Services/OperationStatus/RelationTypeOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/RelationTypeOperationStatus.cs index 51d460923f4b..2d1f8157f46a 100644 --- a/src/Umbraco.Core/Services/OperationStatus/RelationTypeOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/RelationTypeOperationStatus.cs @@ -1,12 +1,42 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a relation type operation. +/// public enum RelationTypeOperationStatus { + /// + /// The relation type operation completed successfully. + /// Success, + + /// + /// The specified relation type was not found. + /// NotFound, + + /// + /// A relation type with the same key already exists. + /// KeyAlreadyExists, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The provided relation type identifier is invalid. + /// InvalidId, + + /// + /// The specified child object type is invalid for this relation type. + /// InvalidChildObjectType, + + /// + /// The specified parent object type is invalid for this relation type. + /// InvalidParentObjectType, } diff --git a/src/Umbraco.Core/Services/OperationStatus/ScriptFolderOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ScriptFolderOperationStatus.cs index 4af83c0b5e29..4d3e5dbe5ccc 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ScriptFolderOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ScriptFolderOperationStatus.cs @@ -1,11 +1,37 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a script folder operation. +/// public enum ScriptFolderOperationStatus { + /// + /// The script folder operation completed successfully. + /// Success, + + /// + /// A script folder with the same name already exists at the specified location. + /// AlreadyExists, + + /// + /// The specified script folder was not found. + /// NotFound, + + /// + /// The script folder cannot be deleted because it is not empty. + /// NotEmpty, + + /// + /// The parent folder was not found. + /// ParentNotFound, + + /// + /// The provided folder name is invalid. + /// InvalidName, } diff --git a/src/Umbraco.Core/Services/OperationStatus/ScriptOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/ScriptOperationStatus.cs index a6a2bd8cdc9b..e162f053886b 100644 --- a/src/Umbraco.Core/Services/OperationStatus/ScriptOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/ScriptOperationStatus.cs @@ -1,13 +1,47 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a script operation. +/// public enum ScriptOperationStatus { + /// + /// The script operation completed successfully. + /// Success, + + /// + /// A script with the same name already exists at the specified location. + /// AlreadyExists, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The file extension is not valid for a script file. + /// InvalidFileExtension, + + /// + /// The parent folder was not found. + /// ParentNotFound, + + /// + /// The resulting file path exceeds the maximum allowed length. + /// PathTooLong, + + /// + /// The provided script name is invalid. + /// InvalidName, + + /// + /// The specified script was not found. + /// NotFound, } diff --git a/src/Umbraco.Core/Services/OperationStatus/SegmentOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/SegmentOperationStatus.cs index e911fef7e7cc..e62250a3cc8d 100644 --- a/src/Umbraco.Core/Services/OperationStatus/SegmentOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/SegmentOperationStatus.cs @@ -1,6 +1,12 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a segment operation. +/// public enum SegmentOperationStatus { + /// + /// The segment operation completed successfully. + /// Success, } diff --git a/src/Umbraco.Core/Services/OperationStatus/StylesheetFolderOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/StylesheetFolderOperationStatus.cs index 87b1bb9bf22a..8f43c2be8337 100644 --- a/src/Umbraco.Core/Services/OperationStatus/StylesheetFolderOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/StylesheetFolderOperationStatus.cs @@ -1,11 +1,37 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a stylesheet folder operation. +/// public enum StylesheetFolderOperationStatus { + /// + /// The stylesheet folder operation completed successfully. + /// Success, + + /// + /// A stylesheet folder with the same name already exists at the specified location. + /// AlreadyExists, + + /// + /// The specified stylesheet folder was not found. + /// NotFound, + + /// + /// The stylesheet folder cannot be deleted because it is not empty. + /// NotEmpty, + + /// + /// The parent folder was not found. + /// ParentNotFound, + + /// + /// The provided folder name is invalid. + /// InvalidName, } diff --git a/src/Umbraco.Core/Services/OperationStatus/StylesheetOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/StylesheetOperationStatus.cs index 64fca903031e..ae0be9f3a916 100644 --- a/src/Umbraco.Core/Services/OperationStatus/StylesheetOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/StylesheetOperationStatus.cs @@ -1,13 +1,47 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a stylesheet operation. +/// public enum StylesheetOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation failed because a stylesheet with the same path already exists. + /// AlreadyExists, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The operation failed because the file extension is not valid for a stylesheet. + /// InvalidFileExtension, + + /// + /// The operation failed because the parent folder could not be found. + /// ParentNotFound, + + /// + /// The operation failed because the stylesheet path exceeds the maximum allowed length. + /// PathTooLong, + + /// + /// The operation failed because the stylesheet name is invalid. + /// InvalidName, + + /// + /// The operation failed because the stylesheet could not be found. + /// NotFound, } diff --git a/src/Umbraco.Core/Services/OperationStatus/TemplateOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/TemplateOperationStatus.cs index 80ccd78dd2ba..9671130fdbd3 100644 --- a/src/Umbraco.Core/Services/OperationStatus/TemplateOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/TemplateOperationStatus.cs @@ -1,13 +1,47 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a template operation. +/// public enum TemplateOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The operation failed because the template alias is invalid. + /// InvalidAlias, + + /// + /// The operation failed because a template with the same alias already exists. + /// DuplicateAlias, + + /// + /// The operation failed because the template could not be found. + /// TemplateNotFound, + + /// + /// The operation failed because the master template could not be found. + /// MasterTemplateNotFound, + + /// + /// The operation failed because it would create a circular reference in the master template hierarchy. + /// CircularMasterTemplateReference, + + /// + /// The operation failed because the master template cannot be deleted while it has child templates. + /// MasterTemplateCannotBeDeleted, } diff --git a/src/Umbraco.Core/Services/OperationStatus/TemporaryFileOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/TemporaryFileOperationStatus.cs index 3f6d8152514d..9109c5e8bfb8 100644 --- a/src/Umbraco.Core/Services/OperationStatus/TemporaryFileOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/TemporaryFileOperationStatus.cs @@ -1,11 +1,37 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a temporary file operation. +/// public enum TemporaryFileOperationStatus { + /// + /// The operation completed successfully. + /// Success = 0, + + /// + /// The operation failed because the file extension is not allowed. + /// FileExtensionNotAllowed = 1, + + /// + /// The operation failed because the specified key is already in use by another temporary file. + /// KeyAlreadyUsed = 2, + + /// + /// The operation failed because the temporary file could not be found. + /// NotFound = 3, + + /// + /// The operation failed because file uploads are currently blocked. + /// UploadBlocked = 4, + + /// + /// The operation failed because the file name is invalid. + /// InvalidFileName = 5, } diff --git a/src/Umbraco.Core/Services/OperationStatus/TemporaryFileXmlImportOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/TemporaryFileXmlImportOperationStatus.cs index 1312e030e580..6b2ec6f51779 100644 --- a/src/Umbraco.Core/Services/OperationStatus/TemporaryFileXmlImportOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/TemporaryFileXmlImportOperationStatus.cs @@ -1,8 +1,22 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a temporary file XML import operation. +/// public enum TemporaryFileXmlImportOperationStatus { + /// + /// The operation completed successfully. + /// Success = 0, + + /// + /// The operation failed because the temporary file could not be found. + /// TemporaryFileNotFound, + + /// + /// The operation failed because the entity type could not be determined from the XML content. + /// UndeterminedEntityType, } diff --git a/src/Umbraco.Core/Services/OperationStatus/TwoFactorOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/TwoFactorOperationStatus.cs index e9b64b460a89..025f97312123 100644 --- a/src/Umbraco.Core/Services/OperationStatus/TwoFactorOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/TwoFactorOperationStatus.cs @@ -1,10 +1,32 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a two-factor authentication operation. +/// public enum TwoFactorOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation failed because the two-factor provider is already set up for the user. + /// ProviderAlreadySetup, + + /// + /// The operation failed because the specified two-factor provider name could not be found. + /// ProviderNameNotFound, + + /// + /// The operation failed because the verification code is invalid. + /// InvalidCode, + + /// + /// The operation failed because the user could not be found. + /// UserNotFound } diff --git a/src/Umbraco.Core/Services/OperationStatus/UpgradeOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/UpgradeOperationStatus.cs index e06b8b9bdc53..373af7714885 100644 --- a/src/Umbraco.Core/Services/OperationStatus/UpgradeOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/UpgradeOperationStatus.cs @@ -1,7 +1,17 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of an Umbraco upgrade operation. +/// public enum UpgradeOperationStatus { + /// + /// The upgrade completed successfully. + /// Success, + + /// + /// The upgrade operation failed. + /// UpgradeFailed, } diff --git a/src/Umbraco.Core/Services/OperationStatus/UserClientCredentialsOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/UserClientCredentialsOperationStatus.cs index 585d87c47a89..081efa3edc51 100644 --- a/src/Umbraco.Core/Services/OperationStatus/UserClientCredentialsOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/UserClientCredentialsOperationStatus.cs @@ -1,9 +1,27 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a user client credentials operation. +/// public enum UserClientCredentialsOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation failed because a client with the same ID already exists. + /// DuplicateClientId, + + /// + /// The operation failed because the user is invalid or does not exist. + /// InvalidUser, + + /// + /// The operation failed because the client ID is invalid. + /// InvalidClientId } diff --git a/src/Umbraco.Core/Services/OperationStatus/UserDataOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/UserDataOperationStatus.cs index 9a05d35ea485..db2cf6064f41 100644 --- a/src/Umbraco.Core/Services/OperationStatus/UserDataOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/UserDataOperationStatus.cs @@ -1,10 +1,29 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; // FIXME: Move all authorization statuses to + +/// +/// Represents the status of a user data operation. +/// public enum UserDataOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation failed because the user data could not be found. + /// NotFound, + + /// + /// The operation failed because the user could not be found. + /// UserNotFound, + + /// + /// The operation failed because user data with the same identifier already exists. + /// AlreadyExists } diff --git a/src/Umbraco.Core/Services/OperationStatus/UserGroupOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/UserGroupOperationStatus.cs index d658e07565e0..928a1c025b03 100644 --- a/src/Umbraco.Core/Services/OperationStatus/UserGroupOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/UserGroupOperationStatus.cs @@ -1,25 +1,107 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a user group operation. +/// public enum UserGroupOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation failed because the user group could not be found. + /// NotFound, + + /// + /// The operation failed because the user could not be found. + /// UserNotFound, + + /// + /// The operation failed because a user group with the same identifier already exists. + /// AlreadyExists, + + /// + /// The operation failed because a user group with the same alias already exists. + /// DuplicateAlias, + + /// + /// The operation failed because the specified user is missing. + /// MissingUser, + + /// + /// The operation failed because system user groups cannot be deleted. + /// CanNotDeleteIsSystemUserGroup, + + /// + /// The operation failed because the alias of a system user group cannot be updated. + /// CanNotUpdateAliasIsSystemUserGroup, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The operation failed because the specified media start node key could not be found. + /// MediaStartNodeKeyNotFound, + + /// + /// The operation failed because the specified document start node key could not be found. + /// DocumentStartNodeKeyNotFound, + + /// + /// The operation failed because the specified document permission key could not be found. + /// DocumentPermissionKeyNotFound, + + /// + /// The operation failed because the specified document type permission key could not be found. + /// DocumentTypePermissionKeyNotFound, + + /// + /// The operation failed because the specified language could not be found. + /// LanguageNotFound, + + /// + /// The operation failed because the user group name exceeds the maximum allowed length. + /// NameTooLong, + + /// + /// The operation failed because the user group alias exceeds the maximum allowed length. + /// AliasTooLong, + + /// + /// The operation failed because the user group name is required but was not provided. + /// MissingName, + + /// + /// The operation failed because the current user is not authorized to perform this action. + /// Unauthorized, + + /// + /// The operation failed because the admin group cannot be empty. + /// AdminGroupCannotBeEmpty, + + /// + /// The operation failed because the user is not a member of the specified group. + /// UserNotInGroup, } diff --git a/src/Umbraco.Core/Services/OperationStatus/UserOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/UserOperationStatus.cs index 2702b9434433..f2aeab772fd3 100644 --- a/src/Umbraco.Core/Services/OperationStatus/UserOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/UserOperationStatus.cs @@ -5,41 +5,188 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; /// public enum UserOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation failed because the specified user is missing. + /// MissingUser, + + /// + /// The operation failed because the specified user group is missing. + /// MissingUserGroup, + + /// + /// The operation failed because the username must be a valid email address. + /// UserNameIsNotEmail, + + /// + /// The operation failed because the email address cannot be changed. + /// EmailCannotBeChanged, + + /// + /// The operation failed because no user group was specified. + /// NoUserGroup, + + /// + /// The operation failed because the admin user group must not be empty. + /// AdminUserGroupMustNotBeEmpty, + + /// + /// The operation failed because a user with the same username already exists. + /// DuplicateUserName, + + /// + /// The operation failed because the email address is invalid. + /// InvalidEmail, + + /// + /// The operation failed because a user with the same email address already exists. + /// DuplicateEmail, + + /// + /// The operation failed because the current user is not authorized to perform this action. + /// Unauthorized, + + /// + /// The operation failed because access to the requested resource is forbidden. + /// Forbidden, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The operation failed because the user could not be found. + /// UserNotFound, + + /// + /// The operation failed because the avatar file could not be found. + /// AvatarFileNotFound, + + /// + /// The operation failed because the user cannot be invited. + /// CannotInvite, + + /// + /// The operation failed because the user cannot be deleted. + /// CannotDelete, + + /// + /// The operation failed because the current user cannot disable themselves. + /// CannotDisableSelf, + + /// + /// The operation failed because the current user cannot delete themselves. + /// CannotDeleteSelf, + + /// + /// The operation failed because an invited user cannot be disabled. + /// CannotDisableInvitedUser, + + /// + /// The operation failed because the old password is required when the user is changing their own password. + /// SelfOldPasswordRequired, + + /// + /// The operation failed because the avatar file is invalid. + /// InvalidAvatar, + + /// + /// The operation failed because the ISO code is invalid. + /// InvalidIsoCode, + + /// + /// The operation failed because the invite token is invalid. + /// InvalidInviteToken, + + /// + /// The operation failed because the password reset token is invalid. + /// InvalidPasswordResetToken, + + /// + /// The operation failed because the content start node could not be found. + /// ContentStartNodeNotFound, + + /// + /// The operation failed because the media start node could not be found. + /// MediaStartNodeNotFound, + + /// + /// The operation failed because the content node could not be found. + /// ContentNodeNotFound, + + /// + /// The operation failed because the media node could not be found. + /// MediaNodeNotFound, + + /// + /// The operation failed because the specified node could not be found. + /// NodeNotFound, + + /// + /// The operation failed due to an unknown failure. + /// UnknownFailure, + + /// + /// The operation failed because password reset is not allowed for this user. + /// CannotPasswordReset, + + /// + /// The operation failed because the user is not in an invite state. + /// NotInInviteState, + + /// + /// The operation failed because users cannot reset their own password through this operation. + /// SelfPasswordResetNotAllowed, + + /// + /// The operation failed because a user with the same ID already exists. + /// DuplicateId, + + /// + /// The operation failed because the user type is invalid. + /// InvalidUserType, + + /// + /// The operation failed because the username is invalid. + /// InvalidUserName, } diff --git a/src/Umbraco.Core/Services/OperationStatus/WebProfilerOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/WebProfilerOperationStatus.cs index 2a3a0bc3f243..1bbca1c76c65 100644 --- a/src/Umbraco.Core/Services/OperationStatus/WebProfilerOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/WebProfilerOperationStatus.cs @@ -1,7 +1,17 @@ namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a web profiler operation. +/// public enum WebProfilerOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation failed because the executing user could not be found. + /// ExecutingUserNotFound } diff --git a/src/Umbraco.Core/Services/OperationStatus/WebhookOperationStatus.cs b/src/Umbraco.Core/Services/OperationStatus/WebhookOperationStatus.cs index adf4badabf62..041b39b9ff48 100644 --- a/src/Umbraco.Core/Services/OperationStatus/WebhookOperationStatus.cs +++ b/src/Umbraco.Core/Services/OperationStatus/WebhookOperationStatus.cs @@ -1,9 +1,27 @@ -namespace Umbraco.Cms.Core.Services.OperationStatus; +namespace Umbraco.Cms.Core.Services.OperationStatus; +/// +/// Represents the status of a webhook operation. +/// public enum WebhookOperationStatus { + /// + /// The operation completed successfully. + /// Success, + + /// + /// The operation was cancelled by a notification handler. + /// CancelledByNotification, + + /// + /// The operation failed because the webhook could not be found. + /// NotFound, + + /// + /// The operation failed because no events were specified for the webhook. + /// NoEvents, } diff --git a/src/Umbraco.Core/Services/Ordering.cs b/src/Umbraco.Core/Services/Ordering.cs index 6ab42426175a..86425148d9e7 100644 --- a/src/Umbraco.Core/Services/Ordering.cs +++ b/src/Umbraco.Core/Services/Ordering.cs @@ -34,6 +34,9 @@ public Ordering(string? orderBy, Direction direction = Direction.Ascending, stri IsCustomField = isCustomField; } + /// + /// Gets or sets the next ordering in a chain of orderings. + /// public Ordering? Next { get; set; } = null; /// /// Gets the name of the ordering field. diff --git a/src/Umbraco.Core/Services/Pagination/PaginationConverter.cs b/src/Umbraco.Core/Services/Pagination/PaginationConverter.cs index 4e3af351ec0f..51988d999331 100644 --- a/src/Umbraco.Core/Services/Pagination/PaginationConverter.cs +++ b/src/Umbraco.Core/Services/Pagination/PaginationConverter.cs @@ -1,7 +1,33 @@ namespace Umbraco.Cms.Core.Services.Pagination; +/// +/// Provides utility methods for converting between different pagination strategies. +/// internal static class PaginationConverter { + /// + /// Converts skip/take pagination parameters to page number and page size format. + /// + /// The number of items to skip. Must be evenly divisible by when is non-zero. + /// The number of items to take per page. Must be equal to or greater than zero. + /// When this method returns, contains the calculated zero-based page number. + /// When this method returns, contains the page size (same as ). + /// + /// if the conversion was successful; if + /// is not evenly divisible by (indicating the skip/take values don't align to page boundaries). + /// + /// Thrown when is less than zero. + /// + /// + /// This method enables translation between offset-based pagination (skip/take) and page-based pagination + /// (page number/page size), which is useful when interfacing with APIs or data layers that use different + /// pagination conventions. + /// + /// + /// When is zero, both and + /// will be set to zero, and the method returns . + /// + /// internal static bool ConvertSkipTakeToPaging(int skip, int take, out long pageNumber, out int pageSize) { if (take < 0) diff --git a/src/Umbraco.Core/Services/PartialViewService.cs b/src/Umbraco.Core/Services/PartialViewService.cs index 043eac5ac441..00c15b70ac7d 100644 --- a/src/Umbraco.Core/Services/PartialViewService.cs +++ b/src/Umbraco.Core/Services/PartialViewService.cs @@ -12,10 +12,29 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing partial view files in Umbraco. +/// +/// +/// This service handles CRUD operations for partial view files (.cshtml) stored in the file system, +/// including creating, updating, renaming, and deleting partial views. It also provides access to +/// partial view snippets that can be used as templates when creating new partial views. +/// public class PartialViewService : FileServiceOperationBase, IPartialViewService { private readonly PartialViewSnippetCollection _snippetCollection; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The repository for partial view file operations. + /// The logger instance for logging operations. + /// The resolver for converting user keys to IDs. + /// The service for audit logging. + /// The collection of available partial view snippets. public PartialViewService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -28,6 +47,17 @@ public PartialViewService( : base(provider, loggerFactory, eventMessagesFactory, repository, logger, userIdKeyResolver, auditService) => _snippetCollection = snippetCollection; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The repository for partial view file operations. + /// The logger instance for logging operations. + /// The resolver for converting user keys to IDs. + /// The repository for audit logging (obsolete). + /// The collection of available partial view snippets. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public PartialViewService( ICoreScopeProvider provider, @@ -50,6 +80,18 @@ public PartialViewService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The repository for partial view file operations. + /// The logger instance for logging operations. + /// The resolver for converting user keys to IDs. + /// The service for audit logging. + /// The repository for audit logging (obsolete). + /// The collection of available partial view snippets. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public PartialViewService( ICoreScopeProvider provider, @@ -73,38 +115,53 @@ public PartialViewService( { } + /// protected override string[] AllowedFileExtensions { get; } = { ".cshtml" }; + /// protected override PartialViewOperationStatus Success => PartialViewOperationStatus.Success; + /// protected override PartialViewOperationStatus NotFound => PartialViewOperationStatus.NotFound; + /// protected override PartialViewOperationStatus CancelledByNotification => PartialViewOperationStatus.CancelledByNotification; + /// protected override PartialViewOperationStatus PathTooLong => PartialViewOperationStatus.PathTooLong; + /// protected override PartialViewOperationStatus AlreadyExists => PartialViewOperationStatus.AlreadyExists; + /// protected override PartialViewOperationStatus ParentNotFound => PartialViewOperationStatus.ParentNotFound; + /// protected override PartialViewOperationStatus InvalidName => PartialViewOperationStatus.InvalidName; + /// protected override PartialViewOperationStatus InvalidFileExtension => PartialViewOperationStatus.InvalidFileExtension; + /// protected override string EntityType => "PartialView"; + /// protected override PartialViewSavingNotification SavingNotification(IPartialView target, EventMessages messages) => new(target, messages); + /// protected override PartialViewSavedNotification SavedNotification(IPartialView target, EventMessages messages) => new(target, messages); + /// protected override PartialViewDeletingNotification DeletingNotification(IPartialView target, EventMessages messages) => new(target, messages); + /// protected override PartialViewDeletedNotification DeletedNotification(IPartialView target, EventMessages messages) => new(target, messages); + /// protected override IPartialView CreateEntity(string path, string? content) => new PartialView(path) { Content = content }; diff --git a/src/Umbraco.Core/Services/PreviewService.cs b/src/Umbraco.Core/Services/PreviewService.cs index 43e24f0e07f7..eb1a8a8d8e71 100644 --- a/src/Umbraco.Core/Services/PreviewService.cs +++ b/src/Umbraco.Core/Services/PreviewService.cs @@ -9,6 +9,14 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing content preview mode. +/// +/// +/// Preview mode allows backoffice users to view unpublished content changes +/// as they would appear on the front-end website. This implementation uses +/// secure cookies with SameSite=None to support cross-site preview scenarios. +/// public class PreviewService : IPreviewService { private readonly ICookieManager _cookieManager; @@ -16,6 +24,13 @@ public class PreviewService : IPreviewService private readonly IServiceScopeFactory _serviceScopeFactory; private readonly IRequestCache _requestCache; + /// + /// Initializes a new instance of the class. + /// + /// The cookie manager for handling preview cookies. + /// The generator for creating and validating preview tokens. + /// The factory for creating service scopes. + /// The request cache for caching preview state per request. public PreviewService( ICookieManager cookieManager, IPreviewTokenGenerator previewTokenGenerator, @@ -28,6 +43,7 @@ public PreviewService( _requestCache = requestCache; } + /// public async Task TryEnterPreviewAsync(IUser user) { Attempt attempt = await _previewTokenGenerator.GenerateTokenAsync(user.Key); @@ -43,17 +59,20 @@ public async Task TryEnterPreviewAsync(IUser user) return attempt.Success; } + /// public Task EndPreviewAsync() { _cookieManager.ExpireCookie(Constants.Web.PreviewCookieName); return Task.CompletedTask; } + /// public bool IsInPreview() => _requestCache.Get( "IsInPreview", () => TryGetPreviewClaimsIdentityAsync().GetAwaiter().GetResult().Success) as bool? ?? false; + /// public async Task> TryGetPreviewClaimsIdentityAsync() { var cookieValue = _cookieManager.GetCookieValue(Constants.Web.PreviewCookieName); diff --git a/src/Umbraco.Core/Services/ProcessInstructionsResult.cs b/src/Umbraco.Core/Services/ProcessInstructionsResult.cs index e109d1ed105e..9205ae6cdbb6 100644 --- a/src/Umbraco.Core/Services/ProcessInstructionsResult.cs +++ b/src/Umbraco.Core/Services/ProcessInstructionsResult.cs @@ -6,20 +6,44 @@ namespace Umbraco.Cms.Core.Services; /// public class ProcessInstructionsResult { + /// + /// Initializes a new instance of the class. + /// private ProcessInstructionsResult() { } + /// + /// Gets the number of instructions that were processed. + /// public int NumberOfInstructionsProcessed { get; private set; } + /// + /// Gets the ID of the last instruction that was processed. + /// public int LastId { get; private set; } + /// + /// Gets a value indicating whether the instructions were pruned. + /// [Obsolete("Instruction pruning has been moved to a separate background job. Scheduled for removal in V18.")] public bool InstructionsWerePruned { get; private set; } + /// + /// Creates a new completed result with the specified number of instructions processed and last ID. + /// + /// The number of instructions that were processed. + /// The ID of the last instruction that was processed. + /// A new instance. public static ProcessInstructionsResult AsCompleted(int numberOfInstructionsProcessed, int lastId) => new() { NumberOfInstructionsProcessed = numberOfInstructionsProcessed, LastId = lastId }; + /// + /// Creates a new completed result with the specified number of instructions processed, last ID, and pruned flag set to true. + /// + /// The number of instructions that were processed. + /// The ID of the last instruction that was processed. + /// A new instance with the pruned flag set. [Obsolete("Instruction pruning has been moved to a separate background job. Scheduled for removal in V18.")] public static ProcessInstructionsResult AsCompletedAndPruned(int numberOfInstructionsProcessed, int lastId) => new() diff --git a/src/Umbraco.Core/Services/PropertyValidationService.cs b/src/Umbraco.Core/Services/PropertyValidationService.cs index fe95f18911ed..346cf2bc893d 100644 --- a/src/Umbraco.Core/Services/PropertyValidationService.cs +++ b/src/Umbraco.Core/Services/PropertyValidationService.cs @@ -12,6 +12,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides property validation functionality for content, media, and member properties. +/// public class PropertyValidationService : IPropertyValidationService { private readonly IDataTypeService _dataTypeService; @@ -22,6 +25,16 @@ public class PropertyValidationService : IPropertyValidationService private readonly ILanguageService _languageService; private readonly ContentSettings _contentSettings; + /// + /// Initializes a new instance of the class. + /// + /// The collection of property editors. + /// The data type service for retrieving data types. + /// The localized text service for retrieving validation messages. + /// The value editor cache for caching value editors. + /// The culture dictionary for translating validation messages. + /// The language service for language operations. + /// The content settings options. public PropertyValidationService( PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService, diff --git a/src/Umbraco.Core/Services/PublicAccessService.cs b/src/Umbraco.Core/Services/PublicAccessService.cs index 465b37b89c8d..e89b9d38b0d7 100644 --- a/src/Umbraco.Core/Services/PublicAccessService.cs +++ b/src/Umbraco.Core/Services/PublicAccessService.cs @@ -10,6 +10,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Implements providing operations for managing public access entries and rules. +/// internal sealed class PublicAccessService : RepositoryService, IPublicAccessService { private readonly IPublicAccessRepository _publicAccessRepository; @@ -17,6 +20,16 @@ internal sealed class PublicAccessService : RepositoryService, IPublicAccessServ private readonly IContentService _contentService; private readonly IIdKeyMap _idKeyMap; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for public access entry operations. + /// The entity service for entity-related operations. + /// The content service for content-related operations. + /// The ID-key map for converting between IDs and keys. public PublicAccessService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -227,6 +240,7 @@ public IEnumerable GetAll() return OperationResult.Attempt.Succeed(evtMsgs); } + /// public async Task> CreateAsync(PublicAccessEntrySlim entry) { Attempt validationAttempt = ValidatePublicAccessEntrySlim(entry); @@ -247,6 +261,11 @@ public IEnumerable GetAll() : Attempt.FailWithStatus(attempt.Status, null); } + /// + /// Saves a public access entry asynchronously. + /// + /// The to save. + /// A task that represents the asynchronous operation. The task result contains an with the saved entry and operation status. private async Task> SaveAsync(PublicAccessEntry entry) { EventMessages eventMessages = EventMessagesFactory.Get(); @@ -270,6 +289,11 @@ public IEnumerable GetAll() return Attempt.SucceedWithStatus(PublicAccessOperationStatus.Success, entry); } + /// + /// Validates a and resolves its referenced content nodes. + /// + /// The entry to validate. + /// An containing the validation result with resolved nodes. private Attempt ValidatePublicAccessEntrySlim(PublicAccessEntrySlim entry) { var result = new PublicAccessNodesValidationResult(); @@ -308,6 +332,7 @@ private Attempt return Attempt.SucceedWithStatus(PublicAccessOperationStatus.Success, result); } + /// public async Task> UpdateAsync(PublicAccessEntrySlim entry) { Attempt validationAttempt = ValidatePublicAccessEntrySlim(entry); @@ -360,6 +385,7 @@ private Attempt return OperationResult.Attempt.Succeed(evtMsgs); } + /// public Task> GetEntryByContentKeyAsync(Guid key) { IEntitySlim? entity = _entityService.Get(key, UmbracoObjectTypes.Document); @@ -378,6 +404,7 @@ private Attempt return Task.FromResult(Attempt.SucceedWithStatus(PublicAccessOperationStatus.Success, entry)); } + /// public async Task> GetEntryByContentKeyWithoutAncestorsAsync(Guid key) { Attempt result = await GetEntryByContentKeyAsync(key); @@ -395,6 +422,7 @@ private Attempt return result; } + /// public async Task> DeleteAsync(Guid key) { using (ICoreScope scope = ScopeProvider.CreateCoreScope()) @@ -432,6 +460,12 @@ public async Task> DeleteAsync(Guid key) return Attempt.Succeed(PublicAccessOperationStatus.Success); } + /// + /// Creates a collection of public access rules from the specified rule values and type. + /// + /// The values for the rules. + /// The type of the rules. + /// An enumerable collection of objects. private IEnumerable CreateAccessRuleList(string[] ruleValues, string ruleType) => ruleValues.Select(ruleValue => new PublicAccessRule { @@ -439,6 +473,12 @@ private IEnumerable CreateAccessRuleList(string[] ruleValues, RuleType = ruleType, }); + /// + /// Maps updates from a to an existing . + /// + /// The model containing the updates. + /// The existing entry to update. + /// The updated . private PublicAccessEntry MapToUpdatedEntry(PublicAccessEntrySlim updatesModel, PublicAccessEntry entryToUpdate) { entryToUpdate.LoginNodeId = _entityService.GetId(updatesModel.LoginPageId, UmbracoObjectTypes.Document).Result; diff --git a/src/Umbraco.Core/Services/PublicAccessServiceExtensions.cs b/src/Umbraco.Core/Services/PublicAccessServiceExtensions.cs index eb42dcda73fa..f068358bd352 100644 --- a/src/Umbraco.Core/Services/PublicAccessServiceExtensions.cs +++ b/src/Umbraco.Core/Services/PublicAccessServiceExtensions.cs @@ -12,6 +12,13 @@ namespace Umbraco.Extensions; /// public static class PublicAccessServiceExtensions { + /// + /// Renames member group role rules from an old role name to a new role name. + /// + /// The public access service. + /// The old role name to find. + /// The new role name to set. + /// true if any rules were updated; otherwise, false. public static bool RenameMemberGroupRoleRules(this IPublicAccessService publicAccessService, string? oldRolename, string? newRolename) { var hasChange = false; @@ -46,6 +53,15 @@ public static bool RenameMemberGroupRoleRules(this IPublicAccessService publicAc return hasChange; } + /// + /// Checks if the specified user has access to a document based on the current member roles. + /// + /// The public access service. + /// The document ID to check access for. + /// The content service for retrieving the document. + /// The username to check access for. + /// The current member roles of the user. + /// true if the user has access; otherwise, false. public static bool HasAccess(this IPublicAccessService publicAccessService, int documentId, IContentService contentService, string username, IEnumerable currentMemberRoles) { IContent? content = contentService.GetById(documentId); @@ -100,6 +116,13 @@ public static async Task HasAccessAsync(this IPublicAccessService publicAc return HasAccess(entry, username, roles); } + /// + /// Checks if the specified user has access based on the public access entry rules. + /// + /// The public access entry containing the rules. + /// The username to check access for. + /// The roles of the user. + /// true if the user has access; otherwise, false. private static bool HasAccess(PublicAccessEntry entry, string username, IEnumerable roles) { if (entry is null) diff --git a/src/Umbraco.Core/Services/PublishStatus/IPublishStatusManagementService.cs b/src/Umbraco.Core/Services/PublishStatus/IPublishStatusManagementService.cs index 215564fe2793..acac372a4294 100644 --- a/src/Umbraco.Core/Services/PublishStatus/IPublishStatusManagementService.cs +++ b/src/Umbraco.Core/Services/PublishStatus/IPublishStatusManagementService.cs @@ -1,9 +1,42 @@ namespace Umbraco.Cms.Core.Services.Navigation; +/// +/// Provides management operations for the in-memory publish status cache. +/// +/// +/// This service is responsible for maintaining the publish status cache that tracks +/// which documents are published and in which cultures. +/// public interface IPublishStatusManagementService { + /// + /// Initializes the publish status cache by loading all published document statuses from the database. + /// + /// A token to cancel the operation. + /// A task that represents the asynchronous initialization operation. Task InitializeAsync(CancellationToken cancellationToken); + + /// + /// Adds or updates the publish status for a specific document in the cache. + /// + /// The unique key of the document to update. + /// A token to cancel the operation. + /// A task that represents the asynchronous operation. Task AddOrUpdateStatusAsync(Guid documentKey, CancellationToken cancellationToken); + + /// + /// Removes a document from the publish status cache. + /// + /// The unique key of the document to remove. + /// A token to cancel the operation. + /// A task that represents the asynchronous operation. Task RemoveAsync(Guid documentKey, CancellationToken cancellationToken); + + /// + /// Adds or updates the publish status for a document and all its descendants in the cache. + /// + /// The unique key of the root document. + /// A token to cancel the operation. + /// A task that represents the asynchronous operation. Task AddOrUpdateStatusWithDescendantsAsync(Guid rootDocumentKey, CancellationToken cancellationToken); } diff --git a/src/Umbraco.Core/Services/PublishStatus/IPublishedContentStatusFilteringService.cs b/src/Umbraco.Core/Services/PublishStatus/IPublishedContentStatusFilteringService.cs index 1c54de959f8b..a42f8f445d07 100644 --- a/src/Umbraco.Core/Services/PublishStatus/IPublishedContentStatusFilteringService.cs +++ b/src/Umbraco.Core/Services/PublishStatus/IPublishedContentStatusFilteringService.cs @@ -1,5 +1,12 @@ -namespace Umbraco.Cms.Core.Services.Navigation; +namespace Umbraco.Cms.Core.Services.Navigation; +/// +/// Provides filtering operations specifically for published document content. +/// +/// +/// This interface extends to provide +/// a content-specific filtering service that considers publish status, culture, and preview mode. +/// public interface IPublishedContentStatusFilteringService : IPublishedStatusFilteringService { } diff --git a/src/Umbraco.Core/Services/PublishStatus/IPublishedMediaStatusFilteringService.cs b/src/Umbraco.Core/Services/PublishStatus/IPublishedMediaStatusFilteringService.cs index 5841bacd033c..a59995a9f8df 100644 --- a/src/Umbraco.Core/Services/PublishStatus/IPublishedMediaStatusFilteringService.cs +++ b/src/Umbraco.Core/Services/PublishStatus/IPublishedMediaStatusFilteringService.cs @@ -1,5 +1,12 @@ -namespace Umbraco.Cms.Core.Services.Navigation; +namespace Umbraco.Cms.Core.Services.Navigation; +/// +/// Provides filtering operations specifically for published media content. +/// +/// +/// This interface extends to provide +/// a media-specific filtering service that can be registered separately in the dependency injection container. +/// public interface IPublishedMediaStatusFilteringService : IPublishedStatusFilteringService { } diff --git a/src/Umbraco.Core/Services/PublishStatus/IPublishedStatusFilteringService.cs b/src/Umbraco.Core/Services/PublishStatus/IPublishedStatusFilteringService.cs index 1cdffea26c4c..0df5b9ab50ae 100644 --- a/src/Umbraco.Core/Services/PublishStatus/IPublishedStatusFilteringService.cs +++ b/src/Umbraco.Core/Services/PublishStatus/IPublishedStatusFilteringService.cs @@ -1,8 +1,17 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; namespace Umbraco.Cms.Core.Services.Navigation; +/// +/// Provides filtering operations to determine which published content items are available for display. +/// public interface IPublishedStatusFilteringService { + /// + /// Filters a collection of candidate content keys to return only those that are available for display. + /// + /// The collection of content keys to filter. + /// The culture to filter by, or null to use the current culture context. + /// A collection of items that are available for display. IEnumerable FilterAvailable(IEnumerable candidateKeys, string? culture); } diff --git a/src/Umbraco.Core/Services/PublishStatus/PublishStatusService.cs b/src/Umbraco.Core/Services/PublishStatus/PublishStatusService.cs index 43b954a7f7b5..2847a1e62852 100644 --- a/src/Umbraco.Core/Services/PublishStatus/PublishStatusService.cs +++ b/src/Umbraco.Core/Services/PublishStatus/PublishStatusService.cs @@ -18,24 +18,32 @@ public class PublishStatusService : IPublishStatusManagementService, IPublishSta private readonly IDictionary> _publishedCultures = new Dictionary>(); - private string? DefaultCulture { get; set; } - /// - /// Initializes a new instance of the class. + /// Gets or sets the default culture ISO code used when no culture is specified. /// - public PublishStatusService( - ILogger logger, - IPublishStatusRepository publishStatusRepository, - ICoreScopeProvider coreScopeProvider, - ILanguageService languageService, - IDocumentNavigationQueryService documentNavigationQueryService) - { - _logger = logger; - _publishStatusRepository = publishStatusRepository; - _coreScopeProvider = coreScopeProvider; - _languageService = languageService; - _documentNavigationQueryService = documentNavigationQueryService; - } + private string? DefaultCulture { get; set; } + +/// +/// Initializes a new instance of the class. +/// +/// The logger for diagnostic output. +/// The repository for accessing publish status data. +/// The provider for creating database scopes. +/// The service for retrieving language information. +/// The service for querying document navigation structure. +public PublishStatusService( + ILogger logger, + IPublishStatusRepository publishStatusRepository, + ICoreScopeProvider coreScopeProvider, + ILanguageService languageService, + IDocumentNavigationQueryService documentNavigationQueryService) +{ + _logger = logger; + _publishStatusRepository = publishStatusRepository; + _coreScopeProvider = coreScopeProvider; + _languageService = languageService; + _documentNavigationQueryService = documentNavigationQueryService; +} /// public async Task InitializeAsync(CancellationToken cancellationToken) diff --git a/src/Umbraco.Core/Services/PublishStatus/PublishedContentStatusFilteringService.cs b/src/Umbraco.Core/Services/PublishStatus/PublishedContentStatusFilteringService.cs index fce1eb949c75..2d4d8ad965c7 100644 --- a/src/Umbraco.Core/Services/PublishStatus/PublishedContentStatusFilteringService.cs +++ b/src/Umbraco.Core/Services/PublishStatus/PublishedContentStatusFilteringService.cs @@ -4,6 +4,14 @@ namespace Umbraco.Cms.Core.Services.Navigation; +/// +/// Filters published content based on availability, considering publish status, culture, and preview mode. +/// +/// +/// This service determines which content items from a set of candidates are available for display, +/// taking into account whether the content is published, whether it has a published ancestor path, +/// and whether the request is in preview mode. +/// internal sealed class PublishedContentStatusFilteringService : IPublishedContentStatusFilteringService { private readonly IVariationContextAccessor _variationContextAccessor; @@ -11,6 +19,13 @@ internal sealed class PublishedContentStatusFilteringService : IPublishedContent private readonly IPreviewService _previewService; private readonly IPublishedContentCache _publishedContentCache; + /// + /// Initializes a new instance of the class. + /// + /// The variation context accessor for retrieving culture information. + /// The service for querying document publish status. + /// The service for determining if the current request is in preview mode. + /// The published content cache for retrieving content items. public PublishedContentStatusFilteringService( IVariationContextAccessor variationContextAccessor, IPublishStatusQueryService publishStatusQueryService, @@ -23,6 +38,7 @@ public PublishedContentStatusFilteringService( _publishedContentCache = publishedContentCache; } + /// public IEnumerable FilterAvailable(IEnumerable candidateKeys, string? culture) { culture ??= _variationContextAccessor.VariationContext?.Culture ?? string.Empty; @@ -43,6 +59,13 @@ public IEnumerable FilterAvailable(IEnumerable candidat return WhereIsInvariantOrHasCultureOrRequestedAllCultures(candidateKeys, culture, preview).ToArray(); } + /// + /// Filters content items to include only those that are invariant, have the requested culture, or when all cultures are requested. + /// + /// The content keys to filter. + /// The requested culture. + /// Whether the request is in preview mode. + /// A collection of items that match the culture criteria. private IEnumerable WhereIsInvariantOrHasCultureOrRequestedAllCultures(IEnumerable keys, string culture, bool preview) => keys .Select(key => _publishedContentCache.GetById(preview, key)) diff --git a/src/Umbraco.Core/Services/PublishStatus/PublishedMediaStatusFilteringService.cs b/src/Umbraco.Core/Services/PublishStatus/PublishedMediaStatusFilteringService.cs index 3c91e1d7bb80..d3e874d4bc45 100644 --- a/src/Umbraco.Core/Services/PublishStatus/PublishedMediaStatusFilteringService.cs +++ b/src/Umbraco.Core/Services/PublishStatus/PublishedMediaStatusFilteringService.cs @@ -1,19 +1,29 @@ -using Umbraco.Cms.Core.Models.PublishedContent; +using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Extensions; namespace Umbraco.Cms.Core.Services.Navigation; -// NOTE: this class is basically a no-op implementation of IPublishStatusQueryService, because the published -// content extensions need a media equivalent to the content implementation. -// incidentally, if we'll ever support variant and/or draft media, this comes in really handy :-) +/// +/// Filters published media based on availability. +/// +/// +/// NOTE: this class is basically a no-op implementation of IPublishStatusQueryService, because the published +/// content extensions need a media equivalent to the content implementation. +/// Incidentally, if we'll ever support variant and/or draft media, this comes in really handy :-) +/// internal sealed class PublishedMediaStatusFilteringService : IPublishedMediaStatusFilteringService { private readonly IPublishedMediaCache _publishedMediaCache; + /// + /// Initializes a new instance of the class. + /// + /// The published media cache for retrieving media items. public PublishedMediaStatusFilteringService(IPublishedMediaCache publishedMediaCache) => _publishedMediaCache = publishedMediaCache; + /// public IEnumerable FilterAvailable(IEnumerable candidateKeys, string? culture) => candidateKeys.Select(_publishedMediaCache.GetById).WhereNotNull().ToArray(); } diff --git a/src/Umbraco.Core/Services/Querying/RecycleBin/DocumentRecycleBinQueryService.cs b/src/Umbraco.Core/Services/Querying/RecycleBin/DocumentRecycleBinQueryService.cs index 9f0fc7202820..52872131b508 100644 --- a/src/Umbraco.Core/Services/Querying/RecycleBin/DocumentRecycleBinQueryService.cs +++ b/src/Umbraco.Core/Services/Querying/RecycleBin/DocumentRecycleBinQueryService.cs @@ -4,12 +4,21 @@ namespace Umbraco.Cms.Core.Services.Querying.RecycleBin; +/// +/// Provides query operations for documents (content items) in the recycle bin. +/// public class DocumentRecycleBinQueryService : IDocumentRecycleBinQueryService { private readonly IEntityService _entityService; private readonly ICoreScopeProvider _scopeProvider; private readonly IRelationService _relationService; + /// + /// Initializes a new instance of the class. + /// + /// The entity service. + /// The core scope provider. + /// The relation service. public DocumentRecycleBinQueryService( IEntityService entityService, ICoreScopeProvider scopeProvider, @@ -20,6 +29,7 @@ public DocumentRecycleBinQueryService( _relationService = relationService; } + /// public Task> GetOriginalParentAsync(Guid trashedDocumentId) { using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true); diff --git a/src/Umbraco.Core/Services/Querying/RecycleBin/IDocumentRecycleBinQueryService.cs b/src/Umbraco.Core/Services/Querying/RecycleBin/IDocumentRecycleBinQueryService.cs index 37ba3abbf07a..3df620cf625a 100644 --- a/src/Umbraco.Core/Services/Querying/RecycleBin/IDocumentRecycleBinQueryService.cs +++ b/src/Umbraco.Core/Services/Querying/RecycleBin/IDocumentRecycleBinQueryService.cs @@ -2,7 +2,18 @@ namespace Umbraco.Cms.Core.Services.Querying.RecycleBin; +/// +/// Defines a service for querying documents (content items) in the recycle bin. +/// public interface IDocumentRecycleBinQueryService { + /// + /// Gets the original parent of a trashed document. + /// + /// The unique identifier of the trashed document. + /// + /// An containing the original parent as an + /// if found, or null if the original parent was the root. The status indicates the result of the operation. + /// Task> GetOriginalParentAsync(Guid trashedDocumentId); } diff --git a/src/Umbraco.Core/Services/Querying/RecycleBin/IMediaRecycleBinQueryService.cs b/src/Umbraco.Core/Services/Querying/RecycleBin/IMediaRecycleBinQueryService.cs index e7e486b2f1d6..c68a42009ff1 100644 --- a/src/Umbraco.Core/Services/Querying/RecycleBin/IMediaRecycleBinQueryService.cs +++ b/src/Umbraco.Core/Services/Querying/RecycleBin/IMediaRecycleBinQueryService.cs @@ -2,7 +2,18 @@ namespace Umbraco.Cms.Core.Services.Querying.RecycleBin; +/// +/// Defines a service for querying media items in the recycle bin. +/// public interface IMediaRecycleBinQueryService { + /// + /// Gets the original parent of a trashed media item. + /// + /// The unique identifier of the trashed media item. + /// + /// An containing the original parent as an + /// if found, or null if the original parent was the root. The status indicates the result of the operation. + /// Task> GetOriginalParentAsync(Guid trashedMediaId); } diff --git a/src/Umbraco.Core/Services/Querying/RecycleBin/MediaRecycleBinQueryService.cs b/src/Umbraco.Core/Services/Querying/RecycleBin/MediaRecycleBinQueryService.cs index 8e0510cf421f..5a11290286fb 100644 --- a/src/Umbraco.Core/Services/Querying/RecycleBin/MediaRecycleBinQueryService.cs +++ b/src/Umbraco.Core/Services/Querying/RecycleBin/MediaRecycleBinQueryService.cs @@ -4,12 +4,21 @@ namespace Umbraco.Cms.Core.Services.Querying.RecycleBin; +/// +/// Provides query operations for media items in the recycle bin. +/// public class MediaRecycleBinQueryService : IMediaRecycleBinQueryService { private readonly IEntityService _entityService; private readonly ICoreScopeProvider _scopeProvider; private readonly IRelationService _relationService; + /// + /// Initializes a new instance of the class. + /// + /// The entity service. + /// The core scope provider. + /// The relation service. public MediaRecycleBinQueryService( IEntityService entityService, ICoreScopeProvider scopeProvider, @@ -20,6 +29,7 @@ public MediaRecycleBinQueryService( _relationService = relationService; } + /// public Task> GetOriginalParentAsync(Guid trashedMediaId) { using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true); diff --git a/src/Umbraco.Core/Services/Querying/RecycleBin/RecycleBinQueryResultType.cs b/src/Umbraco.Core/Services/Querying/RecycleBin/RecycleBinQueryResultType.cs index f9f0a34a7547..893e805e6f1c 100644 --- a/src/Umbraco.Core/Services/Querying/RecycleBin/RecycleBinQueryResultType.cs +++ b/src/Umbraco.Core/Services/Querying/RecycleBin/RecycleBinQueryResultType.cs @@ -1,15 +1,45 @@ namespace Umbraco.Cms.Core.Services.Querying.RecycleBin; /// -/// <10 = Success. +/// Represents the result types for recycle bin query operations. /// +/// +/// Values less than 10 indicate success, values 10 or greater indicate failure. +/// public enum RecycleBinQueryResultType { + /// + /// The operation completed successfully. + /// Success = 0, + + /// + /// The original parent of the trashed item was the root node. + /// ParentIsRoot = 2, + + /// + /// The specified item was not found. + /// NotFound = 11, + + /// + /// The specified item is not in the recycle bin (not trashed). + /// NotTrashed = 12, + + /// + /// No parent recycle relation was found for the trashed item. + /// NoParentRecycleRelation = 13, + + /// + /// The original parent of the trashed item was not found. + /// ParentNotFound = 14, + + /// + /// The original parent of the trashed item is also in the recycle bin. + /// ParentIsTrashed = 15, } diff --git a/src/Umbraco.Core/Services/RelationService.cs b/src/Umbraco.Core/Services/RelationService.cs index ed1d03df7029..8166e61f8ddb 100644 --- a/src/Umbraco.Core/Services/RelationService.cs +++ b/src/Umbraco.Core/Services/RelationService.cs @@ -13,6 +13,14 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing relations and relation types between entities. +/// +/// +/// Relations allow entities like content, media, and members to be linked together +/// through various relationship types. This service handles CRUD operations for both +/// relations and relation types. +/// public class RelationService : RepositoryService, IRelationService { private readonly IAuditService _auditService; @@ -21,6 +29,17 @@ public class RelationService : RepositoryService, IRelationService private readonly IRelationRepository _relationRepository; private readonly IRelationTypeRepository _relationTypeRepository; + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for unit of work operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The entity service for entity operations. + /// The repository for relation data access. + /// The repository for relation type data access. + /// The audit service for recording audit entries. + /// The resolver for converting user IDs to keys. public RelationService( ICoreScopeProvider uowProvider, ILoggerFactory loggerFactory, @@ -39,6 +58,17 @@ public RelationService( _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); } + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for unit of work operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The entity service for entity operations. + /// The repository for relation data access. + /// The repository for relation type data access. + /// The audit repository (unused, kept for backward compatibility). + /// The resolver for converting user IDs to keys. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public RelationService( ICoreScopeProvider uowProvider, @@ -61,6 +91,18 @@ public RelationService( { } + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for unit of work operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The entity service for entity operations. + /// The repository for relation data access. + /// The repository for relation type data access. + /// The audit service for recording audit entries. + /// The audit repository (unused, kept for backward compatibility). + /// The resolver for converting user IDs to keys. [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public RelationService( ICoreScopeProvider uowProvider, @@ -134,10 +176,7 @@ public IEnumerable GetAllRelationTypes(params int[] ids) return _relationTypeRepository.GetMany(ids); } - /// - /// Gets the Relation types in a paged manner. - /// Currently implements the paging in memory on the name property because the underlying repository does not support paging yet - /// + /// public Task> GetPagedRelationTypesAsync(int skip, int take, params int[] ids) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -485,9 +524,20 @@ public bool HasRelations(IRelationType relationType) return _relationRepository.Get(query).Any(); } + /// + /// Checks whether an entity has any relations. + /// + /// The identifier of the entity. + /// true if the entity has any relations; otherwise, false. [Obsolete("No longer used in Umbraco, please the overload taking all parameters. Scheduled for removal in Umbraco 19.")] public bool IsRelated(int id) => IsRelated(id, RelationDirectionFilter.Any, null, null); + /// + /// Checks whether an entity has relations in the specified direction. + /// + /// The identifier of the entity. + /// The direction filter to apply when checking relations. + /// true if the entity has relations matching the filter; otherwise, false. [Obsolete("Please the overload taking all parameters. Scheduled for removal in Umbraco 18.")] public bool IsRelated(int id, RelationDirectionFilter directionFilter) => IsRelated(id, directionFilter, null, null); diff --git a/src/Umbraco.Core/Services/RepositoryService.cs b/src/Umbraco.Core/Services/RepositoryService.cs index 2c7bb39085fa..0103fa0a294d 100644 --- a/src/Umbraco.Core/Services/RepositoryService.cs +++ b/src/Umbraco.Core/Services/RepositoryService.cs @@ -10,6 +10,12 @@ namespace Umbraco.Cms.Core.Services; /// public abstract class RepositoryService : IService { + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for unit of work operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. protected RepositoryService(ICoreScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory) { EventMessagesFactory = eventMessagesFactory ?? throw new ArgumentNullException(nameof(eventMessagesFactory)); @@ -17,11 +23,25 @@ protected RepositoryService(ICoreScopeProvider provider, ILoggerFactory loggerFa LoggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); } + /// + /// Gets the event messages factory. + /// protected IEventMessagesFactory EventMessagesFactory { get; } + /// + /// Gets the scope provider. + /// protected ICoreScopeProvider ScopeProvider { get; } + /// + /// Gets the logger factory. + /// protected ILoggerFactory LoggerFactory { get; } + /// + /// Creates a query for the specified type. + /// + /// The type to query. + /// A new query instance. protected IQuery Query() => ScopeProvider.CreateQuery(); } diff --git a/src/Umbraco.Core/Services/ScriptService.cs b/src/Umbraco.Core/Services/ScriptService.cs index 91a89298b242..e3519dbd05b9 100644 --- a/src/Umbraco.Core/Services/ScriptService.cs +++ b/src/Umbraco.Core/Services/ScriptService.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; @@ -10,8 +10,25 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing JavaScript script files in Umbraco. +/// +/// +/// This service handles CRUD operations for script files (.js) stored in the file system, +/// including creating, updating, renaming, and deleting scripts. +/// public class ScriptService : FileServiceOperationBase, IScriptService { + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The repository for script file operations. + /// The logger instance for logging operations. + /// The resolver for converting user keys to IDs. + /// The service for audit logging. public ScriptService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -24,6 +41,16 @@ public ScriptService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The repository for script file operations. + /// The logger instance for logging operations. + /// The resolver for converting user keys to IDs. + /// The repository for audit logging (obsolete). [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public ScriptService( ICoreScopeProvider provider, @@ -44,6 +71,17 @@ public ScriptService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The repository for script file operations. + /// The logger instance for logging operations. + /// The resolver for converting user keys to IDs. + /// The service for audit logging. + /// The repository for audit logging (obsolete). [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public ScriptService( ICoreScopeProvider provider, @@ -65,38 +103,53 @@ public ScriptService( { } + /// protected override string[] AllowedFileExtensions { get; } = { ".js" }; + /// protected override ScriptOperationStatus Success => ScriptOperationStatus.Success; + /// protected override ScriptOperationStatus NotFound => ScriptOperationStatus.NotFound; + /// protected override ScriptOperationStatus CancelledByNotification => ScriptOperationStatus.CancelledByNotification; + /// protected override ScriptOperationStatus PathTooLong => ScriptOperationStatus.PathTooLong; + /// protected override ScriptOperationStatus AlreadyExists => ScriptOperationStatus.AlreadyExists; + /// protected override ScriptOperationStatus ParentNotFound => ScriptOperationStatus.ParentNotFound; + /// protected override ScriptOperationStatus InvalidName => ScriptOperationStatus.InvalidName; + /// protected override ScriptOperationStatus InvalidFileExtension => ScriptOperationStatus.InvalidFileExtension; + /// protected override string EntityType => "Script"; + /// protected override ScriptSavingNotification SavingNotification(IScript target, EventMessages messages) => new(target, messages); + /// protected override ScriptSavedNotification SavedNotification(IScript target, EventMessages messages) => new(target, messages); + /// protected override ScriptDeletingNotification DeletingNotification(IScript target, EventMessages messages) => new(target, messages); + /// protected override ScriptDeletedNotification DeletedNotification(IScript target, EventMessages messages) => new(target, messages); + /// protected override IScript CreateEntity(string path, string? content) => new Script(path) { Content = content }; diff --git a/src/Umbraco.Core/Services/StylesheetService.cs b/src/Umbraco.Core/Services/StylesheetService.cs index 2137de92b8d3..6dc3999ab585 100644 --- a/src/Umbraco.Core/Services/StylesheetService.cs +++ b/src/Umbraco.Core/Services/StylesheetService.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Events; @@ -10,8 +10,25 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for managing CSS stylesheet files in Umbraco. +/// +/// +/// This service handles CRUD operations for stylesheet files (.css) stored in the file system, +/// including creating, updating, renaming, and deleting stylesheets. +/// public class StylesheetService : FileServiceOperationBase, IStylesheetService { + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The repository for stylesheet file operations. + /// The logger instance for logging operations. + /// The resolver for converting user keys to IDs. + /// The service for audit logging. public StylesheetService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -24,6 +41,16 @@ public StylesheetService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The repository for stylesheet file operations. + /// The logger instance for logging operations. + /// The resolver for converting user keys to IDs. + /// The repository for audit logging (obsolete). [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public StylesheetService( ICoreScopeProvider provider, @@ -44,6 +71,17 @@ public StylesheetService( { } + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for managing database transactions. + /// The factory for creating loggers. + /// The factory for creating event messages. + /// The repository for stylesheet file operations. + /// The logger instance for logging operations. + /// The resolver for converting user keys to IDs. + /// The service for audit logging. + /// The repository for audit logging (obsolete). [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public StylesheetService( ICoreScopeProvider provider, @@ -65,38 +103,53 @@ public StylesheetService( { } + /// protected override string[] AllowedFileExtensions { get; } = { ".css" }; + /// protected override StylesheetOperationStatus Success => StylesheetOperationStatus.Success; + /// protected override StylesheetOperationStatus NotFound => StylesheetOperationStatus.NotFound; + /// protected override StylesheetOperationStatus CancelledByNotification => StylesheetOperationStatus.CancelledByNotification; + /// protected override StylesheetOperationStatus PathTooLong => StylesheetOperationStatus.PathTooLong; + /// protected override StylesheetOperationStatus AlreadyExists => StylesheetOperationStatus.AlreadyExists; + /// protected override StylesheetOperationStatus ParentNotFound => StylesheetOperationStatus.ParentNotFound; + /// protected override StylesheetOperationStatus InvalidName => StylesheetOperationStatus.InvalidName; + /// protected override StylesheetOperationStatus InvalidFileExtension => StylesheetOperationStatus.InvalidFileExtension; + /// protected override string EntityType => "Stylesheet"; + /// protected override StylesheetSavingNotification SavingNotification(IStylesheet target, EventMessages messages) => new(target, messages); + /// protected override StylesheetSavedNotification SavedNotification(IStylesheet target, EventMessages messages) => new(target, messages); + /// protected override StylesheetDeletingNotification DeletingNotification(IStylesheet target, EventMessages messages) => new(target, messages); + /// protected override StylesheetDeletedNotification DeletedNotification(IStylesheet target, EventMessages messages) => new(target, messages); + /// protected override IStylesheet CreateEntity(string path, string? content) => new Stylesheet(path) { Content = content }; diff --git a/src/Umbraco.Core/Services/TagService.cs b/src/Umbraco.Core/Services/TagService.cs index 0a567dca0586..86bc789dda7c 100644 --- a/src/Umbraco.Core/Services/TagService.cs +++ b/src/Umbraco.Core/Services/TagService.cs @@ -18,6 +18,13 @@ public class TagService : RepositoryService, ITagService { private readonly ITagRepository _tagRepository; + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for unit of work operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for tag data access. public TagService(ICoreScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory, ITagRepository tagRepository) : base(provider, loggerFactory, eventMessagesFactory) => _tagRepository = tagRepository; @@ -103,6 +110,12 @@ public IEnumerable GetAllTags(string? group = null, string? culture = null } } + /// + /// Gets all tags asynchronously, optionally filtered by group and culture. + /// + /// The optional tag group to filter by. + /// The optional culture to filter by. + /// A task that represents the asynchronous operation containing the tags. public Task> GetAllAsync(string? group = null, string? culture = null) { if (culture == string.Empty) @@ -113,6 +126,13 @@ public Task> GetAllAsync(string? group = null, string? culture return Task.FromResult(GetAllTags(group, culture)); } + /// + /// Gets tags matching the specified query text, optionally filtered by group and culture. + /// + /// The text to search for in tag names. + /// The optional tag group to filter by. + /// The optional culture to filter by. + /// A task that represents the asynchronous operation containing the matching tags. public async Task> GetByQueryAsync(string query, string? group = null, string? culture = null) => (await GetAllAsync(group, culture)).Where(x => x.Text.InvariantContains(query)); /// diff --git a/src/Umbraco.Core/Services/TemplateContentParserService.cs b/src/Umbraco.Core/Services/TemplateContentParserService.cs index 21f70e10e44d..738da20fac4b 100644 --- a/src/Umbraco.Core/Services/TemplateContentParserService.cs +++ b/src/Umbraco.Core/Services/TemplateContentParserService.cs @@ -1,10 +1,14 @@ -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; using Umbraco.Extensions; namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for parsing template content to extract metadata such as the master template alias. +/// public partial class TemplateContentParserService : ITemplateContentParserService { + /// public string? MasterTemplateAlias(string? viewContent) { if (viewContent.IsNullOrWhiteSpace()) diff --git a/src/Umbraco.Core/Services/TemplateService.cs b/src/Umbraco.Core/Services/TemplateService.cs index 100dccb7b958..66904c5ecd37 100644 --- a/src/Umbraco.Core/Services/TemplateService.cs +++ b/src/Umbraco.Core/Services/TemplateService.cs @@ -14,6 +14,9 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing templates (Razor views) including CRUD operations and master template relationships. +/// public class TemplateService : RepositoryService, ITemplateService { private readonly IShortStringHelper _shortStringHelper; @@ -21,6 +24,16 @@ public class TemplateService : RepositoryService, ITemplateService private readonly IAuditService _auditService; private readonly ITemplateContentParserService _templateContentParserService; + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for unit of work operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The helper for short string operations. + /// The repository for template data access. + /// The audit service for recording audit entries. + /// The service for parsing template content. public TemplateService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -37,6 +50,18 @@ public TemplateService( _templateContentParserService = templateContentParserService; } + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for unit of work operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The helper for short string operations. + /// The repository for template data access. + /// The audit repository (unused, kept for backward compatibility). + /// The service for parsing template content. + /// The resolver for converting user IDs to keys (unused, kept for backward compatibility). + /// The provider for default view content (unused, kept for backward compatibility). [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public TemplateService( ICoreScopeProvider provider, @@ -59,6 +84,19 @@ public TemplateService( { } + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for unit of work operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The helper for short string operations. + /// The repository for template data access. + /// The audit service for recording audit entries. + /// The audit repository (unused, kept for backward compatibility). + /// The service for parsing template content. + /// The resolver for converting user IDs to keys (unused, kept for backward compatibility). + /// The provider for default view content (unused, kept for backward compatibility). [Obsolete("Use the non-obsolete constructor instead. Scheduled removal in v19.")] public TemplateService( ICoreScopeProvider provider, @@ -162,6 +200,11 @@ public async Task> CreateAsync( public async Task> CreateAsync(ITemplate template, Guid userKey) => await CreateAsync(template, userKey, null); + /// + /// Validates that a template can be created. + /// + /// The template to validate. + /// The operation status indicating the result of the validation. private TemplateOperationStatus ValidateCreate(ITemplate templateToCreate) { ITemplate? existingTemplate = GetAsync(templateToCreate.Alias).GetAwaiter().GetResult(); @@ -254,6 +297,11 @@ public async Task> UpdateAsync(ITemp // fail the attempt if the template does not exist within the scope () => ValidateUpdate(template)); + /// + /// Validates that a template can be updated. + /// + /// The template to validate. + /// The operation status indicating the result of the validation. private TemplateOperationStatus ValidateUpdate(ITemplate templateToUpdate) { ITemplate? existingTemplate = GetAsync(templateToUpdate.Alias).GetAwaiter().GetResult(); @@ -270,6 +318,15 @@ private TemplateOperationStatus ValidateUpdate(ITemplate templateToUpdate) return TemplateOperationStatus.Success; } + /// + /// Saves a template with validation and auditing. + /// + /// The template to save. + /// The type of audit entry to create. + /// The key of the user performing the operation. + /// An optional validation function to execute within the scope. + /// The optional content type alias for the saving notification. + /// An attempt result containing the template and operation status. private async Task> SaveAsync( ITemplate template, AuditType auditType, @@ -372,7 +429,12 @@ public Task GetFileSizeAsync(string filepath) } } - /// + /// + /// Sets or removes the master template for the specified template. + /// + /// The template to update. + /// The master template to set, or null to remove the master template. + /// The key of the user performing the operation. private async Task SetMasterTemplateAsync(ITemplate template, ITemplate? masterTemplate, Guid userKey) { if (template.MasterTemplateAlias == masterTemplate?.Alias) @@ -428,6 +490,11 @@ private async Task SetMasterTemplateAsync(ITemplate template, ITemplate? masterT } } + /// + /// Gets the content of a view file from disk. + /// + /// The file name of the view. + /// The content of the view file, or null if empty. private string? GetViewContent(string? fileName) { if (fileName.IsNullOrWhiteSpace()) @@ -448,9 +515,24 @@ private async Task SetMasterTemplateAsync(ITemplate template, ITemplate? masterT } } + /// + /// Records an audit entry. + /// + /// The type of audit. + /// The key of the user who performed the action. + /// The ID of the object being audited. + /// The type of entity being audited. + /// A task representing the asynchronous operation. private Task Audit(AuditType type, Guid userKey, int objectId, string? entityType) => _auditService.AddAsync(type, userKey, objectId, entityType); + /// + /// Creates a template with optional content type association. + /// + /// The template to create. + /// The key of the user performing the operation. + /// The optional content type alias to associate with the template. + /// An attempt result containing the template and operation status. private async Task> CreateAsync(ITemplate template, Guid userKey, string? contentTypeAlias) { if (IsValidAlias(template.Alias) is false) @@ -471,6 +553,12 @@ private async Task> CreateAsync(ITem } } + /// + /// Deletes a template using a function to retrieve it. + /// + /// A function that retrieves the template to delete. + /// The key of the user performing the operation. + /// An attempt result containing the deleted template and operation status. private async Task> DeleteAsync(Func> getTemplate, Guid userKey) { using (ICoreScope scope = ScopeProvider.CreateCoreScope()) @@ -507,9 +595,21 @@ private async Task> CreateAsync(ITem } } + /// + /// Determines whether the specified alias is valid. + /// + /// The alias to validate. + /// true if the alias is valid; otherwise, false. private static bool IsValidAlias(string alias) => alias.IsNullOrWhiteSpace() == false && alias.Length <= 255; + /// + /// Checks if setting the master template would create a circular reference. + /// + /// The parsed master template alias from the template content. + /// The template being updated. + /// The proposed master template. + /// true if a circular reference would be created; otherwise, false. private async Task HasCircularReference(string parsedMasterTemplateAlias, ITemplate template, ITemplate masterTemplate) { // quick check without extra DB calls as we already have both templates @@ -524,6 +624,12 @@ private async Task HasCircularReference(string parsedMasterTemplateAlias, return await HasRecursiveCircularReference(processedTemplates, masterTemplate.MasterTemplateAlias); } + /// + /// Recursively checks for circular references in the master template chain. + /// + /// The list of templates already referenced in the chain. + /// The master template alias to check. + /// true if a circular reference is detected; otherwise, false. private async Task HasRecursiveCircularReference(List referencedTemplates, string? masterTemplateAlias) { if (masterTemplateAlias is null) diff --git a/src/Umbraco.Core/Services/TemporaryFileService.cs b/src/Umbraco.Core/Services/TemporaryFileService.cs index 12a78b07396b..7c205106dbdc 100644 --- a/src/Umbraco.Core/Services/TemporaryFileService.cs +++ b/src/Umbraco.Core/Services/TemporaryFileService.cs @@ -8,6 +8,13 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing temporary files used during uploads and other operations. +/// +/// +/// Temporary files are stored for a limited time based on +/// and are automatically cleaned up when they expire. +/// internal sealed class TemporaryFileService : ITemporaryFileService { private readonly ITemporaryFileRepository _temporaryFileRepository; @@ -15,6 +22,13 @@ internal sealed class TemporaryFileService : ITemporaryFileService private RuntimeSettings _runtimeSettings; private ContentSettings _contentSettings; + /// + /// Initializes a new instance of the class. + /// + /// The repository for temporary file data access. + /// The options monitor for runtime settings. + /// The options monitor for content settings. + /// The validator for checking file stream security. public TemporaryFileService( ITemporaryFileRepository temporaryFileRepository, IOptionsMonitor runtimeOptionsMonitor, @@ -31,6 +45,7 @@ public TemporaryFileService( contentOptionsMonitor.OnChange(x => _contentSettings = x); } + /// public async Task> CreateAsync(CreateTemporaryFileModel createModel) { TemporaryFileOperationStatus validationResult = Validate(createModel); @@ -65,6 +80,11 @@ public TemporaryFileService( return Attempt.Succeed(TemporaryFileOperationStatus.Success, temporaryFileModel); } + /// + /// Validates a temporary file model for allowed file extensions and valid file name. + /// + /// The temporary file model to validate. + /// The operation status indicating success or the type of validation failure. private TemporaryFileOperationStatus Validate(TemporaryFileModelBase temporaryFileModel) { if (IsAllowedFileExtension(temporaryFileModel.FileName) == false) @@ -80,15 +100,26 @@ private TemporaryFileOperationStatus Validate(TemporaryFileModelBase temporaryFi return TemporaryFileOperationStatus.Success; } + /// + /// Determines whether the file extension is allowed for upload. + /// + /// The file name to check. + /// true if the file extension is allowed; otherwise, false. private bool IsAllowedFileExtension(string fileName) { var extension = Path.GetExtension(fileName)[1..]; return _contentSettings.IsFileAllowedForUpload(extension); } + /// + /// Determines whether the file name is valid (not empty and contains no invalid characters). + /// + /// The file name to validate. + /// true if the file name is valid; otherwise, false. private static bool IsValidFileName(string fileName) => !string.IsNullOrEmpty(fileName) && fileName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0; + /// public async Task> DeleteAsync(Guid key) { TemporaryFileModel? model = await _temporaryFileRepository.GetAsync(key); @@ -102,7 +133,9 @@ private static bool IsValidFileName(string fileName) => return Attempt.Succeed(TemporaryFileOperationStatus.Success, model); } + /// public async Task GetAsync(Guid key) => await _temporaryFileRepository.GetAsync(key); + /// public async Task> CleanUpOldTempFiles() => await _temporaryFileRepository.CleanUpOldTempFiles(DateTime.Now); } diff --git a/src/Umbraco.Core/Services/TrackedReferencesService.cs b/src/Umbraco.Core/Services/TrackedReferencesService.cs index 24332dcfa52c..c6f82d216f28 100644 --- a/src/Umbraco.Core/Services/TrackedReferencesService.cs +++ b/src/Umbraco.Core/Services/TrackedReferencesService.cs @@ -6,12 +6,25 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides services for tracking and querying references between entities in Umbraco. +/// +/// +/// This service is used to find relationships and dependencies between content, media, and other entities. +/// It helps determine which items reference other items, which is useful for operations like deletion checks. +/// public class TrackedReferencesService : ITrackedReferencesService { private readonly ICoreScopeProvider _scopeProvider; private readonly IEntityService _entityService; private readonly ITrackedReferencesRepository _trackedReferencesRepository; + /// + /// Initializes a new instance of the class. + /// + /// The repository for accessing tracked reference data. + /// The scope provider for database operations. + /// The entity service for retrieving entity information. public TrackedReferencesService( ITrackedReferencesRepository trackedReferencesRepository, ICoreScopeProvider scopeProvider, @@ -22,6 +35,7 @@ public TrackedReferencesService( _entityService = entityService; } + /// [Obsolete("Use the GetPagedRelationsForItemAsync overload which returns an Attempt with operation status. Scheduled for removal in Umbraco 19.")] public Task> GetPagedRelationsForItemAsync(Guid key, long skip, long take, bool filterMustBeIsDependency) { @@ -32,6 +46,7 @@ public Task> GetPagedRelationsForItemAsync(Guid ke return Task.FromResult(pagedModel); } + /// public async Task, GetReferencesOperationStatus>> GetPagedRelationsForItemAsync(Guid key, UmbracoObjectTypes objectType, long skip, long take, bool filterMustBeIsDependency) { IEntitySlim? entity = _entityService.Get(key, objectType); @@ -47,6 +62,7 @@ public async Task, GetReferencesOperationS return Attempt.SucceedWithStatus(GetReferencesOperationStatus.Success, pagedModel); } + /// public Task> GetPagedRelationsForRecycleBinAsync(UmbracoObjectTypes objectType, long skip, long take, bool filterMustBeIsDependency) { Guid objectTypeKey = objectType switch @@ -62,6 +78,7 @@ public Task> GetPagedRelationsForRecycleBinAsync(U return Task.FromResult(pagedModel); } + /// [Obsolete("Use GetPagedDescendantsInReferencesAsync which returns an Attempt with operation status. Scheduled for removal in Umbraco 19.")] public Task> GetPagedDescendantsInReferencesAsync(Guid parentKey, long skip, long take, bool filterMustBeIsDependency) { @@ -78,6 +95,7 @@ public Task> GetPagedDescendantsInReferencesAsync( return Task.FromResult(pagedModel); } + /// public async Task, GetReferencesOperationStatus>> GetPagedDescendantsInReferencesAsync(Guid parentKey, UmbracoObjectTypes objectType, long skip, long take, bool filterMustBeIsDependency) { IEntitySlim? entity = _entityService.Get(parentKey, objectType); @@ -93,6 +111,7 @@ public async Task, GetReferencesOperationS return Attempt.SucceedWithStatus(GetReferencesOperationStatus.Success, pagedModel); } + /// public Task> GetPagedItemsWithRelationsAsync(ISet keys, long skip, long take, bool filterMustBeIsDependency) { using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true); @@ -102,6 +121,7 @@ public Task> GetPagedItemsWithRelationsAsync(ISet< return Task.FromResult(pagedModel); } + /// public async Task> GetPagedKeysWithDependentReferencesAsync(ISet keys, Guid objectTypeId, long skip, long take) { using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true); diff --git a/src/Umbraco.Core/Services/TreeEntitySortingService.cs b/src/Umbraco.Core/Services/TreeEntitySortingService.cs index dfbb4d692d9f..6f8b8f7697ca 100644 --- a/src/Umbraco.Core/Services/TreeEntitySortingService.cs +++ b/src/Umbraco.Core/Services/TreeEntitySortingService.cs @@ -1,10 +1,14 @@ -using Umbraco.Cms.Core.Models.ContentEditing; +using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Cms.Core.Models.Entities; namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for sorting tree entities based on sorting models. +/// public class TreeEntitySortingService : ITreeEntitySortingService { + /// public IEnumerable SortEntities(IEnumerable entities, IEnumerable sortingModels) where TTreeEntity : ITreeEntity { diff --git a/src/Umbraco.Core/Services/TwoFactorLoginServiceBase.cs b/src/Umbraco.Core/Services/TwoFactorLoginServiceBase.cs index 28becea84826..e0aaf220d0c5 100644 --- a/src/Umbraco.Core/Services/TwoFactorLoginServiceBase.cs +++ b/src/Umbraco.Core/Services/TwoFactorLoginServiceBase.cs @@ -15,6 +15,12 @@ internal abstract class TwoFactorLoginServiceBase private readonly ICoreScopeProvider _scopeProvider; private readonly IDictionary _twoFactorSetupGenerators; + /// + /// Initializes a new instance of the class. + /// + /// The two-factor login service for managing 2FA data. + /// The collection of two-factor providers. + /// The scope provider for unit of work operations. protected TwoFactorLoginServiceBase(ITwoFactorLoginService twoFactorLoginService, IEnumerable twoFactorSetupGenerators, ICoreScopeProvider scopeProvider) { _twoFactorLoginService = twoFactorLoginService; @@ -22,6 +28,12 @@ protected TwoFactorLoginServiceBase(ITwoFactorLoginService twoFactorLoginService _twoFactorSetupGenerators = twoFactorSetupGenerators.ToDictionary(x => x.ProviderName); } + /// + /// Disables two-factor authentication for the specified user and provider. + /// + /// The unique key of the user. + /// The name of the two-factor provider to disable. + /// An attempt result indicating success or failure with the operation status. public virtual async Task> DisableAsync(Guid userKey, string providerName) { var result = await _twoFactorLoginService.DisableAsync(userKey, providerName); @@ -49,6 +61,12 @@ public virtual async Task, TwoFa /// The random secret protected virtual string GenerateSecret() => Guid.NewGuid().ToString(); + /// + /// Gets the setup information for enabling two-factor authentication. + /// + /// The unique key of the user or member. + /// The name of the two-factor provider. + /// An attempt result containing the setup model and operation status. public virtual async Task> GetSetupInfoAsync(Guid userOrMemberKey, string providerName) { var secret = await _twoFactorLoginService.GetSecretForUserAndProviderAsync(userOrMemberKey, providerName); @@ -70,6 +88,14 @@ public virtual async Task + /// Validates the two-factor code and saves the provider configuration if valid. + /// + /// The name of the two-factor provider. + /// The unique key of the user or member. + /// The secret key for the provider. + /// The verification code to validate. + /// An attempt result indicating success or failure with the operation status. public virtual async Task> ValidateAndSaveAsync( string providerName, Guid userOrMemberKey, @@ -114,8 +140,12 @@ public virtual async Task> ValidateAndSaveAsyn } /// - /// Disables 2FA with Code. + /// Disables two-factor authentication by validating a code. /// + /// The name of the two-factor provider. + /// The unique key of the user or member. + /// The verification code to validate before disabling. + /// An attempt result indicating success or failure with the operation status. public async Task> DisableByCodeAsync(string providerName, Guid userOrMemberKey, string code) { var secret = await _twoFactorLoginService.GetSecretForUserAndProviderAsync(userOrMemberKey, providerName); diff --git a/src/Umbraco.Core/Services/UpgradeService.cs b/src/Umbraco.Core/Services/UpgradeService.cs index 0c9a31d6a6b0..dfaed052a731 100644 --- a/src/Umbraco.Core/Services/UpgradeService.cs +++ b/src/Umbraco.Core/Services/UpgradeService.cs @@ -3,14 +3,22 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for checking for available Umbraco upgrades. +/// [Obsolete("Upgrade checks are no longer supported and this service will be removed in Umbraco 19.")] public class UpgradeService : IUpgradeService { private readonly IUpgradeCheckRepository _upgradeCheckRepository; + /// + /// Initializes a new instance of the class. + /// + /// The repository for checking upgrades. public UpgradeService(IUpgradeCheckRepository upgradeCheckRepository) => _upgradeCheckRepository = upgradeCheckRepository; + /// public async Task CheckUpgrade(SemVersion version) => await _upgradeCheckRepository.CheckUpgradeAsync(version); } diff --git a/src/Umbraco.Core/Services/UserDataService.cs b/src/Umbraco.Core/Services/UserDataService.cs index ff12d3603022..238afebfff71 100644 --- a/src/Umbraco.Core/Services/UserDataService.cs +++ b/src/Umbraco.Core/Services/UserDataService.cs @@ -9,11 +9,22 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Implements providing operations for managing user-specific data entries. +/// public class UserDataService : RepositoryService, IUserDataService { private readonly IUserDataRepository _userDataRepository; private readonly IUserService _userService; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for user data operations. + /// The user service for user-related operations. public UserDataService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -26,6 +37,7 @@ public UserDataService( _userService = userService; } + /// public async Task GetAsync(Guid key) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -34,6 +46,7 @@ public UserDataService( return userData; } + /// public async Task> GetAsync(int skip, int take, IUserDataFilter? filter = null) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -42,6 +55,7 @@ public async Task> GetAsync(int skip, int take, IUserDataF return pagedUserData; } + /// public async Task> CreateAsync(IUserData userData) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -62,6 +76,7 @@ public async Task> CreateAsync(IUser return Attempt.Succeed(UserDataOperationStatus.Success, userData); } + /// public async Task> UpdateAsync(IUserData userData) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -82,6 +97,7 @@ public async Task> UpdateAsync(IUser return Attempt.Succeed(UserDataOperationStatus.Success, userData); } + /// public async Task> DeleteAsync(Guid key) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -97,6 +113,11 @@ public async Task> DeleteAsync(Guid key) return Attempt.Succeed(UserDataOperationStatus.Success); } + /// + /// Checks whether the user referenced by the user data exists. + /// + /// The user data containing the user reference. + /// A task that represents the asynchronous operation. The task result is true if the referenced user exists; otherwise, false. private async Task ReferencedUserExits(IUserData userData) => await _userService.GetAsync(userData.UserKey) is not null; } diff --git a/src/Umbraco.Core/Services/UserGroupPermissionService.cs b/src/Umbraco.Core/Services/UserGroupPermissionService.cs index cbd06db181d7..b2b67599f5b1 100644 --- a/src/Umbraco.Core/Services/UserGroupPermissionService.cs +++ b/src/Umbraco.Core/Services/UserGroupPermissionService.cs @@ -16,6 +16,13 @@ internal sealed class UserGroupPermissionService : IUserGroupPermissionService private readonly IEntityService _entityService; private readonly AppCaches _appCaches; + /// + /// Initializes a new instance of the class. + /// + /// The content service. + /// The media service. + /// The entity service. + /// The application caches. public UserGroupPermissionService( IContentService contentService, IMediaService mediaService, diff --git a/src/Umbraco.Core/Services/UserGroupService.cs b/src/Umbraco.Core/Services/UserGroupService.cs index ac7d1a40aaab..1bed0729689c 100644 --- a/src/Umbraco.Core/Services/UserGroupService.cs +++ b/src/Umbraco.Core/Services/UserGroupService.cs @@ -17,7 +17,14 @@ namespace Umbraco.Cms.Core.Services; /// internal sealed class UserGroupService : RepositoryService, IUserGroupService { + /// + /// The maximum length of a user group name. + /// public const int MaxUserGroupNameLength = 200; + + /// + /// The maximum length of a user group alias. + /// public const int MaxUserGroupAliasLength = 200; private readonly IUserGroupRepository _userGroupRepository; @@ -26,6 +33,17 @@ internal sealed class UserGroupService : RepositoryService, IUserGroupService private readonly IUserService _userService; private readonly ILogger _logger; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The repository for user group operations. + /// The service for user group permission operations. + /// The entity service for entity-related operations. + /// The user service for user-related operations. + /// The logger for this service. public UserGroupService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -119,6 +137,7 @@ public Task> GetAsync(params string[] aliases) return Task.FromResult(groups); } + /// public Task> GetAsync(IEnumerable keys) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -210,6 +229,7 @@ public async Task> DeleteAsync(ISet keys return Attempt.Succeed(UserGroupOperationStatus.Success); } + /// public async Task> UpdateUserGroupsOnUsersAsync( ISet userGroupKeys, ISet userKeys) @@ -254,6 +274,11 @@ public async Task> UpdateUserGroupsOnUsersAsyn return Attempt.Succeed(UserGroupOperationStatus.Success); } + /// + /// Validates that a user group can be deleted. + /// + /// The user group to validate for deletion. + /// An indicating whether the user group can be deleted. private Attempt ValidateUserGroupDeletion(IUserGroup? userGroup) { if (userGroup is null) @@ -331,6 +356,11 @@ public async Task> CreateAsync( return Attempt.SucceedWithStatus(UserGroupOperationStatus.Success, userGroup); } + /// + /// Validates a user group for creation. + /// + /// The user group to validate. + /// A task that represents the asynchronous operation. The task result contains an with the validation result. private async Task> ValidateUserGroupCreationAsync( IUserGroup userGroup) { @@ -410,6 +440,7 @@ public async Task> UpdateAsync( return Attempt.SucceedWithStatus(UserGroupOperationStatus.Success, userGroup); } + /// public async Task> AddUsersToUserGroupAsync(UsersToUserGroupManipulationModel addUsersModel, Guid performingUserKey) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -440,6 +471,7 @@ public async Task> AddUsersToUserGroupAsync(Us return Attempt.Succeed(UserGroupOperationStatus.Success); } + /// public async Task> RemoveUsersFromUserGroupAsync(UsersToUserGroupManipulationModel removeUsersModel, Guid performingUserKey) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -518,6 +550,11 @@ public async Task> RemoveUsersFromUserGroupAsy return Attempt.SucceedWithStatus(UserGroupOperationStatus.Success, resolvedModel); } + /// + /// Validates a user group for update operations. + /// + /// The user group to validate. + /// A task that represents the asynchronous operation. The task result contains the indicating validation result. private async Task ValidateUserGroupUpdateAsync(IUserGroup userGroup) { UserGroupOperationStatus commonValidationStatus = ValidateCommon(userGroup); @@ -581,6 +618,11 @@ private UserGroupOperationStatus ValidateCommon(IUserGroup userGroup) return UserGroupOperationStatus.Success; } + /// + /// Determines whether the user group is new (not yet persisted). + /// + /// The user group to check. + /// A task that represents the asynchronous operation. The task result is true if the user group is new; otherwise, false. private async Task IsNewUserGroup(IUserGroup userGroup) { if (userGroup.Id != 0 && userGroup.HasIdentity is false) @@ -591,6 +633,11 @@ private async Task IsNewUserGroup(IUserGroup userGroup) return await GetAsync(userGroup.Key) is null; } + /// + /// Validates that the start nodes specified in the user group exist. + /// + /// The user group containing start node references. + /// The indicating whether validation passed. private UserGroupOperationStatus ValidateStartNodesExists(IUserGroup userGroup) { if (userGroup.StartContentId is not null @@ -610,6 +657,11 @@ private UserGroupOperationStatus ValidateStartNodesExists(IUserGroup userGroup) return UserGroupOperationStatus.Success; } + /// + /// Validates that the granular permissions specified in the user group reference existing entities. + /// + /// The user group containing granular permission references. + /// The indicating whether validation passed. private UserGroupOperationStatus ValidateGranularPermissionsExists(IUserGroup userGroup) { Guid[] documentKeys = userGroup.GranularPermissions diff --git a/src/Umbraco.Core/Services/UserPermissionService.cs b/src/Umbraco.Core/Services/UserPermissionService.cs index a03624fbc238..cb5e1ffbcdf5 100644 --- a/src/Umbraco.Core/Services/UserPermissionService.cs +++ b/src/Umbraco.Core/Services/UserPermissionService.cs @@ -9,6 +9,10 @@ internal sealed class UserPermissionService : IUserPermissionService { private readonly IUserService _userService; + /// + /// Initializes a new instance of the class. + /// + /// The user service. public UserPermissionService(IUserService userService) => _userService = userService; diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs index ecc5989ef6a6..8bef16ee911a 100644 --- a/src/Umbraco.Core/Services/UserService.cs +++ b/src/Umbraco.Core/Services/UserService.cs @@ -52,6 +52,28 @@ internal partial class UserService : RepositoryService, IUserService private readonly ContentSettings _contentSettings; private readonly IUserIdKeyResolver _userIdKeyResolver; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider for database operations. + /// The logger factory for creating loggers. + /// The factory for creating event messages. + /// The user repository for data access. + /// The user group repository for data access. + /// The global settings configuration. + /// The security settings configuration. + /// The helper for user editor authorization. + /// The factory for creating service scopes. + /// The entity service for entity operations. + /// The provider for local login settings. + /// The sender for user invitations. + /// The manager for media files. + /// The service for temporary file operations. + /// The helper for short string operations. + /// The content settings configuration. + /// The validator for ISO codes. + /// The sender for forgot password emails. + /// The resolver for user ID to key mappings. public UserService( ICoreScopeProvider provider, ILoggerFactory loggerFactory, @@ -126,11 +148,7 @@ public static bool TryGetAssignedPermissionsForNode( #region Implementation of IMembershipUserService - /// - /// Checks if a User with the username exists - /// - /// Username to check - /// True if the User exists otherwise False + /// public bool Exists(string username) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -139,66 +157,31 @@ public bool Exists(string username) } } - /// - /// Creates a new User - /// - /// The user will be saved in the database and returned with an Id - /// Username of the user to create - /// Email of the user to create - /// - /// - /// + /// public IUser CreateUserWithIdentity(string username, string email) => CreateUserWithIdentity(username, email, string.Empty); - /// - /// Creates and persists a new - /// - /// Username of the to create - /// Email of the to create - /// - /// This value should be the encoded/encrypted/hashed value for the password that will be - /// stored in the database - /// - /// Not used for users - /// - /// - /// + /// IUser IMembershipMemberService.CreateWithIdentity(string username, string email, string passwordValue, string memberTypeAlias) => CreateUserWithIdentity(username, email, passwordValue); - /// - /// Creates and persists a new - /// - /// Username of the to create - /// Email of the to create - /// - /// This value should be the encoded/encrypted/hashed value for the password that will be - /// stored in the database - /// - /// Alias of the Type - /// Is the member approved - /// - /// - /// + /// IUser IMembershipMemberService.CreateWithIdentity(string username, string email, string passwordValue, string memberTypeAlias, bool isApproved) => CreateUserWithIdentity(username, email, passwordValue, isApproved); /// - /// Creates and persists a Member + /// Creates and persists a user with identity. /// /// - /// Using this method will persist the Member object before its returned - /// meaning that it will have an Id available (unlike the CreateMember method) + /// Using this method will persist the user object before it's returned, + /// meaning that it will have an Id available. /// - /// Username of the Member to create - /// Email of the Member to create + /// Username of the user to create. + /// Email of the user to create. /// /// This value should be the encoded/encrypted/hashed value for the password that will be - /// stored in the database + /// stored in the database. /// - /// Is the user approved - /// - /// - /// + /// Indicates whether the user is approved. Defaults to true. + /// The created . private IUser CreateUserWithIdentity(string username, string email, string passwordValue, bool isApproved = true) { if (username == null) @@ -252,13 +235,7 @@ private IUser CreateUserWithIdentity(string username, string email, string passw return user; } - /// - /// Gets an by its provider key - /// - /// Id to use for retrieval - /// - /// - /// + /// public IUser? GetByProviderKey(object id) { Attempt asInt = id.TryConvertTo(); @@ -283,13 +260,7 @@ private IUser CreateUserWithIdentity(string username, string email, string passw } } - /// - /// Get an by email - /// - /// Email to use for retrieval - /// - /// - /// + /// public IUser? GetByEmail(string email) { using IServiceScope scope = _serviceScopeFactory.CreateScope(); @@ -297,13 +268,7 @@ private IUser CreateUserWithIdentity(string username, string email, string passw return backOfficeUserStore.GetByEmailAsync(email).GetAwaiter().GetResult(); } - /// - /// Get an by username - /// - /// Username to use for retrieval - /// - /// - /// + /// public IUser? GetByUsername(string? username) { if (username is null) @@ -316,10 +281,7 @@ private IUser CreateUserWithIdentity(string username, string email, string passw return backOfficeUserStore.GetByUserNameAsync(username).GetAwaiter().GetResult(); } - /// - /// Disables an - /// - /// to disable + /// public void Delete(IUser membershipUser) { using IServiceScope scope = _serviceScopeFactory.CreateScope(); @@ -328,11 +290,7 @@ public void Delete(IUser membershipUser) backOfficeUserStore.DisableAsync(membershipUser).GetAwaiter().GetResult(); } - /// - /// Deletes or disables a User - /// - /// to delete - /// True to permanently delete the user, False to disable the user + /// public void Delete(IUser user, bool deletePermanently) { if (deletePermanently == false) @@ -361,10 +319,7 @@ public void Delete(IUser user, bool deletePermanently) } } - /// - /// Saves an - /// - /// to Save + /// public void Save(IUser entity) { using IServiceScope scope = _serviceScopeFactory.CreateScope(); @@ -374,9 +329,10 @@ public void Save(IUser entity) } /// - /// Saves an + /// Saves an asynchronously. /// - /// to Save + /// The to save. + /// A task that represents the asynchronous operation, containing the . public async Task SaveAsync(IUser entity) { using IServiceScope scope = _serviceScopeFactory.CreateScope(); @@ -385,10 +341,7 @@ public async Task SaveAsync(IUser entity) return await backOfficeUserStore.SaveAsync(entity); } - /// - /// Saves a list of objects - /// - /// to save + /// public void Save(IEnumerable entities) { EventMessages evtMsgs = EventMessagesFactory.Get(); @@ -427,20 +380,7 @@ public void Save(IEnumerable entities) } } - /// - /// Finds a list of objects by a partial email string - /// - /// Partial email string to match - /// Current page index - /// Size of the page - /// Total number of records found (out) - /// - /// The type of match to make as . Default is - /// - /// - /// - /// - /// + /// public IEnumerable FindByEmail(string emailStringToMatch, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -472,20 +412,7 @@ public IEnumerable FindByEmail(string emailStringToMatch, long pageIndex, } } - /// - /// Finds a list of objects by a partial username - /// - /// Partial username to match - /// Current page index - /// Size of the page - /// Total number of records found (out) - /// - /// The type of match to make as . Default is - /// - /// - /// - /// - /// + /// public IEnumerable FindByUsername(string login, long pageIndex, int pageSize, out long totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -517,18 +444,7 @@ public IEnumerable FindByUsername(string login, long pageIndex, int pageS } } - /// - /// Gets the total number of Users based on the count type - /// - /// - /// The way the Online count is done is the same way that it is done in the MS SqlMembershipProvider - We query for any - /// members - /// that have their last active date within the Membership.UserIsOnlineTimeWindow (which is in minutes). It isn't exact - /// science - /// but that is how MS have made theirs so we'll follow that principal. - /// - /// to count by - /// with number of Users for passed in type + /// public int GetCount(MemberCountType countType) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -554,6 +470,7 @@ public int GetCount(MemberCountType countType) } } + /// public Guid CreateLoginSession(int userId, string requestingIpAddress) { using (ICoreScope scope = ScopeProvider.CreateCoreScope()) @@ -564,6 +481,7 @@ public Guid CreateLoginSession(int userId, string requestingIpAddress) } } + /// public int ClearLoginSessions(int userId) { using (ICoreScope scope = ScopeProvider.CreateCoreScope()) @@ -574,6 +492,7 @@ public int ClearLoginSessions(int userId) } } + /// public void ClearLoginSession(Guid sessionId) { using (ICoreScope scope = ScopeProvider.CreateCoreScope()) @@ -583,6 +502,7 @@ public void ClearLoginSession(Guid sessionId) } } + /// public bool ValidateLoginSession(int userId, Guid sessionId) { using (ICoreScope scope = ScopeProvider.CreateCoreScope()) @@ -593,6 +513,7 @@ public bool ValidateLoginSession(int userId, Guid sessionId) } } + /// public IDictionary GetUserStates() { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -683,6 +604,7 @@ public async Task> CreateAsync( return Attempt.SucceedWithStatus(UserOperationStatus.Success, creationResult); } + /// public async Task> SendResetPasswordEmailAsync(string userEmail) { if (_forgotPasswordSender.CanSend() is false) @@ -723,6 +645,8 @@ public async Task> SendResetPasswordEmailAsync(stri return Attempt.Succeed(UserOperationStatus.Success); } + + /// public async Task> InviteAsync(Guid performingUserKey, UserInviteModel model) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -803,6 +727,7 @@ public async Task> InviteAsyn return invitationAttempt; } + /// public async Task> ResendInvitationAsync(Guid performingUserKey, UserResendInviteModel model) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -836,6 +761,14 @@ public async Task> ResendInvi return invitationAttempt; } + /// + /// Sends an invitation to a user. + /// + /// The user performing the invitation. + /// The service scope for dependency resolution. + /// The user being invited. + /// An optional message to include in the invitation. + /// An attempt containing the invitation result and operation status. private async Task> SendInvitationAsync(IUser performingUser, IServiceScope serviceScope, IUser invitedUser, string? message) { IInviteUriProvider inviteUriProvider = serviceScope.ServiceProvider.GetRequiredService(); @@ -857,6 +790,11 @@ private async Task> SendInvit return Attempt.SucceedWithStatus(UserOperationStatus.Success, new UserInvitationResult { InvitedUser = invitedUser }); } + /// + /// Validates a user create model. + /// + /// The user create model to validate. + /// A task that represents the asynchronous operation, containing the . private async Task ValidateUserCreateModel(UserCreateModel model) { if (_securitySettings.UsernameIsEmail && model.UserName != model.Email) @@ -891,6 +829,7 @@ private async Task ValidateUserCreateModel(UserCreateModel return UserOperationStatus.Success; } + /// public async Task> UpdateAsync(Guid performingUserKey, UserUpdateModel model) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -1013,6 +952,7 @@ private async Task ValidateUserCreateModel(UserCreateModel } + /// public async Task SetAvatarAsync(Guid userKey, Guid temporaryFileKey) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -1057,6 +997,15 @@ public async Task SetAvatarAsync(Guid userKey, Guid tempora return UserOperationStatus.Success; } + /// + /// Maps user update model properties to an existing user. + /// + /// The source update model. + /// The user groups to assign. + /// The target user to update. + /// The content start node IDs. + /// The media start node IDs. + /// The updated . private IUser MapUserUpdate( UserUpdateModel source, ISet sourceUserGroups, @@ -1080,6 +1029,12 @@ private IUser MapUserUpdate( return target; } + /// + /// Validates a user update model against an existing user. + /// + /// The existing user being updated. + /// The update model to validate. + /// The indicating validation result. private UserOperationStatus ValidateUserUpdateModel(IUser existingUser, UserUpdateModel model) { if (_isoCodeValidator.IsValid(model.LanguageIsoCode) is false) @@ -1126,6 +1081,12 @@ private UserOperationStatus ValidateUserUpdateModel(IUser existingUser, UserUpda return UserOperationStatus.Success; } + /// + /// Converts a collection of entity keys to their corresponding IDs. + /// + /// The GUIDs to convert. + /// The type of Umbraco object. + /// A list of IDs, or null if any conversion failed. private List? GetIdsFromKeys(IEnumerable? guids, UmbracoObjectTypes type) { var keys = guids? @@ -1151,6 +1112,12 @@ public async Task> ChangePass return await ChangePasswordAsync(performingUser, model); } + /// + /// Changes a user's password. + /// + /// The user performing the password change. + /// The password change model. + /// An attempt containing the password changed result and operation status. private async Task> ChangePasswordAsync(IUser performingUser, ChangeUserPasswordModel model) { IServiceScope serviceScope = _serviceScopeFactory.CreateScope(); @@ -1208,6 +1175,7 @@ private async Task> ChangePas return Attempt.SucceedWithStatus(UserOperationStatus.Success, result.Result ?? new PasswordChangedModel()); } + /// public async Task?, UserOperationStatus>> GetAllAsync(Guid performingUserKey, int skip, int take) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -1254,6 +1222,7 @@ private async Task> ChangePas return Attempt.SucceedWithStatus?, UserOperationStatus>(UserOperationStatus.Success, pagedResult); } + /// public async Task, UserOperationStatus>> FilterAsync( Guid userKey, UserFilter filter, @@ -1359,12 +1328,14 @@ public async Task, UserOperationStatus>> FilterAsync( } /// - /// Creates a base user filter which ensures our rules are followed, I.E. Only admins can se other admins. + /// Creates a base user filter which ensures our rules are followed, i.e. only admins can see other admins. /// /// - /// We return the query as an out parameter instead of having it in the intermediate object because a two queries cannot be merged into one. + /// We return the query as an out parameter instead of having it in the intermediate object because two queries cannot be merged into one. /// - /// + /// The user performing the query. + /// The base query to apply filters to. + /// A with the base filter rules applied. private UserFilter CreateBaseUserFilter(IUser performingUser, out IQuery baseQuery) { var filter = new UserFilter(); @@ -1390,6 +1361,11 @@ private UserFilter CreateBaseUserFilter(IUser performingUser, out IQuery return filter; } + /// + /// Gets user group aliases from their keys. + /// + /// The user group keys to convert. + /// An attempt containing the aliases or an error status. private Attempt, UserOperationStatus> GetUserGroupAliasesFromKeys(IEnumerable userGroupKeys) { var aliases = new List(); @@ -1408,6 +1384,11 @@ private Attempt, UserOperationStatus> GetUserGroupAliasesFro return Attempt.SucceedWithStatus, UserOperationStatus>(UserOperationStatus.Success, aliases); } + /// + /// Gets the order by expression for user queries. + /// + /// The order by specification. + /// An expression for ordering users. private Expression> GetOrderByExpression(UserOrder orderBy) { return orderBy switch @@ -1426,6 +1407,7 @@ private Attempt, UserOperationStatus> GetUserGroupAliasesFro }; } + /// public async Task DeleteAsync(Guid performingUserKey, ISet keys) { if(keys.Any() is false) @@ -1474,6 +1456,7 @@ public async Task DeleteAsync(Guid performingUserKey, ISet< return UserOperationStatus.Success; } + /// public async Task DisableAsync(Guid performingUserKey, ISet keys) { if(keys.Any() is false) @@ -1520,6 +1503,7 @@ public async Task DisableAsync(Guid performingUserKey, ISet return UserOperationStatus.Success; } + /// public async Task EnableAsync(Guid performingUserKey, ISet keys) { if(keys.Any() is false) @@ -1555,6 +1539,7 @@ public async Task EnableAsync(Guid performingUserKey, ISet< return UserOperationStatus.Success; } + /// public async Task ClearAvatarAsync(Guid userKey) { IUser? user = await GetAsync(userKey); @@ -1590,6 +1575,7 @@ public async Task ClearAvatarAsync(Guid userKey) return UserOperationStatus.Success; } + /// public async Task> UnlockAsync(Guid performingUserKey, params Guid[] keys) { if (keys.Length == 0) @@ -1624,6 +1610,7 @@ public async Task> UnlockAsync(Gu return Attempt.SucceedWithStatus(UserOperationStatus.Success, new UserUnlockResult()); } + /// public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection, UserState[]? userState = null, string[]? userGroups = null, string? filter = null) { IQuery? filterQuery = null; @@ -1636,6 +1623,7 @@ public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRec return GetAll(pageIndex, pageSize, out totalRecords, orderBy, orderDirection, userState, userGroups, null, filterQuery); } + /// public IEnumerable GetAll( long pageIndex, int pageSize, @@ -1690,15 +1678,7 @@ public IEnumerable GetAll( } } - /// - /// Gets a list of paged objects - /// - /// Current page index - /// Size of the page - /// Total number of records found (out) - /// - /// - /// + /// public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRecords) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -1707,13 +1687,7 @@ public IEnumerable GetAll(long pageIndex, int pageSize, out long totalRec } } - /// - /// Gets a list of objects associated with a given group - /// - /// Id of group - /// - /// - /// + /// public IEnumerable GetAllInGroup(int? groupId) { if (groupId is null) @@ -1727,13 +1701,7 @@ public IEnumerable GetAllInGroup(int? groupId) return backOfficeUserStore.GetAllInGroupAsync(groupId.Value).GetAwaiter().GetResult(); } - /// - /// Gets a list of objects not associated with a given group - /// - /// Id of group - /// - /// - /// + /// public IEnumerable GetAllNotInGroup(int groupId) { using (ICoreScope scope = ScopeProvider.CreateCoreScope()) @@ -1746,13 +1714,7 @@ public IEnumerable GetAllNotInGroup(int groupId) #region Implementation of IUserService - /// - /// Gets an IProfile by User Id. - /// - /// Id of the User to retrieve - /// - /// - /// + /// public IProfile? GetProfileById(int id) { // This is called a TON. Go get the full user from cache which should already be IProfile @@ -1766,13 +1728,7 @@ public IEnumerable GetAllNotInGroup(int groupId) return asProfile ?? new UserProfile(fullUser.Id, fullUser.Name); } - /// - /// Gets a profile by username - /// - /// Username - /// - /// - /// + /// public IProfile? GetProfileByUserName(string username) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -1781,13 +1737,7 @@ public IEnumerable GetAllNotInGroup(int groupId) } } - /// - /// Gets a user by Id - /// - /// Id of the user to retrieve. - /// - /// - /// + /// public IUser? GetUserById(int id) { using IServiceScope scope = _serviceScopeFactory.CreateScope(); @@ -1796,11 +1746,7 @@ public IEnumerable GetAllNotInGroup(int groupId) return backOfficeUserStore.GetAsync(id).GetAwaiter().GetResult(); } - /// - /// Gets a user by it's key. - /// - /// Key of the user to retrieve. - /// Task resolving into an . + /// public Task GetAsync(Guid key) { using IServiceScope scope = _serviceScopeFactory.CreateScope(); @@ -1809,6 +1755,7 @@ public IEnumerable GetAllNotInGroup(int groupId) return backOfficeUserStore.GetAsync(key); } + /// public Task> GetAsync(IEnumerable keys) { using IServiceScope scope = _serviceScopeFactory.CreateScope(); @@ -1817,6 +1764,7 @@ public Task> GetAsync(IEnumerable keys) return backOfficeUserStore.GetUsersAsync(keys.ToArray()); } + /// public async Task, UserOperationStatus>> GetLinkedLoginsAsync(Guid userKey) { using IServiceScope scope = _serviceScopeFactory.CreateScope(); @@ -1837,6 +1785,7 @@ public async Task, UserOperationStatus>> : Attempt.SucceedWithStatus(UserOperationStatus.Success, loginsAttempt.Result); } + /// public IEnumerable GetUsersById(params int[]? ids) { using IServiceScope scope = _serviceScopeFactory.CreateScope(); @@ -1845,16 +1794,7 @@ public IEnumerable GetUsersById(params int[]? ids) return backOfficeUserStore.GetUsersAsync(ids).GetAwaiter().GetResult(); } - /// - /// Replaces the same permission set for a single group to any number of entities - /// - /// If no 'entityIds' are specified all permissions will be removed for the specified group. - /// Id of the group - /// - /// Permissions as enumerable list of If nothing is specified all permissions - /// are removed. - /// - /// Specify the nodes to replace permissions for. + /// public void ReplaceUserGroupPermissions(int groupId, ISet permissions, params int[] entityIds) { if (entityIds.Length == 0) @@ -1878,12 +1818,7 @@ public void ReplaceUserGroupPermissions(int groupId, ISet permissions, p } } - /// - /// Assigns the same permission set for a single user group to any number of entities - /// - /// Id of the user group - /// - /// Specify the nodes to replace permissions for + /// public void AssignUserGroupPermission(int groupId, string permission, params int[] entityIds) { if (entityIds.Length == 0) @@ -1905,6 +1840,7 @@ public void AssignUserGroupPermission(int groupId, string permission, params int } } + /// public async Task> VerifyPasswordResetAsync(Guid userKey, string token) { var decoded = token.FromUrlBase64(); @@ -1931,6 +1867,7 @@ public async Task> VerifyPasswordResetAsync(Guid us : Attempt.Fail(UserOperationStatus.InvalidPasswordResetToken); } + /// public async Task> VerifyInviteAsync(Guid userKey, string token) { var decoded = token.FromUrlBase64(); @@ -1957,6 +1894,7 @@ public async Task> VerifyInviteAsync(Guid userKey, : Attempt.Fail(UserOperationStatus.InvalidInviteToken); } + /// public async Task> CreateInitialPasswordAsync(Guid userKey, string token, string password) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -1980,6 +1918,7 @@ public async Task> CreateInit return changePasswordAttempt; } + /// public async Task> ResetPasswordAsync(Guid userKey, string token, string password) { using ICoreScope scope = ScopeProvider.CreateCoreScope(); @@ -2013,6 +1952,7 @@ public async Task> ResetPassw return changePasswordAttempt; } + /// public async Task> ResetPasswordAsync(Guid performingUserKey, Guid userKey) { if (performingUserKey.Equals(userKey)) @@ -2049,11 +1989,7 @@ public async Task> ResetPassw } - /// - /// Removes a specific section from all users - /// - /// This is useful when an entire section is removed from config - /// Alias of the section to remove + /// public void DeleteSectionFromAllUserGroups(string sectionAlias) { using (ICoreScope scope = ScopeProvider.CreateCoreScope()) @@ -2105,7 +2041,12 @@ public async Task, UserOperationStatus>> Ge return permissions; } - + /// + /// Gets permissions for a user and a set of nodes. + /// + /// The key of the user to get permissions for. + /// A dictionary mapping node keys to node IDs. + /// An attempt containing the permissions or an error status. private async Task, UserOperationStatus>> GetPermissionsAsync(Guid userKey, Dictionary nodes) { IUser? user = await GetAsync(userKey); @@ -2130,6 +2071,12 @@ private async Task, UserOperationStatus>> G return Attempt.SucceedWithStatus, UserOperationStatus>(UserOperationStatus.Success, results); } + /// + /// Creates a mapping between node keys and their IDs. + /// + /// The keys of the nodes. + /// The type of Umbraco object. + /// An attempt containing the key-to-ID mapping or null if any key was not found. private Attempt?> CreateIdKeyMap(IEnumerable nodeKeys, UmbracoObjectTypes objectType) { // We'll return this as a dictionary we can link the id and key again later. @@ -2193,12 +2140,7 @@ public async Task, UserOperationStatus>> Ge return Attempt.SucceedWithStatus, UserOperationStatus>(UserOperationStatus.Success, results); } - /// - /// Get explicitly assigned permissions for a user and optional node ids - /// - /// User to retrieve permissions for - /// Specifying nothing will return all permissions for all nodes - /// An enumerable list of + /// public EntityPermissionCollection GetPermissions(IUser? user, params int[] nodeIds) { using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true)) @@ -2207,16 +2149,7 @@ public EntityPermissionCollection GetPermissions(IUser? user, params int[] nodeI } } - /// - /// Get explicitly assigned permissions for a group and optional node Ids - /// - /// - /// - /// Flag indicating if we want to include the default group permissions for each result if there are not explicit - /// permissions set - /// - /// Specifying nothing will return all permissions for all nodes - /// An enumerable list of + /// public EntityPermissionCollection GetPermissions(IUserGroup?[] groups, bool fallbackToDefaultPermissions, params int[] nodeIds) { if (groups == null) @@ -2234,15 +2167,15 @@ public EntityPermissionCollection GetPermissions(IUserGroup?[] groups, bool fall } /// - /// Get explicitly assigned permissions for a group and optional node Ids + /// Gets explicitly assigned permissions for read-only user groups and optional node IDs. /// - /// Groups to retrieve permissions for + /// The read-only user groups to retrieve permissions for. /// - /// Flag indicating if we want to include the default group permissions for each result if there are not explicit - /// permissions set + /// Flag indicating if we want to include the default group permissions for each result if there are no explicit + /// permissions set. /// - /// Specifying nothing will return all permissions for all nodes - /// An enumerable list of + /// Specifying nothing will return all permissions for all nodes. + /// An enumerable list of . private IEnumerable GetPermissions(IReadOnlyUserGroup[] groups, bool fallbackToDefaultPermissions, params int[] nodeIds) { if (groups == null) @@ -2256,11 +2189,7 @@ private IEnumerable GetPermissions(IReadOnlyUserGroup[] groups } } - /// - /// Gets the implicit/inherited permissions for the user for the given path - /// - /// User to check permissions for - /// Path to check permissions for + /// public EntityPermissionSet GetPermissionsForPath(IUser? user, string? path) { var nodeIds = path?.GetIdsFromPathReversed(); @@ -2277,16 +2206,7 @@ public EntityPermissionSet GetPermissionsForPath(IUser? user, string? path) } - /// - /// Gets the permissions for the provided group and path - /// - /// - /// Path to check permissions for - /// - /// Flag indicating if we want to include the default group permissions for each result if there are not explicit - /// permissions set - /// - /// String indicating permissions for provided user and path + /// public EntityPermissionSet GetPermissionsForPath(IUserGroup[] groups, string path, bool fallbackToDefaultPermissions = false) { var nodeIds = path.GetIdsFromPathReversed(); @@ -2303,6 +2223,7 @@ public EntityPermissionSet GetPermissionsForPath(IUserGroup[] groups, string pat return CalculatePermissionsForPathForUser(groupPermissions, nodeIds); } + /// public async Task AddClientIdAsync(Guid userKey, string clientId) { if (ValidClientId().IsMatch(clientId) is false) @@ -2329,6 +2250,7 @@ public async Task AddClientIdAsync(Guid us return UserClientCredentialsOperationStatus.Success; } + /// public async Task RemoveClientIdAsync(Guid userKey, string clientId) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -2337,6 +2259,7 @@ public async Task RemoveClientIdAsync(Guid userKey, string clientId) return _userRepository.RemoveClientId(userId, clientId); } + /// public Task FindByClientIdAsync(string clientId) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -2345,6 +2268,7 @@ public async Task RemoveClientIdAsync(Guid userKey, string clientId) return Task.FromResult(user?.Kind == UserKind.Api ? user : null); } + /// public async Task> GetClientIdsAsync(Guid userKey) { using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true); @@ -2429,6 +2353,16 @@ internal static EntityPermissionSet CalculatePermissionsForPathForUser( return permissionSet; } + /// + /// Gets permissions for a path for the specified user groups. + /// + /// The user groups to get permissions for. + /// The path IDs ordered from deepest to shallowest. + /// + /// Flag indicating if we want to include the default group permissions for each result if there are no explicit + /// permissions set. + /// + /// A collection of . private EntityPermissionCollection GetPermissionsForPath(IReadOnlyUserGroup[] groups, int[] pathIds, bool fallbackToDefaultPermissions = false) { if (pathIds.Length == 0) @@ -2489,6 +2423,11 @@ private EntityPermissionCollection GetPermissionsForPath(IReadOnlyUserGroup[] gr return permissionsByEntityId[pathIds[0]]; } + /// + /// Adds additional permissions to an existing permission set. + /// + /// The existing permission set to add to. + /// The additional permissions to add. private static void AddAdditionalPermissions(ISet assignedPermissions, ISet additionalPermissions) { foreach (var additionalPermission in additionalPermissions) @@ -2497,6 +2436,10 @@ private static void AddAdditionalPermissions(ISet assignedPermissions, I } } + /// + /// Gets a regex pattern for validating client IDs. + /// + /// A for validating client IDs. [GeneratedRegex(@"^[\w\d\-\._~]{1,100}$")] private static partial Regex ValidClientId(); diff --git a/src/Umbraco.Core/Services/UserServiceExtensions.cs b/src/Umbraco.Core/Services/UserServiceExtensions.cs index ec88d576531e..ae26fd70b0a2 100644 --- a/src/Umbraco.Core/Services/UserServiceExtensions.cs +++ b/src/Umbraco.Core/Services/UserServiceExtensions.cs @@ -5,13 +5,31 @@ namespace Umbraco.Extensions; +/// +/// Provides extension methods for . +/// public static class UserServiceExtensions { + /// + /// Gets the first permission for a user at the specified path. + /// + /// The user service. + /// The user to get permissions for. + /// The path to check permissions for. + /// The first found, or null if none exists. public static EntityPermission? GetPermissions(this IUserService userService, IUser? user, string path) { return userService.GetAllPermissions(user, path).FirstOrDefault(); } + /// + /// Gets all permissions for a user at the specified path. + /// + /// The user service. + /// The user to get permissions for. + /// The path to check permissions for. + /// A collection of for the specified path. + /// Thrown when the path cannot be parsed into an array of integers or is empty. public static EntityPermissionCollection GetAllPermissions(this IUserService userService, IUser? user, string path) { var ids = path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries) @@ -75,6 +93,12 @@ public static void RemoveUserGroupPermissions(this IUserService userService, int public static void RemoveUserGroupPermissions(this IUserService userService, int groupId) => userService.ReplaceUserGroupPermissions(groupId, new HashSet()); + /// + /// Gets user profiles by their identifiers. + /// + /// The user service. + /// The user identifiers to retrieve profiles for. + /// An enumerable collection of instances. public static IEnumerable GetProfilesById(this IUserService userService, params int[] ids) { IEnumerable fullUsers = userService.GetUsersById(ids); diff --git a/src/Umbraco.Core/Services/UserTwoFactorLoginService.cs b/src/Umbraco.Core/Services/UserTwoFactorLoginService.cs index 58352a242f91..e68cd37a40c3 100644 --- a/src/Umbraco.Core/Services/UserTwoFactorLoginService.cs +++ b/src/Umbraco.Core/Services/UserTwoFactorLoginService.cs @@ -11,6 +11,13 @@ internal sealed class UserTwoFactorLoginService : TwoFactorLoginServiceBase, IUs { private readonly IUserService _userService; + /// + /// Initializes a new instance of the class. + /// + /// The two-factor login service. + /// The two-factor setup generators. + /// The user service. + /// The scope provider. public UserTwoFactorLoginService( ITwoFactorLoginService twoFactorLoginService, IEnumerable twoFactorSetupGenerators, diff --git a/src/Umbraco.Core/Services/WebProfilerService.cs b/src/Umbraco.Core/Services/WebProfilerService.cs index af89c8bf1a9e..b324162e41e4 100644 --- a/src/Umbraco.Core/Services/WebProfilerService.cs +++ b/src/Umbraco.Core/Services/WebProfilerService.cs @@ -4,17 +4,24 @@ namespace Umbraco.Cms.Core.Services; +/// internal sealed class WebProfilerService : IWebProfilerService { private readonly IWebProfilerRepository _webProfilerRepository; private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor; + /// + /// Initializes a new instance of the class. + /// + /// The web profiler repository. + /// The backoffice security accessor. public WebProfilerService(IWebProfilerRepository webProfilerRepository, IBackOfficeSecurityAccessor backOfficeSecurityAccessor) { _webProfilerRepository = webProfilerRepository; _backOfficeSecurityAccessor = backOfficeSecurityAccessor; } + /// public Task> GetStatus() { Attempt userIdAttempt = GetExecutingUserId(); @@ -28,6 +35,7 @@ public Task> GetStatus() return Task.FromResult(Attempt.SucceedWithStatus(WebProfilerOperationStatus.Success, result)); } + /// public Task> SetStatus(bool status) { Attempt userIdAttempt = GetExecutingUserId(); @@ -41,6 +49,10 @@ public Task> SetStatus(bool status) return Task.FromResult(Attempt.SucceedWithStatus(WebProfilerOperationStatus.Success, status)); } + /// + /// Gets the identifier of the currently executing user. + /// + /// An containing the user identifier if successful. private Attempt GetExecutingUserId() { //FIXME when we can get current user diff --git a/src/Umbraco.Core/Services/WebhookLogFactory.cs b/src/Umbraco.Core/Services/WebhookLogFactory.cs index 3c260c017ff6..ed644beb3e98 100644 --- a/src/Umbraco.Core/Services/WebhookLogFactory.cs +++ b/src/Umbraco.Core/Services/WebhookLogFactory.cs @@ -1,11 +1,15 @@ -using System.Net; +using System.Net; using System.Text; using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Services; +/// +/// Implements to create webhook log entries. +/// public class WebhookLogFactory : IWebhookLogFactory { + /// public async Task CreateAsync(string eventAlias, HttpRequestMessage requestMessage, HttpResponseMessage? httpResponseMessage, int retryCount, Exception? exception, IWebhook webhook, CancellationToken cancellationToken) { var log = new WebhookLog @@ -49,8 +53,18 @@ public async Task CreateAsync(string eventAlias, HttpRequestMessage return log; } + /// + /// Maps an HTTP status code to a human-readable message. + /// + /// The HTTP status code. + /// A formatted string containing the status code name and numeric value. private string MapStatusCodeToMessage(HttpStatusCode statusCode) => $"{statusCode.ToString()} ({(int)statusCode})"; + /// + /// Calculates and formats the headers from an HTTP response message. + /// + /// The HTTP response message. + /// A formatted string containing all headers. private string CalculateHeaders(HttpResponseMessage responseMessage) { IEnumerable>> headers = responseMessage.RequestMessage!.Headers.Concat(responseMessage.RequestMessage.Content!.Headers); diff --git a/src/Umbraco.Core/Services/WebhookLogService.cs b/src/Umbraco.Core/Services/WebhookLogService.cs index 4257b775d4d1..ab30db20437d 100644 --- a/src/Umbraco.Core/Services/WebhookLogService.cs +++ b/src/Umbraco.Core/Services/WebhookLogService.cs @@ -4,17 +4,26 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Implements to manage webhook log entries. +/// public class WebhookLogService : IWebhookLogService { private readonly IWebhookLogRepository _webhookLogRepository; private readonly ICoreScopeProvider _coreScopeProvider; + /// + /// Initializes a new instance of the class. + /// + /// The webhook log repository. + /// The core scope provider. public WebhookLogService(IWebhookLogRepository webhookLogRepository, ICoreScopeProvider coreScopeProvider) { _webhookLogRepository = webhookLogRepository; _coreScopeProvider = coreScopeProvider; } + /// public async Task CreateAsync(WebhookLog webhookLog) { using ICoreScope scope = _coreScopeProvider.CreateCoreScope(); @@ -24,12 +33,14 @@ public async Task CreateAsync(WebhookLog webhookLog) return webhookLog; } + /// public async Task> Get(int skip = 0, int take = int.MaxValue) { using ICoreScope scope = _coreScopeProvider.CreateCoreScope(autoComplete: true); return await _webhookLogRepository.GetPagedAsync(skip, take); } + /// public async Task> Get(Guid webhookKey, int skip = 0, int take = int.MaxValue) { using ICoreScope scope = _coreScopeProvider.CreateCoreScope(autoComplete: true); diff --git a/src/Umbraco.Core/Services/WebhookRequestService.cs b/src/Umbraco.Core/Services/WebhookRequestService.cs index 53ff1b7abb81..ddd971fc4606 100644 --- a/src/Umbraco.Core/Services/WebhookRequestService.cs +++ b/src/Umbraco.Core/Services/WebhookRequestService.cs @@ -1,16 +1,29 @@ -using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Serialization; namespace Umbraco.Cms.Core.Services; +/// +/// Provides functionality for managing webhook requests. +/// +/// +/// Webhook requests are queued when events occur and are processed asynchronously +/// to send HTTP callbacks to configured webhook endpoints. +/// public class WebhookRequestService : IWebhookRequestService { private readonly ICoreScopeProvider _coreScopeProvider; private readonly IWebhookRequestRepository _webhookRequestRepository; private readonly IWebhookJsonSerializer _webhookJsonSerializer; + /// + /// Initializes a new instance of the class. + /// + /// The scope provider for unit of work operations. + /// The repository for webhook request data access. + /// The serializer for converting payloads to JSON. public WebhookRequestService(ICoreScopeProvider coreScopeProvider, IWebhookRequestRepository webhookRequestRepository, IWebhookJsonSerializer webhookJsonSerializer) { _coreScopeProvider = coreScopeProvider; @@ -18,6 +31,7 @@ public WebhookRequestService(ICoreScopeProvider coreScopeProvider, IWebhookReque _webhookJsonSerializer = webhookJsonSerializer; } + /// public async Task CreateAsync(Guid webhookKey, string eventAlias, object? payload) { using ICoreScope scope = _coreScopeProvider.CreateCoreScope(); @@ -36,6 +50,7 @@ public async Task CreateAsync(Guid webhookKey, string eventAlias return webhookRequest; } + /// public Task> GetAllAsync() { using ICoreScope scope = _coreScopeProvider.CreateCoreScope(); @@ -44,6 +59,7 @@ public Task> GetAllAsync() return webhookRequests; } + /// public async Task DeleteAsync(WebhookRequest webhookRequest) { using ICoreScope scope = _coreScopeProvider.CreateCoreScope(); @@ -52,6 +68,7 @@ public async Task DeleteAsync(WebhookRequest webhookRequest) scope.Complete(); } + /// public async Task UpdateAsync(WebhookRequest webhookRequest) { using ICoreScope scope = _coreScopeProvider.CreateCoreScope(); diff --git a/src/Umbraco.Core/Services/WebhookService.cs b/src/Umbraco.Core/Services/WebhookService.cs index f6eff0b315d4..9755ea0242ad 100644 --- a/src/Umbraco.Core/Services/WebhookService.cs +++ b/src/Umbraco.Core/Services/WebhookService.cs @@ -7,12 +7,21 @@ namespace Umbraco.Cms.Core.Services; +/// +/// Implements to manage webhooks. +/// public class WebhookService : IWebhookService { private readonly ICoreScopeProvider _provider; private readonly IWebhookRepository _webhookRepository; private readonly IEventMessagesFactory _eventMessagesFactory; + /// + /// Initializes a new instance of the class. + /// + /// The core scope provider. + /// The webhook repository. + /// The event messages factory. public WebhookService(ICoreScopeProvider provider, IWebhookRepository webhookRepository, IEventMessagesFactory eventMessagesFactory) { _provider = provider; @@ -20,6 +29,11 @@ public WebhookService(ICoreScopeProvider provider, IWebhookRepository webhookRep _eventMessagesFactory = eventMessagesFactory; } + /// + /// Validates that a webhook has the required configuration. + /// + /// The webhook to validate. + /// The indicating the validation result. private WebhookOperationStatus ValidateWebhook(IWebhook webhook) { if (webhook.Events.Length <= 0) diff --git a/src/Umbraco.Core/SimpleMainDom.cs b/src/Umbraco.Core/SimpleMainDom.cs index ffdd7e706cb3..c835f56d5cb3 100644 --- a/src/Umbraco.Core/SimpleMainDom.cs +++ b/src/Umbraco.Core/SimpleMainDom.cs @@ -16,6 +16,7 @@ public class SimpleMainDom : IMainDom, IDisposable /// public bool IsMainDom { get; private set; } = true; + /// public void Dispose() { // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method @@ -23,6 +24,11 @@ public void Dispose() GC.SuppressFinalize(this); } + /// + /// Acquires the main domain status. + /// + /// The application shutdown registry. + /// Always returns true as this is a simple implementation. // always acquire public bool Acquire(IApplicationShutdownRegistry hostingEnvironment) => true; @@ -46,6 +52,9 @@ public bool Register(Action? install, Action? release, int weight = 100) } } + /// + /// Stops the main domain and executes all registered release callbacks. + /// public void Stop() { lock (_locko) @@ -77,6 +86,10 @@ public void Stop() } } + /// + /// Releases the unmanaged resources used by the and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (!_disposedValue) diff --git a/src/Umbraco.Core/Snippets/PartialViewSnippet.cs b/src/Umbraco.Core/Snippets/PartialViewSnippet.cs index 87a1e62bfb90..71e701f2707a 100644 --- a/src/Umbraco.Core/Snippets/PartialViewSnippet.cs +++ b/src/Umbraco.Core/Snippets/PartialViewSnippet.cs @@ -1,10 +1,20 @@ -namespace Umbraco.Cms.Core.Snippets; +namespace Umbraco.Cms.Core.Snippets; /// -/// Defines a partial view snippet. +/// Defines a partial view snippet with its content. /// +/// +/// A partial view snippet is a predefined template that can be used when creating new partial views. +/// This class extends by including the actual content of the snippet. +/// public class PartialViewSnippet : PartialViewSnippetSlim { + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier for the snippet. + /// The display name of the snippet. + /// The content (Razor markup) of the snippet. public PartialViewSnippet(string id, string name, string content) : base(id, name) => Content = content; diff --git a/src/Umbraco.Core/Snippets/PartialViewSnippetCollection.cs b/src/Umbraco.Core/Snippets/PartialViewSnippetCollection.cs index a49c2c897a53..1555ef3033b5 100644 --- a/src/Umbraco.Core/Snippets/PartialViewSnippetCollection.cs +++ b/src/Umbraco.Core/Snippets/PartialViewSnippetCollection.cs @@ -2,8 +2,19 @@ namespace Umbraco.Cms.Core.Snippets; +/// +/// Represents a collection of instances. +/// +/// +/// This collection contains all registered partial view snippets that can be used +/// when creating new partial views in the Umbraco backoffice. +/// public class PartialViewSnippetCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that provides the partial view snippets. public PartialViewSnippetCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/Snippets/PartialViewSnippetCollectionBuilder.cs b/src/Umbraco.Core/Snippets/PartialViewSnippetCollectionBuilder.cs index 9e9746afe4dc..c1ceab8e8204 100644 --- a/src/Umbraco.Core/Snippets/PartialViewSnippetCollectionBuilder.cs +++ b/src/Umbraco.Core/Snippets/PartialViewSnippetCollectionBuilder.cs @@ -13,8 +13,10 @@ namespace Umbraco.Cms.Core.Snippets; /// public partial class PartialViewSnippetCollectionBuilder : LazyCollectionBuilderBase { + /// protected override PartialViewSnippetCollectionBuilder This => this; + /// protected override IEnumerable CreateItems(IServiceProvider factory) { var embeddedSnippets = new List(base.CreateItems(factory)); @@ -36,6 +38,11 @@ protected override IEnumerable CreateItems(IServiceProvider return embeddedSnippets; } + /// + /// Cleans up snippet content by normalizing line endings and adjusting the header. + /// + /// The raw snippet content to clean up. + /// The cleaned snippet content with a standard header. private string CleanUpSnippetContent(string content) { const string partialViewHeader = "@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage"; diff --git a/src/Umbraco.Core/Snippets/PartialViewSnippetSlim.cs b/src/Umbraco.Core/Snippets/PartialViewSnippetSlim.cs index 6cf28522d902..15c6957e1231 100644 --- a/src/Umbraco.Core/Snippets/PartialViewSnippetSlim.cs +++ b/src/Umbraco.Core/Snippets/PartialViewSnippetSlim.cs @@ -1,10 +1,19 @@ -namespace Umbraco.Cms.Core.Snippets; +namespace Umbraco.Cms.Core.Snippets; /// /// A lightweight representation of a partial view snippet (i.e. without content). /// +/// +/// This class is used for listing snippets without loading their full content, +/// improving performance when displaying available snippets in the UI. +/// public class PartialViewSnippetSlim { + /// + /// Initializes a new instance of the class. + /// + /// The unique identifier for the snippet. + /// The display name of the snippet. public PartialViewSnippetSlim(string id, string name) { Id = id; diff --git a/src/Umbraco.Core/StaticApplicationLogging.cs b/src/Umbraco.Core/StaticApplicationLogging.cs index eac0a3f51b4f..42ae5e32fa01 100644 --- a/src/Umbraco.Core/StaticApplicationLogging.cs +++ b/src/Umbraco.Core/StaticApplicationLogging.cs @@ -3,16 +3,40 @@ namespace Umbraco.Cms.Core; +/// +/// Provides static access to application logging functionality. +/// +/// +/// This class provides a way to access logging before dependency injection is fully configured. +/// It must be initialized with an before use. +/// public static class StaticApplicationLogging { private static ILoggerFactory? loggerFactory; + /// + /// Gets a default logger instance for general logging purposes. + /// public static ILogger Logger => CreateLogger(); + /// + /// Initializes the static logging with the specified logger factory. + /// + /// The to use for creating loggers. public static void Initialize(ILoggerFactory loggerFactory) => StaticApplicationLogging.loggerFactory = loggerFactory; + /// + /// Creates a logger for the specified type. + /// + /// The type to create a logger for. + /// An instance, or a null logger if not initialized. public static ILogger CreateLogger() => loggerFactory?.CreateLogger() ?? NullLoggerFactory.Instance.CreateLogger(); + /// + /// Creates a logger for the specified type. + /// + /// The type to create a logger for. + /// An instance, or a null logger if not initialized. public static ILogger CreateLogger(Type type) => loggerFactory?.CreateLogger(type) ?? NullLogger.Instance; } diff --git a/src/Umbraco.Core/StringUdi.cs b/src/Umbraco.Core/StringUdi.cs index 32e3677e2fa2..fec7e139b8cc 100644 --- a/src/Umbraco.Core/StringUdi.cs +++ b/src/Umbraco.Core/StringUdi.cs @@ -33,6 +33,11 @@ public StringUdi(Uri uriValue) /// public override bool IsRoot => Id == string.Empty; + /// + /// Ensures that this StringUdi is not a root Udi. + /// + /// This StringUdi. + /// When this Udi is a root Udi. public StringUdi EnsureClosed() { EnsureNotRoot(); diff --git a/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs b/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs index 85ce81390714..bd6240cec67f 100644 --- a/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs +++ b/src/Umbraco.Core/Strings/Css/StylesheetHelper.cs @@ -3,12 +3,25 @@ namespace Umbraco.Cms.Core.Strings.Css; -// FIXME: remove this class and all usage of it (moved to the client in V14) +/// +/// Provides helper methods for parsing and manipulating Umbraco-style CSS stylesheet rules. +/// +/// +/// FIXME: remove this class and all usage of it (moved to the client in V14). +/// public class StylesheetHelper { + /// + /// The regular expression format for matching Umbraco stylesheet rules. + /// private const string RuleRegexFormat = @"/\*\*\s*umb_name:\s*(?{0}?)\s*\*/\s*(?[^,{{]*?)\s*{{\s*(?.*?)\s*}}"; + /// + /// Parses stylesheet rules from a CSS string. + /// + /// The CSS content to parse. + /// A collection of objects extracted from the input. public static IEnumerable ParseRules(string? input) { var rules = new List(); @@ -47,6 +60,13 @@ public static IEnumerable ParseRules(string? input) return rules; } + /// + /// Replaces a stylesheet rule in the CSS content. + /// + /// The CSS content containing the rule to replace. + /// The name of the rule to replace. + /// The new rule to insert, or null to remove the rule. + /// The modified CSS content with the rule replaced or removed. public static string? ReplaceRule(string? input, string oldRuleName, StylesheetRule? rule) { var contents = input; @@ -61,6 +81,12 @@ public static IEnumerable ParseRules(string? input) return contents; } + /// + /// Appends a stylesheet rule to the CSS content. + /// + /// The existing CSS content. + /// The rule to append. + /// The CSS content with the new rule appended. public static string AppendRule(string? input, StylesheetRule rule) { var contents = input; diff --git a/src/Umbraco.Core/Strings/Css/StylesheetRule.cs b/src/Umbraco.Core/Strings/Css/StylesheetRule.cs index 032901c13e93..d3354946f34b 100644 --- a/src/Umbraco.Core/Strings/Css/StylesheetRule.cs +++ b/src/Umbraco.Core/Strings/Css/StylesheetRule.cs @@ -3,14 +3,30 @@ namespace Umbraco.Cms.Core.Strings.Css; +/// +/// Represents a CSS rule with a name, selector, and styles, formatted for Umbraco's Rich Text Editor. +/// public class StylesheetRule { + /// + /// Gets or sets the name of the stylesheet rule. + /// public string Name { get; set; } = null!; + /// + /// Gets or sets the CSS selector for this rule. + /// public string Selector { get; set; } = null!; + /// + /// Gets or sets the CSS styles for this rule. + /// public string Styles { get; set; } = null!; + /// + /// Returns a string representation of the stylesheet rule in Umbraco's format. + /// + /// A CSS-formatted string with the Umbraco name comment, selector, and styles. public override string ToString() { var sb = new StringBuilder(); diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs index 581cd168a3e2..bf02ac5b331f 100644 --- a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs +++ b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs @@ -19,12 +19,19 @@ public class DefaultShortStringHelper : IShortStringHelper { #region Ctor, consts and vars + /// + /// Initializes a new instance of the class using request handler settings. + /// + /// The request handler settings containing character replacement rules. public DefaultShortStringHelper(IOptions settings) { _config = new DefaultShortStringHelperConfig().WithDefault(settings.Value); } - // clones the config so it cannot be changed at runtime + /// + /// Initializes a new instance of the class using a custom configuration. + /// + /// The configuration to use. The configuration is cloned to prevent runtime modification. public DefaultShortStringHelper(DefaultShortStringHelperConfig config) { _config = config.Clone(); @@ -54,6 +61,11 @@ public DefaultShortStringHelper(DefaultShortStringHelperConfig config) .Distinct() .ToFrozenSet(); + /// + /// Determines whether a character is valid for use in a file name. + /// + /// The character to test. + /// true if the character is valid for file names; otherwise, false. public static bool IsValidFileNameChar(char c) { return InvalidFileNameChars.Contains(c) == false; @@ -235,6 +247,14 @@ public string CleanString(string text, CleanStringType stringType, char separato return CleanString(text, stringType, culture, separator); } + /// + /// Cleans a string according to the specified string type, culture, and separator. + /// + /// The text to clean. + /// The type of cleaning to perform. + /// The culture to use for casing. + /// The separator character to use between terms. + /// The cleaned string. protected virtual string CleanString(string text, CleanStringType stringType, string? culture, char? separator) { // be safe @@ -329,11 +349,18 @@ private static string RemoveSurrogatePairs(string text) return new string(output); } - // here was a subtle, ascii-optimized version of the cleaning code, and I was - // very proud of it until benchmarking showed it was an order of magnitude slower - // that the utf8 version. Micro-optimizing sometimes isn't such a good idea. - - // note: does NOT support surrogate pairs in text + /// + /// Cleans a string for use as a code identifier using the specified case type, separator, culture and configuration. + /// + /// The text to clean. + /// The case type to apply (camelCase, PascalCase, etc.). + /// The separator character to use between terms. + /// The culture to use for casing. + /// The configuration settings for string cleaning. + /// The cleaned code string. + /// + /// Does NOT support surrogate pairs in text. + /// internal string CleanCodeString(string text, CleanStringType caseType, char separator, string culture, DefaultShortStringHelperConfig.Config config) { int opos = 0, ipos = 0; @@ -484,7 +511,20 @@ internal string CleanCodeString(string text, CleanStringType caseType, char sepa return new string(output.Slice(0, opos)); } - // note: supports surrogate pairs in input string + /// + /// Copies a term from the input string to the output buffer, applying the specified casing. + /// + /// The input string. + /// The position in the input string. + /// The output buffer. + /// The position in the output buffer (updated by this method). + /// The length of the term to copy. + /// The case type to apply. + /// The culture to use for casing. + /// Whether the term is an acronym. + /// + /// Supports surrogate pairs in input string. + /// internal void CopyTerm(string input, int ipos, Span output, ref int opos, int len, CleanStringType caseType, string culture, bool isAcronym) { var term = input.Substring(ipos, len); diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs index ce395436f2b8..e919f43723ab 100644 --- a/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs +++ b/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs @@ -4,14 +4,34 @@ namespace Umbraco.Cms.Core.Strings; +/// +/// Provides configuration for the . +/// +/// +/// This class manages culture-specific and string-type-specific configurations +/// for cleaning and transforming strings. +/// public class DefaultShortStringHelperConfig { + /// + /// The dictionary of configurations per culture and string type. + /// private readonly Dictionary> _configs = new(); + /// + /// Gets or sets the default culture to use for string operations. + /// public string DefaultCulture { get; set; } = string.Empty; // invariant + /// + /// Gets or sets the dictionary of character replacements for URL generation. + /// public Dictionary? UrlReplaceCharacters { get; set; } + /// + /// Creates a deep copy of this configuration. + /// + /// A new instance with the same settings. public DefaultShortStringHelperConfig Clone() { var config = new DefaultShortStringHelperConfig @@ -33,12 +53,31 @@ public DefaultShortStringHelperConfig Clone() return config; } + /// + /// Adds or updates a configuration for the default culture and all string roles. + /// + /// The configuration to set. + /// This instance for method chaining. public DefaultShortStringHelperConfig WithConfig(Config config) => WithConfig(DefaultCulture, CleanStringType.RoleMask, config); + /// + /// Adds or updates a configuration for the default culture and a specific string role. + /// + /// The string role to configure. + /// The configuration to set. + /// This instance for method chaining. public DefaultShortStringHelperConfig WithConfig(CleanStringType stringRole, Config config) => WithConfig(DefaultCulture, stringRole, config); + /// + /// Adds or updates a configuration for a specific culture and string role. + /// + /// The culture to configure, or null for the default culture. + /// The string role to configure. + /// The configuration to set. + /// This instance for method chaining. + /// Thrown when is null. public DefaultShortStringHelperConfig WithConfig(string? culture, CleanStringType stringRole, Config config) { if (config == null) @@ -127,8 +166,16 @@ public DefaultShortStringHelperConfig WithDefault(RequestHandlerSettings request }); } - // internal: we don't want ppl to retrieve a config and modify it - // (the helper uses a private clone to prevent modifications) + /// + /// Gets the configuration for the specified string type and culture. + /// + /// The type of string cleaning. + /// The culture name. + /// The configuration for the specified string type and culture. + /// + /// Internal: we don't want people to retrieve a config and modify it. + /// The helper uses a private clone to prevent modifications. + /// internal Config For(CleanStringType stringType, string? culture) { culture = culture ?? string.Empty; @@ -174,13 +221,31 @@ internal Config For(CleanStringType stringType, string? culture) public string ApplyUrlReplaceCharacters(string s) => UrlReplaceCharacters == null ? s : s.ReplaceMany(UrlReplaceCharacters); + /// + /// Cuts a string to a maximum length. + /// + /// The text to cut. + /// The maximum length. + /// The original text if shorter than or equal to ; otherwise, the first characters. public static string CutMaxLength(string text, int length) => text.Length <= length ? text : text.Substring(0, length); + /// + /// Represents configuration settings for a specific string type and culture combination. + /// + /// + /// Represents configuration settings for a specific string type and culture combination. + /// public sealed class Config { + /// + /// The default configuration instance returned when no configuration is found. + /// internal static readonly Config NotConfigured = new(); + /// + /// Initializes a new instance of the class with default settings. + /// public Config() { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged; @@ -193,31 +258,59 @@ public Config() Separator = char.MinValue; } + /// + /// Gets or sets a function to apply before string processing. + /// public Func? PreFilter { get; set; } + /// + /// Gets or sets a function to apply after string processing. + /// public Func? PostFilter { get; set; } + /// + /// Gets or sets a function that determines whether a character is a valid term character. + /// + /// + /// The first parameter is the character, the second indicates whether it is a leading character. + /// public Func IsTerm { get; set; } + /// + /// Gets or sets the target string type (casing and encoding). + /// public CleanStringType StringType { get; set; } - // indicate whether an uppercase within a term eg "fooBar" is to break - // into a new term, or to be considered as part of the current term + /// + /// Gets or sets a value indicating whether an uppercase character within a term (e.g., "fooBar") + /// should break into a new term, or be considered as part of the current term. + /// public bool BreakTermsOnUpper { get; set; } - // indicate whether a non-uppercase within an acronym eg "FOOBar" is to cut - // the acronym (at "B" or "a" depending on GreedyAcronyms) or to give - // up the acronym and treat the term as a word + /// + /// Gets or sets a value indicating whether a non-uppercase character within an acronym (e.g., "FOOBar") + /// should cut the acronym or give up the acronym and treat the term as a word. + /// public bool CutAcronymOnNonUpper { get; set; } - // indicates whether acronyms parsing is greedy ie whether "FOObar" is - // "FOO" + "bar" (greedy) or "FO" + "Obar" (non-greedy) + /// + /// Gets or sets a value indicating whether acronym parsing is greedy, + /// i.e., whether "FOObar" is "FOO" + "bar" (greedy) or "FO" + "Obar" (non-greedy). + /// public bool GreedyAcronyms { get; set; } - // the separator char - // but then how can we tell we don't want any? + /// + /// Gets or sets the separator character to use between terms. + /// + /// + /// Use to indicate no separator. + /// public char Separator { get; set; } + /// + /// Creates a deep copy of this configuration. + /// + /// A new instance with the same settings. public Config Clone() => new Config { @@ -231,7 +324,11 @@ public Config Clone() => Separator = Separator, }; - // extends the config + /// + /// Extends the configuration's string type with values from the specified string type. + /// + /// The string type to merge into this configuration. + /// The merged string type. public CleanStringType StringTypeExtend(CleanStringType stringType) { CleanStringType st = StringType; diff --git a/src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs b/src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs index 5e0ae176b720..05b3fe1a1b68 100644 --- a/src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs +++ b/src/Umbraco.Core/Strings/DefaultUrlSegmentProvider.cs @@ -10,9 +10,14 @@ public class DefaultUrlSegmentProvider : IUrlSegmentProvider { private readonly IShortStringHelper _shortStringHelper; + /// + /// Initializes a new instance of the class. + /// + /// The short string helper used to convert strings to URL segments. public DefaultUrlSegmentProvider(IShortStringHelper shortStringHelper) => _shortStringHelper = shortStringHelper; + /// public virtual string? GetUrlSegment(IContentBase content, bool published, string? culture = null) => GetUrlSegmentSource(content, culture, published)?.ToUrlSegment(_shortStringHelper, culture); @@ -25,6 +30,13 @@ public class DefaultUrlSegmentProvider : IUrlSegmentProvider public virtual string? GetUrlSegment(IContentBase content, string? culture = null) => GetUrlSegmentSource(content, culture, true)?.ToUrlSegment(_shortStringHelper, culture); + /// + /// Gets the source string to use for the URL segment. + /// + /// The content. + /// The culture. + /// Whether to get the published or draft source. + /// The source string for the URL segment. private static string? GetUrlSegmentSource(IContentBase content, string? culture, bool published) { string? source = null; diff --git a/src/Umbraco.Core/Strings/PathUtility.cs b/src/Umbraco.Core/Strings/PathUtility.cs index cab7127a6ef9..466015e72061 100644 --- a/src/Umbraco.Core/Strings/PathUtility.cs +++ b/src/Umbraco.Core/Strings/PathUtility.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Strings; +/// +/// Provides utility methods for working with file and URL paths. +/// public static class PathUtility { /// diff --git a/src/Umbraco.Core/Strings/UrlSegmentProviderCollection.cs b/src/Umbraco.Core/Strings/UrlSegmentProviderCollection.cs index 39b826dae98d..5096e0f53faa 100644 --- a/src/Umbraco.Core/Strings/UrlSegmentProviderCollection.cs +++ b/src/Umbraco.Core/Strings/UrlSegmentProviderCollection.cs @@ -2,8 +2,19 @@ namespace Umbraco.Cms.Core.Strings; +/// +/// Represents a collection of instances. +/// +/// +/// This collection is built by and provides +/// URL segment providers in priority order. +/// public class UrlSegmentProviderCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection of URL segment providers. public UrlSegmentProviderCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs b/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs index f9aa13b335da..77409f715ce0 100644 --- a/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs +++ b/src/Umbraco.Core/Strings/UrlSegmentProviderCollectionBuilder.cs @@ -1,8 +1,15 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.Strings; +/// +/// Builds a collection of instances. +/// +/// +/// URL segment providers are ordered and determine how content URLs are generated. +/// public class UrlSegmentProviderCollectionBuilder : OrderedCollectionBuilderBase { + /// protected override UrlSegmentProviderCollectionBuilder This => this; } diff --git a/src/Umbraco.Core/Sync/LastSyncedManager.cs b/src/Umbraco.Core/Sync/LastSyncedManager.cs index 64b0019c6fcf..ec421fbd5c8b 100644 --- a/src/Umbraco.Core/Sync/LastSyncedManager.cs +++ b/src/Umbraco.Core/Sync/LastSyncedManager.cs @@ -1,10 +1,12 @@ -using System.ComponentModel; +using System.ComponentModel; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; namespace Umbraco.Cms.Core.Sync; -/// +/// +/// Default implementation of that manages last synced IDs with caching. +/// internal sealed class LastSyncedManager : ILastSyncedManager { private readonly ILastSyncedRepository _lastSyncedRepository; @@ -12,6 +14,11 @@ internal sealed class LastSyncedManager : ILastSyncedManager private int? _lastSyncedInternalId; private int? _lastSyncedExternalId; + /// + /// Initializes a new instance of the class. + /// + /// The repository for persisting last synced data. + /// The scope provider for database transactions. public LastSyncedManager(ILastSyncedRepository lastSyncedRepository, ICoreScopeProvider coreScopeProvider) { _lastSyncedRepository = lastSyncedRepository; @@ -84,7 +91,12 @@ public async Task DeleteOlderThanAsync(DateTime date) scope.Complete(); } - // Used for testing purposes only + /// + /// Clears the local cache of last synced IDs. + /// + /// + /// This method is intended for testing purposes only. + /// [EditorBrowsable(EditorBrowsableState.Never)] internal void ClearLocalCache() { diff --git a/src/Umbraco.Core/Sync/MessageType.cs b/src/Umbraco.Core/Sync/MessageType.cs index 282aebeb54b3..469c2ea55285 100644 --- a/src/Umbraco.Core/Sync/MessageType.cs +++ b/src/Umbraco.Core/Sync/MessageType.cs @@ -1,15 +1,42 @@ namespace Umbraco.Cms.Core.Sync; /// -/// The message type to be used for syncing across servers. +/// The message type to be used for syncing across servers. /// public enum MessageType { + /// + /// Refresh all items of a specific cache type. + /// RefreshAll, + + /// + /// Refresh specific items by their identifiers. + /// RefreshById, + + /// + /// Refresh items using JSON payload data. + /// RefreshByJson, + + /// + /// Remove specific items by their identifiers. + /// RemoveById, + + /// + /// Refresh items by their object instances (local only, cannot be distributed). + /// RefreshByInstance, + + /// + /// Remove items by their object instances (local only, cannot be distributed). + /// RemoveByInstance, + + /// + /// Refresh items using a typed payload. + /// RefreshByPayload, } diff --git a/src/Umbraco.Core/Sync/NonRuntimeLevelBootStateAccessor.cs b/src/Umbraco.Core/Sync/NonRuntimeLevelBootStateAccessor.cs index 4040edd8f723..5899621ca18e 100644 --- a/src/Umbraco.Core/Sync/NonRuntimeLevelBootStateAccessor.cs +++ b/src/Umbraco.Core/Sync/NonRuntimeLevelBootStateAccessor.cs @@ -1,9 +1,14 @@ namespace Umbraco.Cms.Core.Sync; /// -/// Boot state implementation for when umbraco is not in the run state +/// Boot state implementation for when Umbraco is not in the run state. /// +/// +/// This accessor always returns because +/// synchronization is not applicable when the application is not fully running. +/// public sealed class NonRuntimeLevelBootStateAccessor : ISyncBootStateAccessor { + /// public SyncBootState GetSyncBootState() => SyncBootState.Unknown; } diff --git a/src/Umbraco.Core/Sync/RefreshInstruction.cs b/src/Umbraco.Core/Sync/RefreshInstruction.cs index 5060e8854a17..1fc7316f53b7 100644 --- a/src/Umbraco.Core/Sync/RefreshInstruction.cs +++ b/src/Umbraco.Core/Sync/RefreshInstruction.cs @@ -4,6 +4,12 @@ namespace Umbraco.Cms.Core.Sync; +/// +/// Represents an instruction to refresh or remove items in a distributed cache. +/// +/// +/// This class is serializable and used for distributed cache synchronization across servers. +/// [Serializable] [DataContract] public class RefreshInstruction @@ -129,8 +135,26 @@ private RefreshInstruction(ICacheRefresher refresher, RefreshMethodType refreshT [DataMember] public string? JsonPayload { get; set; } + /// + /// Determines whether two instances are equal. + /// + /// The first instruction to compare. + /// The second instruction to compare. + /// true if the instructions are equal; otherwise, false. public static bool operator ==(RefreshInstruction left, RefreshInstruction right) => Equals(left, right); + /// + /// Creates refresh instructions based on the specified message type and parameters. + /// + /// The cache refresher that will handle the instruction. + /// The JSON serializer for serializing IDs. + /// The type of refresh message. + /// The collection of IDs to refresh or remove. + /// The type of the IDs (int or Guid). + /// Optional JSON payload data. + /// A collection of refresh instructions. + /// Thrown when idType is null for ID-based operations. + /// Thrown when messageType is not supported. public static IEnumerable GetInstructions( ICacheRefresher refresher, IJsonSerializer jsonSerializer, @@ -185,6 +209,7 @@ public static IEnumerable GetInstructions( } } + /// public override bool Equals(object? other) { if (other is null) @@ -205,6 +230,11 @@ public override bool Equals(object? other) return Equals((RefreshInstruction)other); } + /// + /// Determines whether the specified is equal to this instance. + /// + /// The instruction to compare with this instance. + /// true if the instructions are equal; otherwise, false. protected bool Equals(RefreshInstruction other) => RefreshType == other.RefreshType && RefresherId.Equals(other.RefresherId) @@ -213,6 +243,7 @@ protected bool Equals(RefreshInstruction other) => && string.Equals(JsonIds, other.JsonIds) && string.Equals(JsonPayload, other.JsonPayload); + /// public override int GetHashCode() { unchecked @@ -227,5 +258,11 @@ public override int GetHashCode() } } + /// + /// Determines whether two instances are not equal. + /// + /// The first instruction to compare. + /// The second instruction to compare. + /// true if the instructions are not equal; otherwise, false. public static bool operator !=(RefreshInstruction left, RefreshInstruction right) => Equals(left, right) == false; } diff --git a/src/Umbraco.Core/Sync/RefreshMethodType.cs b/src/Umbraco.Core/Sync/RefreshMethodType.cs index 11de3a627ff8..5e0a91cdc250 100644 --- a/src/Umbraco.Core/Sync/RefreshMethodType.cs +++ b/src/Umbraco.Core/Sync/RefreshMethodType.cs @@ -1,40 +1,44 @@ namespace Umbraco.Cms.Core.Sync; /// -/// Describes refresh action type. +/// Describes refresh action type. /// +/// +/// +/// This enum is exposed in CacheRefresher web service through , +/// so it is kept as-is for backward compatibility reasons. +/// +/// [Serializable] public enum RefreshMethodType { - // NOTE - // that enum should get merged somehow with MessageType and renamed somehow - // but at the moment it is exposed in CacheRefresher webservice through RefreshInstruction - // so for the time being we keep it as-is for backward compatibility reasons + /// + /// Refresh all cached items of the specified type. + /// RefreshAll = 0, + + /// + /// Refresh a single item by its GUID identifier. + /// RefreshByGuid = 1, + + /// + /// Refresh a single item by its integer identifier. + /// RefreshById = 2, - RefreshByIds = 3, - RefreshByJson = 4, - RemoveById = 5, - // would adding values break backward compatibility? - // RemoveByIds + /// + /// Refresh multiple items by their integer identifiers. + /// + RefreshByIds = 3, - // these are MessageType values - // note that AnythingByInstance are local messages and cannot be distributed - /* - RefreshAll, - RefreshById, - RefreshByJson, - RemoveById, - RefreshByInstance, - RemoveByInstance - */ + /// + /// Refresh items using JSON payload data. + /// + RefreshByJson = 4, - // NOTE - // in the future we want - // RefreshAll - // RefreshById / ByInstance (support enumeration of int or guid) - // RemoveById / ByInstance (support enumeration of int or guid) - // Notify (for everything JSON) + /// + /// Remove an item by its integer identifier. + /// + RemoveById = 5, } diff --git a/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs b/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs index f03f27d9e7bc..fdbc7ce469d4 100644 --- a/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs +++ b/src/Umbraco.Core/Sync/SingleServerRoleAccessor.cs @@ -1,17 +1,22 @@ namespace Umbraco.Cms.Core.Sync; /// -/// Can be used when Umbraco is definitely not operating in a Load Balanced scenario to micro-optimize some startup -/// performance +/// Provides server role access for single-server deployments. /// /// -/// The micro optimization is specifically to avoid a DB query just after the app starts up to determine the -/// -/// which by default is done with scheduling publisher election by a database query. The master election process -/// doesn't occur until just after startup -/// so this micro optimization doesn't really affect the primary startup phase. +/// +/// Can be used when Umbraco is definitely not operating in a load balanced scenario +/// to micro-optimize some startup performance. +/// +/// +/// The micro optimization is specifically to avoid a DB query just after the app starts up +/// to determine the , which by default is done with scheduling +/// publisher election by a database query. The master election process doesn't occur until +/// just after startup so this micro optimization doesn't really affect the primary startup phase. +/// /// public class SingleServerRoleAccessor : IServerRoleAccessor { + /// public ServerRole CurrentServerRole => ServerRole.Single; } diff --git a/src/Umbraco.Core/Sync/SyncBootState.cs b/src/Umbraco.Core/Sync/SyncBootState.cs index 6233ace01ae2..a995714cc662 100644 --- a/src/Umbraco.Core/Sync/SyncBootState.cs +++ b/src/Umbraco.Core/Sync/SyncBootState.cs @@ -1,19 +1,26 @@ namespace Umbraco.Cms.Core.Sync; +/// +/// Represents the synchronization boot state of the application. +/// +/// +/// The boot state indicates whether the application has previous sync state +/// available, which affects how cache synchronization is performed during startup. +/// public enum SyncBootState { /// - /// Unknown state. Treat as WarmBoot + /// Unknown state. Treat as WarmBoot. /// Unknown = 0, /// - /// Cold boot. No Sync state + /// Cold boot. No sync state is present; full cache rebuild may be required. /// ColdBoot = 1, /// - /// Warm boot. Sync state present + /// Warm boot. Sync state is present; incremental cache updates can be applied. /// WarmBoot = 2, } diff --git a/src/Umbraco.Core/SystemLock.cs b/src/Umbraco.Core/SystemLock.cs index 75ca72e27cd1..72bc4f78db10 100644 --- a/src/Umbraco.Core/SystemLock.cs +++ b/src/Umbraco.Core/SystemLock.cs @@ -1,22 +1,28 @@ -using System.Runtime.ConstrainedExecution; +using System.Runtime.ConstrainedExecution; namespace Umbraco.Cms.Core; -// https://devblogs.microsoft.com/pfxteam/building-async-coordination-primitives-part-6-asynclock/ -// -// notes: -// - this is NOT a reader/writer lock -// - this is NOT a recursive lock -// -// using a named Semaphore here and not a Mutex because mutexes have thread -// affinity which does not work with async situations -// -// it is important that managed code properly release the Semaphore before -// going down else it will maintain the lock - however note that when the -// whole process (w3wp.exe) goes down and all handles to the Semaphore have -// been closed, the Semaphore system object is destroyed - so in any case -// an iisreset should clean up everything -// +/// +/// Provides a synchronization lock that can be either local (anonymous) or system-wide (named). +/// +/// +/// +/// This is NOT a reader/writer lock and is NOT a recursive lock. +/// +/// +/// Uses a named Semaphore instead of a Mutex because mutexes have thread affinity +/// which does not work with async situations. +/// +/// +/// It is important that managed code properly releases the Semaphore before going down, +/// otherwise it will maintain the lock. However, when the whole process (w3wp.exe) goes +/// down and all handles to the Semaphore have been closed, the Semaphore system object +/// is destroyed - so an iisreset should clean up everything. +/// +/// +/// See https://devblogs.microsoft.com/pfxteam/building-async-coordination-primitives-part-6-asynclock/ +/// +/// public class SystemLock { private readonly IDisposable? _releaser; @@ -24,11 +30,18 @@ public class SystemLock private readonly SemaphoreSlim? _semaphore; private readonly Semaphore? _semaphore2; + /// + /// Initializes a new instance of the class with an anonymous (local) semaphore. + /// public SystemLock() : this(null) { } + /// + /// Initializes a new instance of the class. + /// + /// The name of the system-wide semaphore, or null for an anonymous local semaphore. public SystemLock(string? name) { // WaitOne() waits until count > 0 then decrements count @@ -53,6 +66,10 @@ public SystemLock(string? name) } } + /// + /// Acquires the lock, blocking until the lock is available. + /// + /// An that releases the lock when disposed. public IDisposable? Lock() { if (_semaphore != null) @@ -74,6 +91,12 @@ public SystemLock(string? name) ? _releaser // (IDisposable)new SemaphoreSlimReleaser(_semaphore) : new NamedSemaphoreReleaser(_semaphore2); + /// + /// Acquires the lock, blocking until the lock is available or the timeout expires. + /// + /// The maximum time in milliseconds to wait for the lock. + /// An that releases the lock when disposed. + /// The lock could not be acquired within the timeout period. public IDisposable? Lock(int millisecondsTimeout) { var entered = _semaphore != null diff --git a/src/Umbraco.Core/Telemetry/Models/TelemetryReportData.cs b/src/Umbraco.Core/Telemetry/Models/TelemetryReportData.cs index 31bab02f1c95..29d0af3a1861 100644 --- a/src/Umbraco.Core/Telemetry/Models/TelemetryReportData.cs +++ b/src/Umbraco.Core/Telemetry/Models/TelemetryReportData.cs @@ -30,6 +30,9 @@ public class TelemetryReportData [DataMember(Name = "packages")] public IEnumerable? Packages { get; set; } + /// + /// Gets or sets detailed telemetry usage information. + /// [DataMember(Name = "detailed")] public IEnumerable? Detailed { get; set; } } diff --git a/src/Umbraco.Core/Telemetry/SiteIdentifierService.cs b/src/Umbraco.Core/Telemetry/SiteIdentifierService.cs index 0d2d3a3c8db3..4ec1ac17eaaa 100644 --- a/src/Umbraco.Core/Telemetry/SiteIdentifierService.cs +++ b/src/Umbraco.Core/Telemetry/SiteIdentifierService.cs @@ -12,6 +12,12 @@ internal sealed class SiteIdentifierService : ISiteIdentifierService private readonly ILogger _logger; private GlobalSettings _globalSettings; + /// + /// Initializes a new instance of the class. + /// + /// The options monitor for global settings. + /// The configuration manipulator. + /// The logger. public SiteIdentifierService( IOptionsMonitor optionsMonitor, IConfigManipulator configManipulator, diff --git a/src/Umbraco.Core/Templates/HtmlImageSourceParser.cs b/src/Umbraco.Core/Templates/HtmlImageSourceParser.cs index 83098ed5ab58..e663206a5297 100644 --- a/src/Umbraco.Core/Templates/HtmlImageSourceParser.cs +++ b/src/Umbraco.Core/Templates/HtmlImageSourceParser.cs @@ -1,9 +1,12 @@ -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; using Umbraco.Cms.Core.Routing; using Umbraco.Extensions; namespace Umbraco.Cms.Core.Templates; +/// +/// Utility class used to parse and update image sources in HTML content based on Umbraco media references. +/// public sealed class HtmlImageSourceParser { private static readonly Regex ResolveImgPattern = new( @@ -22,8 +25,16 @@ public sealed class HtmlImageSourceParser private Func? _getMediaUrl; + /// + /// Initializes a new instance of the class. + /// + /// A function that retrieves the media URL for a given GUID. public HtmlImageSourceParser(Func getMediaUrl) => _getMediaUrl = getMediaUrl; + /// + /// Initializes a new instance of the class. + /// + /// The published URL provider for resolving media URLs. public HtmlImageSourceParser(IPublishedUrlProvider publishedUrlProvider) => _publishedUrlProvider = publishedUrlProvider; diff --git a/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs b/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs index 5b53a472749f..afe3f2e133a0 100644 --- a/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs +++ b/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs @@ -10,28 +10,50 @@ namespace Umbraco.Cms.Core.Templates; /// public sealed class HtmlLocalLinkParser { - // needs to support media and document links, order of attributes should not matter nor should other attributes mess with things - // media - // other page + /// + /// Regex pattern to match local link tags with type and href attributes. + /// + /// + /// Needs to support media and document links. Order of attributes should not matter + /// nor should other attributes mess with things. + /// Examples: + /// <a type="media" href="/{localLink:7e21a725-b905-4c5f-86dc-8c41ec116e39}" title="media">media</a> + /// <a type="document" href="/{localLink:eed5fc6b-96fd-45a5-a0f1-b1adfb483c2f}" title="other page">other page</a> + /// internal static readonly Regex LocalLinkTagPattern = new( @"\/?{localLink:(?[a-fA-F0-9-]+)})[^>]*?>", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled); + /// + /// Regex pattern to match the type attribute (media or document) in local link tags. + /// internal static readonly Regex TypePattern = new( """type=['"](?(?:media|document))['"]""", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled); + /// + /// Regex pattern to match legacy local link href patterns. + /// internal static readonly Regex LocalLinkPattern = new( @"href=['""](?\/?(?:\{|\%7B)localLink:(?[a-zA-Z0-9-://]+)(?:\}|\%7D))", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled); private readonly IPublishedUrlProvider _publishedUrlProvider; + /// + /// Initializes a new instance of the class. + /// + /// The published URL provider for resolving content and media URLs. public HtmlLocalLinkParser(IPublishedUrlProvider publishedUrlProvider) { _publishedUrlProvider = publishedUrlProvider; } + /// + /// Finds all UDIs from local link references in the specified text. + /// + /// The text to search for local links. + /// An enumerable of objects found in the text. public IEnumerable FindUdisFromLocalLinks(string text) { foreach (LocalLinkTag tagData in FindLocalLinkIds(text)) @@ -119,6 +141,11 @@ private IEnumerable FindLocalLinkIds(string text) } } + /// + /// Finds legacy local link identifiers in the specified text. + /// + /// The text to search for legacy local links. + /// An enumerable of objects representing legacy links. [Obsolete("This is a temporary method to support legacy formats until we are sure all data has been migration. Scheduled for removal in v18")] public IEnumerable FindLegacyLocalLinkIds(string text) { @@ -149,9 +176,18 @@ public IEnumerable FindLegacyLocalLinkIds(string text) } } + /// + /// Represents a local link tag extracted from HTML content. + /// [Obsolete("This is a temporary method to support legacy formats until we are sure all data has been migration. Scheduled for removal in v18")] public class LocalLinkTag { + /// + /// Initializes a new instance of the class. + /// + /// The integer identifier for legacy links. + /// The for the linked content or media. + /// The original href value from the tag. public LocalLinkTag(int? intId, GuidUdi? udi, string tagHref) { IntId = intId; @@ -159,10 +195,19 @@ public LocalLinkTag(int? intId, GuidUdi? udi, string tagHref) TagHref = tagHref; } + /// + /// Gets the integer identifier for legacy local links. + /// public int? IntId { get; } + /// + /// Gets the for the linked content or media. + /// public GuidUdi? Udi { get; } + /// + /// Gets the original href value from the local link tag. + /// public string TagHref { get; } } } diff --git a/src/Umbraco.Core/Templates/HtmlUrlParser.cs b/src/Umbraco.Core/Templates/HtmlUrlParser.cs index 80dc47a27c87..ec0d8dcad838 100644 --- a/src/Umbraco.Core/Templates/HtmlUrlParser.cs +++ b/src/Umbraco.Core/Templates/HtmlUrlParser.cs @@ -7,6 +7,9 @@ namespace Umbraco.Cms.Core.Templates; +/// +/// Utility class used to parse and resolve relative URLs in HTML content. +/// public sealed class HtmlUrlParser { private static readonly Regex _resolveUrlPattern = new( @@ -18,6 +21,13 @@ public sealed class HtmlUrlParser private readonly IProfilingLogger _profilingLogger; private ContentSettings _contentSettings; + /// + /// Initializes a new instance of the class. + /// + /// The content settings options monitor. + /// The logger instance. + /// The profiling logger instance. + /// The IO helper for resolving URLs. public HtmlUrlParser(IOptionsMonitor contentSettings, ILogger logger, IProfilingLogger profilingLogger, IIOHelper ioHelper) { _contentSettings = contentSettings.CurrentValue; diff --git a/src/Umbraco.Core/Templates/ITemplateRenderer.cs b/src/Umbraco.Core/Templates/ITemplateRenderer.cs index 17d16168ec99..05da07cdac3a 100644 --- a/src/Umbraco.Core/Templates/ITemplateRenderer.cs +++ b/src/Umbraco.Core/Templates/ITemplateRenderer.cs @@ -5,5 +5,12 @@ namespace Umbraco.Cms.Core.Templates; /// public interface ITemplateRenderer { + /// + /// Renders a template for the specified page asynchronously. + /// + /// The identifier of the page to render. + /// An optional alternative template identifier. If not specified, uses the template assigned to the page. + /// The to write the rendered output to. + /// A task that represents the asynchronous render operation. Task RenderAsync(int pageId, int? altTemplateId, StringWriter writer); } diff --git a/src/Umbraco.Core/Udi.cs b/src/Umbraco.Core/Udi.cs index bc6c1ab6ac34..152bfcb8ce33 100644 --- a/src/Umbraco.Core/Udi.cs +++ b/src/Umbraco.Core/Udi.cs @@ -30,6 +30,9 @@ protected Udi(Uri uriValue) UriValue = uriValue; } + /// + /// Gets the URI representation of this Udi. + /// public Uri UriValue { get; } /// @@ -43,6 +46,12 @@ protected Udi(Uri uriValue) /// A root Udi points to the "root of all things" for a given entity type, e.g. the content tree root. public abstract bool IsRoot { get; } + /// + /// Determines whether two Udi instances are equal. + /// + /// The first Udi to compare. + /// The second Udi to compare. + /// true if the instances are equal; otherwise, false. public static bool operator ==(Udi? udi1, Udi? udi2) { if (ReferenceEquals(udi1, udi2)) @@ -65,8 +74,10 @@ protected Udi(Uri uriValue) /// The root Udi for the entity type. public static Udi Create(string entityType) => UdiParser.GetRootUdi(entityType); + /// public int CompareTo(Udi? other) => string.Compare(UriValue.ToString(), other?.UriValue.ToString(), StringComparison.OrdinalIgnoreCase); + /// public override string ToString() => // UriValue is created in the ctor and is never null @@ -129,6 +140,12 @@ public static Udi Create(string? entityType, Guid id) return new GuidUdi(entityType, id); } + /// + /// Creates a Udi from a URI. + /// + /// The URI to create the Udi from. + /// The Udi for the specified URI. + /// The URI is not a valid Udi or the entity type is unknown. public static Udi Create(Uri uri) { // if it's a know type go fast and use ctors @@ -151,6 +168,11 @@ public static Udi Create(Uri uri) throw new ArgumentException(string.Format("Uri \"{0}\" is not a valid udi.", uri)); } + /// + /// Ensures that this Udi is of one of the specified entity types. + /// + /// The valid entity types. + /// When the entity type is not one of the valid types. public void EnsureType(params string[] validTypes) { if (validTypes.Contains(EntityType) == false) @@ -174,13 +196,21 @@ public Udi EnsureNotRoot() return this; } + /// public override bool Equals(object? obj) { var other = obj as Udi; return other is not null && GetType() == other.GetType() && UriValue == other.UriValue; } + /// public override int GetHashCode() => UriValue.GetHashCode(); + /// + /// Determines whether two Udi instances are not equal. + /// + /// The first Udi to compare. + /// The second Udi to compare. + /// true if the instances are not equal; otherwise, false. public static bool operator !=(Udi? udi1, Udi? udi2) => udi1 == udi2 == false; } diff --git a/src/Umbraco.Core/UdiDefinitionAttribute.cs b/src/Umbraco.Core/UdiDefinitionAttribute.cs index fe96909f78b5..642d018ac7a0 100644 --- a/src/Umbraco.Core/UdiDefinitionAttribute.cs +++ b/src/Umbraco.Core/UdiDefinitionAttribute.cs @@ -1,8 +1,21 @@ namespace Umbraco.Cms.Core; +/// +/// Attribute used to define a UDI (Umbraco Document Identifier) type for an entity. +/// +/// +/// This attribute can be applied multiple times to a class to define multiple UDI types. +/// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] public sealed class UdiDefinitionAttribute : Attribute { + /// + /// Initializes a new instance of the class. + /// + /// The entity type for the UDI. + /// The type of UDI (GUID or String). + /// The entity type is null or whitespace. + /// The UDI type is not valid. public UdiDefinitionAttribute(string entityType, UdiType udiType) { if (string.IsNullOrWhiteSpace(entityType)) @@ -19,7 +32,13 @@ public UdiDefinitionAttribute(string entityType, UdiType udiType) UdiType = udiType; } + /// + /// Gets the entity type for this UDI definition. + /// public string EntityType { get; } + /// + /// Gets the type of UDI (GUID or String) for this definition. + /// public UdiType UdiType { get; } } diff --git a/src/Umbraco.Core/UdiEntityTypeHelper.cs b/src/Umbraco.Core/UdiEntityTypeHelper.cs index 40d5b8dd5990..6ac07963918d 100644 --- a/src/Umbraco.Core/UdiEntityTypeHelper.cs +++ b/src/Umbraco.Core/UdiEntityTypeHelper.cs @@ -2,8 +2,17 @@ namespace Umbraco.Cms.Core; +/// +/// Provides helper methods for converting between UDI entity types and Umbraco object types. +/// public static class UdiEntityTypeHelper { + /// + /// Converts an value to its corresponding UDI entity type string. + /// + /// The Umbraco object type to convert. + /// The UDI entity type string. + /// The Umbraco object type does not have a matching entity type. public static string FromUmbracoObjectType(UmbracoObjectTypes umbracoObjectType) { switch (umbracoObjectType) @@ -52,6 +61,12 @@ public static string FromUmbracoObjectType(UmbracoObjectTypes umbracoObjectType) $"UmbracoObjectType \"{umbracoObjectType}\" does not have a matching EntityType."); } + /// + /// Converts a UDI entity type string to its corresponding value. + /// + /// The UDI entity type string to convert. + /// The corresponding value. + /// The entity type does not have a matching Umbraco object type. public static UmbracoObjectTypes ToUmbracoObjectType(string entityType) { switch (entityType) diff --git a/src/Umbraco.Core/UdiParser.cs b/src/Umbraco.Core/UdiParser.cs index c7169046b01d..86c81ea4a622 100644 --- a/src/Umbraco.Core/UdiParser.cs +++ b/src/Umbraco.Core/UdiParser.cs @@ -4,6 +4,9 @@ namespace Umbraco.Cms.Core; +/// +/// Provides methods for parsing and managing UDI (Umbraco Document Identifier) strings. +/// public sealed class UdiParser { private static readonly ConcurrentDictionary RootUdis = new(); @@ -14,6 +17,9 @@ static UdiParser() => // we will add scanned types later on UdiTypes = new ConcurrentDictionary(GetKnownUdiTypes()); + /// + /// Gets the dictionary of registered UDI types and their corresponding entity types. + /// internal static ConcurrentDictionary UdiTypes { get; private set; } /// @@ -112,6 +118,12 @@ public static bool TryParse(string? s, bool knownTypes, [MaybeNullWhen(false)] o /// public static void RegisterUdiType(string entityType, UdiType udiType) => UdiTypes.TryAdd(entityType, udiType); + /// + /// Gets the root UDI for a specified entity type. + /// + /// The entity type. + /// A root UDI for the entity type. + /// Thrown when the entity type is unknown. internal static Udi GetRootUdi(string entityType) => RootUdis.GetOrAdd(entityType, x => { @@ -196,6 +208,10 @@ private static bool ParseInternal(string? s, bool tryParse, bool knownTypes, [Ma throw new InvalidOperationException(string.Format("Invalid udi type \"{0}\".", udiType)); } + /// + /// Gets a dictionary of all known UDI types and their entity type mappings. + /// + /// A dictionary mapping entity type strings to values. public static Dictionary GetKnownUdiTypes() => new() { diff --git a/src/Umbraco.Core/UdiRange.cs b/src/Umbraco.Core/UdiRange.cs index b91b811b062a..787c885b1aeb 100644 --- a/src/Umbraco.Core/UdiRange.cs +++ b/src/Umbraco.Core/UdiRange.cs @@ -58,6 +58,12 @@ public UdiRange(Udi udi, string selector = Constants.DeploySelector.This) /// public string EntityType => Udi.EntityType; + /// + /// Determines whether two instances are equal. + /// + /// The first range to compare. + /// The second range to compare. + /// true if the ranges are equal; otherwise, false. public static bool operator ==(UdiRange? range1, UdiRange? range2) { if (ReferenceEquals(range1, range2)) @@ -73,8 +79,20 @@ public UdiRange(Udi udi, string selector = Constants.DeploySelector.This) return range1.Equals(range2); } + /// + /// Determines whether two instances are not equal. + /// + /// The first range to compare. + /// The second range to compare. + /// true if the ranges are not equal; otherwise, false. public static bool operator !=(UdiRange range1, UdiRange range2) => !(range1 == range2); + /// + /// Parses a string representation of a UDI range. + /// + /// The string to parse. + /// A instance. + /// Thrown when the string is not a valid UDI range. public static UdiRange Parse(string value) { if (Uri.TryCreate(value, UriKind.Absolute, out Uri? uri) is false || @@ -96,10 +114,13 @@ public static UdiRange Parse(string value) : new UdiRange(udi, uri.Query.TrimStart(Constants.CharArrays.QuestionMark)); } + /// public override string ToString() => _uriValue.ToString(); + /// public override bool Equals(object? obj) => obj is UdiRange other && GetType() == other.GetType() && _uriValue == other._uriValue; + /// public override int GetHashCode() => _uriValue.GetHashCode(); } diff --git a/src/Umbraco.Core/UdiTypeConverter.cs b/src/Umbraco.Core/UdiTypeConverter.cs index c058ce2a70b0..152e62bc216c 100644 --- a/src/Umbraco.Core/UdiTypeConverter.cs +++ b/src/Umbraco.Core/UdiTypeConverter.cs @@ -11,6 +11,7 @@ namespace Umbraco.Cms.Core; /// internal sealed class UdiTypeConverter : TypeConverter { + /// public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) { if (sourceType == typeof(string)) @@ -21,6 +22,7 @@ public override bool CanConvertFrom(ITypeDescriptorContext? context, Type source return base.CanConvertFrom(context, sourceType); } + /// public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) { if (value is string) diff --git a/src/Umbraco.Core/UmbracoApiControllerTypeCollection.cs b/src/Umbraco.Core/UmbracoApiControllerTypeCollection.cs index 747a5553e112..8333305e3285 100644 --- a/src/Umbraco.Core/UmbracoApiControllerTypeCollection.cs +++ b/src/Umbraco.Core/UmbracoApiControllerTypeCollection.cs @@ -2,9 +2,16 @@ namespace Umbraco.Cms.Core; +/// +/// A collection of types representing Umbraco API controllers. +/// [Obsolete("This will be removed in Umbraco 15.")] public class UmbracoApiControllerTypeCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A function that provides the collection of API controller types. public UmbracoApiControllerTypeCollection(Func> items) : base(items) { diff --git a/src/Umbraco.Core/UmbracoContextReference.cs b/src/Umbraco.Core/UmbracoContextReference.cs index d17012e0f98c..52424f621f5d 100644 --- a/src/Umbraco.Core/UmbracoContextReference.cs +++ b/src/Umbraco.Core/UmbracoContextReference.cs @@ -40,8 +40,13 @@ public UmbracoContextReference(IUmbracoContext umbracoContext, bool isRoot, IUmb /// public bool IsRoot { get; } + /// public void Dispose() => Dispose(true); + /// + /// Releases the unmanaged resources used by the and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (!_disposedValue) diff --git a/src/Umbraco.Core/UnknownTypeUdi.cs b/src/Umbraco.Core/UnknownTypeUdi.cs index 3c38418f0e84..f63dc90d5811 100644 --- a/src/Umbraco.Core/UnknownTypeUdi.cs +++ b/src/Umbraco.Core/UnknownTypeUdi.cs @@ -1,13 +1,26 @@ namespace Umbraco.Cms.Core; +/// +/// Represents a UDI with an unknown entity type. +/// +/// +/// This class is used when parsing UDIs with unknown entity types when using the knownTypes parameter. +/// public class UnknownTypeUdi : Udi { + /// + /// Gets the singleton instance of the class. + /// public static readonly UnknownTypeUdi Instance = new(); + /// + /// Initializes a new instance of the class. + /// private UnknownTypeUdi() : base("unknown", "umb://unknown/") { } + /// public override bool IsRoot => false; } diff --git a/src/Umbraco.Core/UpgradeResult.cs b/src/Umbraco.Core/UpgradeResult.cs index 7f27e503fe42..46bb802d9a87 100644 --- a/src/Umbraco.Core/UpgradeResult.cs +++ b/src/Umbraco.Core/UpgradeResult.cs @@ -1,7 +1,16 @@ namespace Umbraco.Cms.Core; +/// +/// Represents the result of an upgrade check operation. +/// public class UpgradeResult { + /// + /// Initializes a new instance of the class. + /// + /// The type of upgrade available. + /// A comment or description about the upgrade. + /// The URL where the upgrade can be obtained. public UpgradeResult(string upgradeType, string comment, string upgradeUrl) { UpgradeType = upgradeType; @@ -9,9 +18,18 @@ public UpgradeResult(string upgradeType, string comment, string upgradeUrl) UpgradeUrl = upgradeUrl; } + /// + /// Gets the type of upgrade available (e.g., major, minor, patch). + /// public string UpgradeType { get; } + /// + /// Gets a comment or description about the upgrade. + /// public string Comment { get; } + /// + /// Gets the URL where the upgrade can be obtained or more information is available. + /// public string UpgradeUrl { get; } } diff --git a/src/Umbraco.Core/UriUtilityCore.cs b/src/Umbraco.Core/UriUtilityCore.cs index cefeed5e6ff6..7051b7057873 100644 --- a/src/Umbraco.Core/UriUtilityCore.cs +++ b/src/Umbraco.Core/UriUtilityCore.cs @@ -2,15 +2,39 @@ namespace Umbraco.Cms.Core; +/// +/// Provides utility methods for working with URIs. +/// public static class UriUtilityCore { + /// + /// Determines whether the specified URI string contains a scheme (e.g., "http://"). + /// + /// The URI string to check. + /// true if the URI has a scheme; otherwise, false. public static bool HasScheme(string uri) => uri.IndexOf("://", StringComparison.Ordinal) > 0; + /// + /// Ensures the URI string starts with a scheme, using HTTP as the default. + /// + /// The URI string. + /// The URI string with a scheme prefix. public static string StartWithScheme(string uri) => StartWithScheme(uri, null); + /// + /// Ensures the URI string starts with the specified scheme. + /// + /// The URI string. + /// The scheme to use, or null to use HTTP. + /// The URI string with a scheme prefix. public static string StartWithScheme(string uri, string? scheme) => HasScheme(uri) ? uri : string.Format("{0}://{1}", scheme ?? Uri.UriSchemeHttp, uri); + /// + /// Ensures the path portion of the URI ends with a slash. + /// + /// The URI string. + /// The URI string with the path ending in a slash. public static string EndPathWithSlash(string uri) { ReadOnlySpan uriSpan = uri.AsSpan(); @@ -27,6 +51,11 @@ public static string EndPathWithSlash(string uri) return path; } + /// + /// Removes the trailing slash from the path portion of the URI. + /// + /// The URI string. + /// The URI string with the trailing slash removed from the path. public static string TrimPathEndSlash(string uri) { ReadOnlySpan uriSpan = uri.AsSpan(); diff --git a/src/Umbraco.Core/Web/CookieManagerExtensions.cs b/src/Umbraco.Core/Web/CookieManagerExtensions.cs index 2e399ac8c1f9..dd0bb5db1c95 100644 --- a/src/Umbraco.Core/Web/CookieManagerExtensions.cs +++ b/src/Umbraco.Core/Web/CookieManagerExtensions.cs @@ -6,8 +6,16 @@ namespace Umbraco.Extensions; +/// +/// Extension methods for . +/// public static class CookieManagerExtensions { + /// + /// Gets the value of the preview cookie. + /// + /// The cookie manager. + /// The preview cookie value if found; otherwise, null. public static string? GetPreviewCookieValue(this ICookieManager cookieManager) => cookieManager.GetCookieValue(Constants.Web.PreviewCookieName); } diff --git a/src/Umbraco.Core/Web/IRequestAccessor.cs b/src/Umbraco.Core/Web/IRequestAccessor.cs index 57940b3c1b23..57872e61e229 100644 --- a/src/Umbraco.Core/Web/IRequestAccessor.cs +++ b/src/Umbraco.Core/Web/IRequestAccessor.cs @@ -1,19 +1,27 @@ namespace Umbraco.Cms.Core.Web; +/// +/// Provides access to HTTP request values. +/// public interface IRequestAccessor { /// - /// Returns the request/form/querystring value for the given name + /// Gets the request value for the specified name from request, form, or query string. /// + /// The name of the value to retrieve. + /// The request value if found; otherwise, null. string? GetRequestValue(string name); /// - /// Returns the query string value for the given name + /// Gets the query string value for the specified name. /// + /// The name of the query string parameter. + /// The query string value if found; otherwise, null. string? GetQueryStringValue(string name); /// - /// Returns the current request uri + /// Gets the current request URL. /// + /// The current request if available; otherwise, null. Uri? GetRequestUrl(); } diff --git a/src/Umbraco.Core/Web/ISessionManager.cs b/src/Umbraco.Core/Web/ISessionManager.cs index a37bebcfa780..9ab31122a4a9 100644 --- a/src/Umbraco.Core/Web/ISessionManager.cs +++ b/src/Umbraco.Core/Web/ISessionManager.cs @@ -1,10 +1,27 @@ namespace Umbraco.Cms.Core.Web; +/// +/// Defines session management operations. +/// public interface ISessionManager { + /// + /// Gets the session value for the specified key. + /// + /// The session key. + /// The session value if found; otherwise, null. string? GetSessionValue(string key); + /// + /// Sets the session value for the specified key. + /// + /// The session key. + /// The value to store in the session. void SetSessionValue(string key, string value); + /// + /// Clears the session value for the specified key. + /// + /// The session key to clear. void ClearSessionValue(string key); } diff --git a/src/Umbraco.Core/Web/IUmbracoContext.cs b/src/Umbraco.Core/Web/IUmbracoContext.cs index 35c4fe64ad8d..be35d1c98699 100644 --- a/src/Umbraco.Core/Web/IUmbracoContext.cs +++ b/src/Umbraco.Core/Web/IUmbracoContext.cs @@ -3,6 +3,10 @@ namespace Umbraco.Cms.Core.Web; +/// +/// Represents the Umbraco context for a request, providing access to published content, +/// media, domains, and request-specific information. +/// public interface IUmbracoContext : IDisposable { /// diff --git a/src/Umbraco.Core/Web/IUmbracoContextAccessor.cs b/src/Umbraco.Core/Web/IUmbracoContextAccessor.cs index 370412b2814a..8a2792df0101 100644 --- a/src/Umbraco.Core/Web/IUmbracoContextAccessor.cs +++ b/src/Umbraco.Core/Web/IUmbracoContextAccessor.cs @@ -3,15 +3,30 @@ namespace Umbraco.Cms.Core.Web; /// -/// Provides access to a TryGetUmbracoContext bool method that will return true if the "current" is not null. -/// Provides a Clear() method that will clear the current object. -/// Provides a Set() method that til set the current object. +/// Provides access to the current . /// +/// +/// Provides a method that returns true if the current is not null. +/// Provides a method that will clear the current object. +/// Provides a method that will set the current object. +/// public interface IUmbracoContextAccessor { + /// + /// Tries to get the current . + /// + /// When this method returns, contains the current if available; otherwise, null. + /// true if the current is available; otherwise, false. bool TryGetUmbracoContext([MaybeNullWhen(false)] out IUmbracoContext umbracoContext); + /// + /// Clears the current . + /// void Clear(); + /// + /// Sets the current . + /// + /// The to set as the current context. void Set(IUmbracoContext umbracoContext); } diff --git a/src/Umbraco.Core/Web/Mvc/PluginControllerMetadata.cs b/src/Umbraco.Core/Web/Mvc/PluginControllerMetadata.cs index 5f484c8fe027..51801889fe1c 100644 --- a/src/Umbraco.Core/Web/Mvc/PluginControllerMetadata.cs +++ b/src/Umbraco.Core/Web/Mvc/PluginControllerMetadata.cs @@ -1,21 +1,36 @@ namespace Umbraco.Cms.Core.Web.Mvc; /// -/// Represents some metadata about the controller +/// Represents metadata about a plugin controller. /// public class PluginControllerMetadata { + /// + /// Gets or sets the type of the controller. + /// public Type ControllerType { get; set; } = null!; + /// + /// Gets or sets the name of the controller. + /// public string? ControllerName { get; set; } + /// + /// Gets or sets the namespace of the controller. + /// public string? ControllerNamespace { get; set; } + /// + /// Gets or sets the area name for the controller. + /// public string? AreaName { get; set; } /// - /// This is determined by another attribute [IsBackOffice] which slightly modifies the route path - /// allowing us to determine if it is indeed a back office request or not + /// Gets or sets a value indicating whether this controller is a back office controller. /// + /// + /// This is determined by another attribute [IsBackOffice] which slightly modifies the route path + /// allowing us to determine if it is indeed a back office request or not. + /// public bool IsBackOffice { get; set; } } diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentCopiedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentCopiedWebhookEvent.cs index a36c1fae648f..f855b0972cf2 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentCopiedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentCopiedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when content is copied. +/// [WebhookEvent("Content Copied", Constants.WebhookEvents.Types.Content)] public class ContentCopiedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public ContentCopiedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -22,8 +32,10 @@ public ContentCopiedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentCopied; + /// public override object ConvertNotificationToRequestPayload(ContentCopiedNotification notification) { return new diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedBlueprintWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedBlueprintWebhookEvent.cs index 93369b9cd9e0..304599283871 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedBlueprintWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedBlueprintWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a content template (blueprint) is deleted. +/// [WebhookEvent("Content Template [Blueprint] Deleted", Constants.WebhookEvents.Types.Content)] public class ContentDeletedBlueprintWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public ContentDeletedBlueprintWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -23,10 +33,13 @@ public ContentDeletedBlueprintWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentDeletedBlueprint; + /// protected override IEnumerable GetEntitiesFromNotification(ContentDeletedBlueprintNotification notification) => notification.DeletedBlueprints; + /// protected override object ConvertEntityToRequestPayload(IContent entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedVersionsWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedVersionsWebhookEvent.cs index 37a7048fd53d..cd55ad23bef1 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedVersionsWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedVersionsWebhookEvent.cs @@ -7,11 +7,22 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when content versions are deleted. +/// [WebhookEvent("Content Versions Deleted", Constants.WebhookEvents.Types.Content)] public class ContentDeletedVersionsWebhookEvent : WebhookEventBase { private readonly IIdKeyMap _idKeyMap; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The ID to key mapping service. public ContentDeletedVersionsWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -27,8 +38,10 @@ public ContentDeletedVersionsWebhookEvent( _idKeyMap = idKeyMap; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentDeletedVersions; + /// public override object ConvertNotificationToRequestPayload(ContentDeletedVersionsNotification notification) { return new diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedWebhookEvent.cs index a439cc916713..2265e5a66a1c 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when content is deleted. +/// [WebhookEvent("Content Deleted", Constants.WebhookEvents.Types.Content)] public class ContentDeletedWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public ContentDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -23,11 +33,14 @@ public ContentDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentDelete; + /// protected override IEnumerable GetEntitiesFromNotification(ContentDeletedNotification notification) => notification.DeletedEntities; + /// protected override object ConvertEntityToRequestPayload(IContent entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentEmptiedRecycleBinWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentEmptiedRecycleBinWebhookEvent.cs index bc344528d3d9..2f49107a501a 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentEmptiedRecycleBinWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentEmptiedRecycleBinWebhookEvent.cs @@ -9,11 +9,22 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when the content recycle bin is emptied. +/// [WebhookEvent("Content Recycle Bin Emptied", Constants.WebhookEvents.Types.Content)] public class ContentEmptiedRecycleBinWebhookEvent : WebhookEventContentBase { private readonly IApiContentBuilder _apiContentBuilder; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The API content builder. public ContentEmptiedRecycleBinWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -29,11 +40,14 @@ public ContentEmptiedRecycleBinWebhookEvent( _apiContentBuilder = apiContentBuilder; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentEmptiedRecycleBin; + /// protected override IEnumerable GetEntitiesFromNotification(ContentEmptiedRecycleBinNotification notification) => notification.DeletedEntities; + /// protected override object ConvertEntityToRequestPayload(IContent entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedToRecycleBinWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedToRecycleBinWebhookEvent.cs index f7e45df629a5..ce6ac6768ce6 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedToRecycleBinWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedToRecycleBinWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when content is moved to the recycle bin. +/// [WebhookEvent("Content Moved to Recycle Bin", Constants.WebhookEvents.Types.Content)] public class ContentMovedToRecycleBinWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public ContentMovedToRecycleBinWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -23,8 +33,10 @@ public ContentMovedToRecycleBinWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentMovedToRecycleBin; + /// public override object ConvertNotificationToRequestPayload(ContentMovedToRecycleBinNotification notification) => notification.MoveInfoCollection.Select(moveInfo => new DefaultPayloadModel { Id = moveInfo.Entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedWebhookEvent.cs index 61137b85c3ce..396441e2bd1e 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentMovedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when content is moved. +/// [WebhookEvent("Content Moved", Constants.WebhookEvents.Types.Content)] public class ContentMovedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public ContentMovedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -23,8 +33,10 @@ public ContentMovedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentMoved; + /// public override object ConvertNotificationToRequestPayload(ContentMovedNotification notification) => notification.MoveInfoCollection.Select(moveInfo => new DefaultPayloadModel { Id = moveInfo.Entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentPublishedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentPublishedWebhookEvent.cs index 55fa122c8a5a..a4b98474c01c 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentPublishedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentPublishedWebhookEvent.cs @@ -11,12 +11,24 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when content is published. +/// [WebhookEvent("Content Published", Constants.WebhookEvents.Types.Content)] public class ContentPublishedWebhookEvent : WebhookEventContentBase { private readonly IApiContentBuilder _apiContentBuilder; private readonly IPublishedContentCache _publishedContentCache; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The API content builder. + /// The published content cache. public ContentPublishedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -34,10 +46,13 @@ public ContentPublishedWebhookEvent( _publishedContentCache = publishedContentCache; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentPublish; + /// protected override IEnumerable GetEntitiesFromNotification(ContentPublishedNotification notification) => notification.PublishedEntities; + /// protected override object? ConvertEntityToRequestPayload(IContent entity) => new { diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentRolledBackWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentRolledBackWebhookEvent.cs index 5a35bade7f77..a99d0f89ee9a 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentRolledBackWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentRolledBackWebhookEvent.cs @@ -10,12 +10,24 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when content is rolled back to a previous version. +/// [WebhookEvent("Content Rolled Back", Constants.WebhookEvents.Types.Content)] public class ContentRolledBackWebhookEvent : WebhookEventContentBase { private readonly IPublishedContentCache _contentCache; private readonly IApiContentBuilder _apiContentBuilder; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The published content cache. + /// The API content builder. public ContentRolledBackWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -33,11 +45,14 @@ public ContentRolledBackWebhookEvent( _apiContentBuilder = apiContentBuilder; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentRolledBack; + /// protected override IEnumerable GetEntitiesFromNotification(ContentRolledBackNotification notification) => new List { notification.Entity }; + /// protected override object? ConvertEntityToRequestPayload(IContent entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedBlueprintWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedBlueprintWebhookEvent.cs index f31ca28f15ac..d2fdfb77d7e8 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedBlueprintWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedBlueprintWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a content template (blueprint) is saved. +/// [WebhookEvent("Content Template [Blueprint] Saved", Constants.WebhookEvents.Types.Content)] public class ContentSavedBlueprintWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public ContentSavedBlueprintWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -23,12 +33,15 @@ public ContentSavedBlueprintWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentSavedBlueprint; + /// protected override IEnumerable GetEntitiesFromNotification(ContentSavedBlueprintNotification notification) => new List { notification.SavedBlueprint }; + /// protected override object ConvertEntityToRequestPayload(IContent entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedWebhookEvent.cs index 024bdcd3b400..c7b33fed6b92 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentSavedWebhookEvent.cs @@ -10,12 +10,24 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when content is saved. +/// [WebhookEvent("Content Saved", Constants.WebhookEvents.Types.Content)] public class ContentSavedWebhookEvent : WebhookEventContentBase { private readonly IApiContentBuilder _apiContentBuilder; private readonly IPublishedContentCache _contentCache; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The API content builder. + /// The published content cache. public ContentSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -33,11 +45,14 @@ public ContentSavedWebhookEvent( _contentCache = contentCache; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentSaved; + /// protected override IEnumerable GetEntitiesFromNotification(ContentSavedNotification notification) => notification.SavedEntities; + /// protected override object? ConvertEntityToRequestPayload(IContent entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentSortedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentSortedWebhookEvent.cs index 7aef1b6b224c..17118f424287 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentSortedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentSortedWebhookEvent.cs @@ -10,12 +10,24 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when content is sorted. +/// [WebhookEvent("Content Sorted", Constants.WebhookEvents.Types.Content)] public class ContentSortedWebhookEvent : WebhookEventBase { private readonly IPublishedContentCache _contentCache; private readonly IApiContentBuilder _apiContentBuilder; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The published content cache. + /// The API content builder. public ContentSortedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -33,8 +45,10 @@ public ContentSortedWebhookEvent( _apiContentBuilder = apiContentBuilder; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentSorted; + /// public override object ConvertNotificationToRequestPayload(ContentSortedNotification notification) => notification.SortedEntities .OrderBy(entity => entity.SortOrder) diff --git a/src/Umbraco.Core/Webhooks/Events/Content/ContentUnpublishedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Content/ContentUnpublishedWebhookEvent.cs index 5e0d7f407c87..fc5fb9963930 100644 --- a/src/Umbraco.Core/Webhooks/Events/Content/ContentUnpublishedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Content/ContentUnpublishedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when content is unpublished. +/// [WebhookEvent("Content Unpublished", Constants.WebhookEvents.Types.Content)] public class ContentUnpublishedWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public ContentUnpublishedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -23,10 +33,13 @@ public ContentUnpublishedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentUnpublish; + /// protected override IEnumerable GetEntitiesFromNotification(ContentUnpublishedNotification notification) => notification.UnpublishedEntities; + /// protected override object ConvertEntityToRequestPayload(IContent entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeChangedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeChangedWebhookEvent.cs index 0c4a56d502f5..a20dafb1d688 100644 --- a/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeChangedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeChangedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a document type is changed. +/// [WebhookEvent("Document Type Changed")] public class DocumentTypeChangedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public DocumentTypeChangedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public DocumentTypeChangedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DocumentTypeChanged; + /// public override object ConvertNotificationToRequestPayload(ContentTypeChangedNotification notification) => notification.Changes.Select(contentTypeChange => new { diff --git a/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeDeletedWebhookEvent.cs index a93eb777ed1b..555b167ffc38 100644 --- a/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a document type is deleted. +/// [WebhookEvent("Document Type Deleted")] public class DocumentTypeDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public DocumentTypeDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public DocumentTypeDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DocumentTypeDeleted; + /// public override object ConvertNotificationToRequestPayload(ContentTypeDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeMovedWebhookEvent.cs index 0f93cffc845c..2101a7ad437e 100644 --- a/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeMovedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeMovedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a document type is moved. +/// [WebhookEvent("Document Type Moved")] public class DocumentTypeMovedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public DocumentTypeMovedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public DocumentTypeMovedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DocumentTypeMoved; + /// public override object ConvertNotificationToRequestPayload(ContentTypeMovedNotification notification) => notification.MoveInfoCollection.Select(moveEvent => new { diff --git a/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeSavedWebhookEvent.cs index e3934a9a0352..98cafd75e27a 100644 --- a/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/ContentType/DocumentTypeSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a document type is saved. +/// [WebhookEvent("Document Type Saved")] public class DocumentTypeSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public DocumentTypeSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public DocumentTypeSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DocumentTypeSaved; + /// public override object ConvertNotificationToRequestPayload(ContentTypeSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeChangedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeChangedWebhookEvent.cs index 0b16c6a9ce36..8f193165cae5 100644 --- a/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeChangedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeChangedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a media type is changed. +/// [WebhookEvent("Media Type Changed")] public class MediaTypeChangedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MediaTypeChangedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public MediaTypeChangedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaTypeChanged; + /// public override object ConvertNotificationToRequestPayload(MediaTypeChangedNotification notification) => notification.Changes.Select(contentTypeChange => new { diff --git a/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeDeletedWebhookEvent.cs index c80ff8b7ecab..7674dfb8abf4 100644 --- a/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a media type is deleted. +/// [WebhookEvent("Media Type Deleted")] public class MediaTypeDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MediaTypeDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public MediaTypeDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaTypeDeleted; + /// public override object ConvertNotificationToRequestPayload(MediaTypeDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeMovedWebhookEvent.cs index d50ab40e56e7..e8bea904d6c2 100644 --- a/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeMovedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeMovedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a media type is moved. +/// [WebhookEvent("Media Type Moved")] public class MediaTypeMovedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MediaTypeMovedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public MediaTypeMovedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaTypeMoved; + /// public override object ConvertNotificationToRequestPayload(MediaTypeMovedNotification notification) => notification.MoveInfoCollection.Select(moveEvent => new { diff --git a/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeSavedWebhookEvent.cs index 6108256282aa..ebd6facd2ee5 100644 --- a/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/ContentType/MediaTypeSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a media type is saved. +/// [WebhookEvent("Media Type Saved")] public class MediaTypeSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MediaTypeSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public MediaTypeSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaTypeSaved; + /// public override object ConvertNotificationToRequestPayload(MediaTypeSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeChangedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeChangedWebhookEvent.cs index 12509a5f25ed..d0ce51b88de2 100644 --- a/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeChangedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeChangedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a member type is changed. +/// [WebhookEvent("Member Type Changed")] public class MemberTypeChangedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MemberTypeChangedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public MemberTypeChangedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberTypeChanged; + /// public override object ConvertNotificationToRequestPayload(MemberTypeChangedNotification notification) => notification.Changes.Select(contentTypeChange => new { diff --git a/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeDeletedWebhookEvent.cs index 992ed5a77a66..44a498f689fd 100644 --- a/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a member type is deleted. +/// [WebhookEvent("Member Type Deleted")] public class MemberTypeDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MemberTypeDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public MemberTypeDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberTypeDeleted; + /// public override object ConvertNotificationToRequestPayload(MemberTypeDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeMovedWebhookEvent.cs index e762f1f87025..e619c7e0460a 100644 --- a/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeMovedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeMovedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a member type is moved. +/// [WebhookEvent("Member Type Moved")] public class MemberTypeMovedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MemberTypeMovedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public MemberTypeMovedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberTypeMoved; + /// public override object ConvertNotificationToRequestPayload(MemberTypeMovedNotification notification) => notification.MoveInfoCollection.Select(moveEvent => new { diff --git a/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeSavedWebhookEvent.cs index 2f1a95095ee1..64e0b5db9b0e 100644 --- a/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/ContentType/MemberTypeSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a member type is saved. +/// [WebhookEvent("Member Type Saved")] public class MemberTypeSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MemberTypeSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public MemberTypeSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberTypeSaved; + /// public override object ConvertNotificationToRequestPayload(MemberTypeSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/DataType/DataTypeDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/DataType/DataTypeDeletedWebhookEvent.cs index b20d4aa7f171..c895502177a5 100644 --- a/src/Umbraco.Core/Webhooks/Events/DataType/DataTypeDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/DataType/DataTypeDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a data type is deleted. +/// [WebhookEvent("Data Type Deleted")] public class DataTypeDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public DataTypeDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public DataTypeDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DataTypeDeleted; + /// public override object ConvertNotificationToRequestPayload(DataTypeDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/DataType/DataTypeMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/DataType/DataTypeMovedWebhookEvent.cs index 15838a7a69f5..e7a1331a83ce 100644 --- a/src/Umbraco.Core/Webhooks/Events/DataType/DataTypeMovedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/DataType/DataTypeMovedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a data type is moved. +/// [WebhookEvent("Data Type Moved")] public class DataTypeMovedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public DataTypeMovedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public DataTypeMovedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DataTypeMoved; + /// public override object ConvertNotificationToRequestPayload(DataTypeMovedNotification notification) => notification.MoveInfoCollection.Select(moveEvent => new { diff --git a/src/Umbraco.Core/Webhooks/Events/DataType/DataTypeSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/DataType/DataTypeSavedWebhookEvent.cs index 65c8a72c7d01..5260646a6d2e 100644 --- a/src/Umbraco.Core/Webhooks/Events/DataType/DataTypeSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/DataType/DataTypeSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a data type is saved. +/// [WebhookEvent("Data Type Saved")] public class DataTypeSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public DataTypeSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public DataTypeSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DataTypeSaved; + /// public override object ConvertNotificationToRequestPayload(DataTypeSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Dictionary/DictionaryItemDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Dictionary/DictionaryItemDeletedWebhookEvent.cs index b6ee34e88246..5eacb554a483 100644 --- a/src/Umbraco.Core/Webhooks/Events/Dictionary/DictionaryItemDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Dictionary/DictionaryItemDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a dictionary item is deleted. +/// [WebhookEvent("Dictionary Item Deleted")] public class DictionaryItemDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public DictionaryItemDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public DictionaryItemDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DictionaryItemDeleted; + /// public override object ConvertNotificationToRequestPayload(DictionaryItemDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Dictionary/DictionaryItemSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Dictionary/DictionaryItemSavedWebhookEvent.cs index f952c85a508b..b5baa891dd89 100644 --- a/src/Umbraco.Core/Webhooks/Events/Dictionary/DictionaryItemSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Dictionary/DictionaryItemSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a dictionary item is saved. +/// [WebhookEvent("Dictionary Item Saved")] public class DictionaryItemSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public DictionaryItemSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public DictionaryItemSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DictionaryItemSaved; + /// public override object ConvertNotificationToRequestPayload(DictionaryItemSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Domain/DomainDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Domain/DomainDeletedWebhookEvent.cs index 1026d2f31e60..633f066345a9 100644 --- a/src/Umbraco.Core/Webhooks/Events/Domain/DomainDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Domain/DomainDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a domain is deleted. +/// [WebhookEvent("Domain Deleted")] public class DomainDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public DomainDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public DomainDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DomainDeleted; + /// public override object ConvertNotificationToRequestPayload(DomainDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Domain/DomainSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Domain/DomainSavedWebhookEvent.cs index bd86be3b770d..cb4b55eb12bc 100644 --- a/src/Umbraco.Core/Webhooks/Events/Domain/DomainSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Domain/DomainSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a domain is saved. +/// [WebhookEvent("Domain Saved")] public class DomainSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public DomainSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public DomainSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DomainSaved; + /// public override object ConvertNotificationToRequestPayload(DomainSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/File/PartialViewDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/File/PartialViewDeletedWebhookEvent.cs index 16ea3930bfa3..88448cf2ef0a 100644 --- a/src/Umbraco.Core/Webhooks/Events/File/PartialViewDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/File/PartialViewDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a partial view is deleted. +/// [WebhookEvent("Partial View Deleted")] public class PartialViewDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public PartialViewDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public PartialViewDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.PartialViewDeleted; + /// public override object ConvertNotificationToRequestPayload(PartialViewDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/File/PartialViewSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/File/PartialViewSavedWebhookEvent.cs index 94f2966ea6b3..acb375cb7df0 100644 --- a/src/Umbraco.Core/Webhooks/Events/File/PartialViewSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/File/PartialViewSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a partial view is saved. +/// [WebhookEvent("Partial View Saved")] public class PartialViewSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public PartialViewSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public PartialViewSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.PartialViewSaved; + /// public override object ConvertNotificationToRequestPayload(PartialViewSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/File/ScriptDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/File/ScriptDeletedWebhookEvent.cs index 13470e8c2cf2..c4fb72a5196d 100644 --- a/src/Umbraco.Core/Webhooks/Events/File/ScriptDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/File/ScriptDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a script is deleted. +/// [WebhookEvent("Script Deleted")] public class ScriptDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public ScriptDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public ScriptDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ScriptDeleted; + /// public override object ConvertNotificationToRequestPayload(ScriptDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/File/ScriptSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/File/ScriptSavedWebhookEvent.cs index 121f81b5e4d7..8205e7b96ee0 100644 --- a/src/Umbraco.Core/Webhooks/Events/File/ScriptSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/File/ScriptSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a script is saved. +/// [WebhookEvent("Script Saved")] public class ScriptSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public ScriptSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public ScriptSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ScriptSaved; + /// public override object ConvertNotificationToRequestPayload(ScriptSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/File/StylesheetDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/File/StylesheetDeletedWebhookEvent.cs index d7dee2925899..557886679d26 100644 --- a/src/Umbraco.Core/Webhooks/Events/File/StylesheetDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/File/StylesheetDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a stylesheet is deleted. +/// [WebhookEvent("Stylesheet Deleted")] public class StylesheetDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public StylesheetDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public StylesheetDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.StylesheetDeleted; + /// public override object ConvertNotificationToRequestPayload(StylesheetDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/File/StylesheetSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/File/StylesheetSavedWebhookEvent.cs index 9217b8a7d7e4..ece6995dc7c3 100644 --- a/src/Umbraco.Core/Webhooks/Events/File/StylesheetSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/File/StylesheetSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a stylesheet is saved. +/// [WebhookEvent("Stylesheet Saved")] public class StylesheetSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public StylesheetSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public StylesheetSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.StylesheetSaved; + /// public override object ConvertNotificationToRequestPayload(StylesheetSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/File/TemplateDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/File/TemplateDeletedWebhookEvent.cs index 029870fd0f4d..fe62f4650c1a 100644 --- a/src/Umbraco.Core/Webhooks/Events/File/TemplateDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/File/TemplateDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a template is deleted. +/// [WebhookEvent("Template Deleted")] public class TemplateDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public TemplateDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public TemplateDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.TemplateDeleted; + /// public override object ConvertNotificationToRequestPayload(TemplateDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/File/TemplateSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/File/TemplateSavedWebhookEvent.cs index 86aae3a3212b..680c34379c0c 100644 --- a/src/Umbraco.Core/Webhooks/Events/File/TemplateSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/File/TemplateSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a template is saved. +/// [WebhookEvent("Template Saved")] public class TemplateSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public TemplateSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public TemplateSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.TemplateSaved; + /// public override object ConvertNotificationToRequestPayload(TemplateSavedNotification notification) => notification.SavedEntities.Select(entity => new { diff --git a/src/Umbraco.Core/Webhooks/Events/HealthCheck/HealthCheckCompletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/HealthCheck/HealthCheckCompletedWebhookEvent.cs index b902aa6ab7d0..41958dd3c49a 100644 --- a/src/Umbraco.Core/Webhooks/Events/HealthCheck/HealthCheckCompletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/HealthCheck/HealthCheckCompletedWebhookEvent.cs @@ -6,15 +6,27 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when health checks are completed. +/// [WebhookEvent("Health Check Completed")] public class HealthCheckCompletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public HealthCheckCompletedWebhookEvent(IWebhookFiringService webhookFiringService, IWebhookService webhookService, IOptionsMonitor webhookSettings, IServerRoleAccessor serverRoleAccessor) : base(webhookFiringService, webhookService, webhookSettings, serverRoleAccessor) { } + /// public override string Alias => Constants.WebhookEvents.Aliases.HealthCheckCompleted; + /// public override object ConvertNotificationToRequestPayload(HealthCheckCompletedNotification notification) => new { diff --git a/src/Umbraco.Core/Webhooks/Events/Language/LanguageDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Language/LanguageDeletedWebhookEvent.cs index 8211577bd66a..4eeddc21f152 100644 --- a/src/Umbraco.Core/Webhooks/Events/Language/LanguageDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Language/LanguageDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a language is deleted. +/// [WebhookEvent("Language Deleted")] public class LanguageDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LanguageDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public LanguageDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.LanguageDeleted; + /// public override object ConvertNotificationToRequestPayload(LanguageDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Language/LanguageSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Language/LanguageSavedWebhookEvent.cs index f8d39dc7ccee..e90bf68ebab4 100644 --- a/src/Umbraco.Core/Webhooks/Events/Language/LanguageSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Language/LanguageSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a language is saved. +/// [WebhookEvent("Language Saved")] public class LanguageSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LanguageSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public LanguageSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.LanguageSaved; + /// public override object ConvertNotificationToRequestPayload(LanguageSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Media/MediaDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Media/MediaDeletedWebhookEvent.cs index 5da80cdf108f..418d8d34a98d 100644 --- a/src/Umbraco.Core/Webhooks/Events/Media/MediaDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Media/MediaDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when media is deleted. +/// [WebhookEvent("Media Deleted", Constants.WebhookEvents.Types.Media)] public class MediaDeletedWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MediaDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -23,11 +33,14 @@ public MediaDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaDelete; + /// protected override IEnumerable GetEntitiesFromNotification(MediaDeletedNotification notification) => notification.DeletedEntities; + /// protected override object ConvertEntityToRequestPayload(IMedia entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/Media/MediaEmptiedRecycleBinWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Media/MediaEmptiedRecycleBinWebhookEvent.cs index 2dbd59b5df7b..e1e90cf87344 100644 --- a/src/Umbraco.Core/Webhooks/Events/Media/MediaEmptiedRecycleBinWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Media/MediaEmptiedRecycleBinWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when the media recycle bin is emptied. +/// [WebhookEvent("Media Recycle Bin Emptied", Constants.WebhookEvents.Types.Media)] public class MediaEmptiedRecycleBinWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MediaEmptiedRecycleBinWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -23,11 +33,14 @@ public MediaEmptiedRecycleBinWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaEmptiedRecycleBin; + /// protected override IEnumerable GetEntitiesFromNotification(MediaEmptiedRecycleBinNotification notification) => notification.DeletedEntities; + /// protected override object ConvertEntityToRequestPayload(IMedia entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/Media/MediaMovedToRecycleBinWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Media/MediaMovedToRecycleBinWebhookEvent.cs index afcf93e6270e..da917c66d4f6 100644 --- a/src/Umbraco.Core/Webhooks/Events/Media/MediaMovedToRecycleBinWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Media/MediaMovedToRecycleBinWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when media is moved to the recycle bin. +/// [WebhookEvent("Media Moved to Recycle Bin", Constants.WebhookEvents.Types.Media)] public class MediaMovedToRecycleBinWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MediaMovedToRecycleBinWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -23,11 +33,14 @@ public MediaMovedToRecycleBinWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaMovedToRecycleBin; + /// protected override IEnumerable GetEntitiesFromNotification(MediaMovedToRecycleBinNotification notification) => notification.MoveInfoCollection.Select(x => x.Entity); + /// protected override object ConvertEntityToRequestPayload(IMedia entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/Media/MediaMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Media/MediaMovedWebhookEvent.cs index e37d66405d67..c0f30e8cceef 100644 --- a/src/Umbraco.Core/Webhooks/Events/Media/MediaMovedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Media/MediaMovedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when media is moved. +/// [WebhookEvent("Media Moved", Constants.WebhookEvents.Types.Media)] public class MediaMovedWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MediaMovedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -23,11 +33,14 @@ public MediaMovedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaMoved; + /// protected override IEnumerable GetEntitiesFromNotification(MediaMovedNotification notification) => notification.MoveInfoCollection.Select(x => x.Entity); + /// protected override object ConvertEntityToRequestPayload(IMedia entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/Media/MediaSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Media/MediaSavedWebhookEvent.cs index 21a39fb42d85..8b2d075b4eb1 100644 --- a/src/Umbraco.Core/Webhooks/Events/Media/MediaSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Media/MediaSavedWebhookEvent.cs @@ -10,12 +10,24 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when media is saved. +/// [WebhookEvent("Media Saved", Constants.WebhookEvents.Types.Media)] public class MediaSavedWebhookEvent : WebhookEventContentBase { private readonly IPublishedMediaCache _mediaCache; private readonly IApiMediaBuilder _apiMediaBuilder; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The published media cache. + /// The API media builder. public MediaSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -33,11 +45,14 @@ public MediaSavedWebhookEvent( _apiMediaBuilder = apiMediaBuilder; } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaSave; + /// protected override IEnumerable GetEntitiesFromNotification(MediaSavedNotification notification) => notification.SavedEntities; + /// protected override object? ConvertEntityToRequestPayload(IMedia entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/Member/AssignedMemberRolesWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Member/AssignedMemberRolesWebhookEvent.cs index c1a65a14a51f..31fd85fb255f 100644 --- a/src/Umbraco.Core/Webhooks/Events/Member/AssignedMemberRolesWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Member/AssignedMemberRolesWebhookEvent.cs @@ -7,11 +7,22 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when member roles are assigned. +/// [WebhookEvent("Member Roles Assigned")] public class AssignedMemberRolesWebhookEvent : WebhookEventBase { private readonly IIdKeyMap _idKeyMap; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The ID to key mapping service. public AssignedMemberRolesWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -23,8 +34,10 @@ public AssignedMemberRolesWebhookEvent( _idKeyMap = idKeyMap; } + /// public override string Alias => Constants.WebhookEvents.Aliases.AssignedMemberRoles; + /// public override object ConvertNotificationToRequestPayload(AssignedMemberRolesNotification notification) => new { diff --git a/src/Umbraco.Core/Webhooks/Events/Member/ExportedMemberWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Member/ExportedMemberWebhookEvent.cs index 3f325dba34ee..7827813e7acd 100644 --- a/src/Umbraco.Core/Webhooks/Events/Member/ExportedMemberWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Member/ExportedMemberWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a member is exported. +/// [WebhookEvent("Member Exported")] public class ExportedMemberWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public ExportedMemberWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public ExportedMemberWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ExportedMember; + /// public override object ConvertNotificationToRequestPayload(ExportedMemberNotification notification) => new DefaultPayloadModel { Id = notification.Member.Key }; } diff --git a/src/Umbraco.Core/Webhooks/Events/Member/MemberDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Member/MemberDeletedWebhookEvent.cs index 4f097192d8a4..44b4a9070530 100644 --- a/src/Umbraco.Core/Webhooks/Events/Member/MemberDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Member/MemberDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a member is deleted. +/// [WebhookEvent("Member Deleted")] public class MemberDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MemberDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public MemberDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberDeleted; + /// public override object ConvertNotificationToRequestPayload(MemberDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key, }); diff --git a/src/Umbraco.Core/Webhooks/Events/Member/MemberGroupDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Member/MemberGroupDeletedWebhookEvent.cs index aad3421e58ea..dd8c72b1c5b7 100644 --- a/src/Umbraco.Core/Webhooks/Events/Member/MemberGroupDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Member/MemberGroupDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a member group is deleted. +/// [WebhookEvent("Member Group Deleted")] public class MemberGroupDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MemberGroupDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public MemberGroupDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberGroupDeleted; + /// public override object ConvertNotificationToRequestPayload(MemberGroupDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Member/MemberGroupSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Member/MemberGroupSavedWebhookEvent.cs index 24d6b93101a6..84c23d441b4d 100644 --- a/src/Umbraco.Core/Webhooks/Events/Member/MemberGroupSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Member/MemberGroupSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a member group is saved. +/// [WebhookEvent("Member Group Saved")] public class MemberGroupSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MemberGroupSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public MemberGroupSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberGroupSaved; + /// public override object ConvertNotificationToRequestPayload(MemberGroupSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel{ Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Member/MemberSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Member/MemberSavedWebhookEvent.cs index dacff8fcd652..2adb31722505 100644 --- a/src/Umbraco.Core/Webhooks/Events/Member/MemberSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Member/MemberSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a member is saved. +/// [WebhookEvent("Member Saved")] public class MemberSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public MemberSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public MemberSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberSaved; + /// public override object ConvertNotificationToRequestPayload(MemberSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Member/RemovedMemberRolesWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Member/RemovedMemberRolesWebhookEvent.cs index c8109b0d19f6..d5cf128203ba 100644 --- a/src/Umbraco.Core/Webhooks/Events/Member/RemovedMemberRolesWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Member/RemovedMemberRolesWebhookEvent.cs @@ -7,11 +7,22 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when member roles are removed. +/// [WebhookEvent("Member Roles Removed")] public class RemovedMemberRolesWebhookEvent : WebhookEventBase { private readonly IIdKeyMap _idKeyMap; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The ID to key mapping service. public RemovedMemberRolesWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -23,8 +34,10 @@ public RemovedMemberRolesWebhookEvent( _idKeyMap = idKeyMap; } + /// public override string Alias => Constants.WebhookEvents.Aliases.RemovedMemberRoles; + /// public override object ConvertNotificationToRequestPayload(RemovedMemberRolesNotification notification) => new { diff --git a/src/Umbraco.Core/Webhooks/Events/Package/ImportedPackageWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Package/ImportedPackageWebhookEvent.cs index 4b003ff2a31b..17e937d293ae 100644 --- a/src/Umbraco.Core/Webhooks/Events/Package/ImportedPackageWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Package/ImportedPackageWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a package is imported. +/// [WebhookEvent("Package Imported")] public class ImportedPackageWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public ImportedPackageWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public ImportedPackageWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.PackageImported; + /// public override object ConvertNotificationToRequestPayload(ImportedPackageNotification notification) => new { diff --git a/src/Umbraco.Core/Webhooks/Events/PublicAccess/PublicAccessEntryDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/PublicAccess/PublicAccessEntryDeletedWebhookEvent.cs index 4a9593c123dd..95e39935dc4b 100644 --- a/src/Umbraco.Core/Webhooks/Events/PublicAccess/PublicAccessEntryDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/PublicAccess/PublicAccessEntryDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a public access entry is deleted. +/// [WebhookEvent("Public Access Entry Deleted")] public class PublicAccessEntryDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public PublicAccessEntryDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public PublicAccessEntryDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.PublicAccessEntryDeleted; + /// public override object ConvertNotificationToRequestPayload(PublicAccessEntryDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/PublicAccess/PublicAccessEntrySavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/PublicAccess/PublicAccessEntrySavedWebhookEvent.cs index 7ac8163371eb..0967183fdb7e 100644 --- a/src/Umbraco.Core/Webhooks/Events/PublicAccess/PublicAccessEntrySavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/PublicAccess/PublicAccessEntrySavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a public access entry is saved. +/// [WebhookEvent("Public Access Entry Saved")] public class PublicAccessEntrySavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public PublicAccessEntrySavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public PublicAccessEntrySavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.PublicAccessEntrySaved; + /// public override object ConvertNotificationToRequestPayload(PublicAccessEntrySavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Relation/RelationDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Relation/RelationDeletedWebhookEvent.cs index 94e6f326aabf..da9ce8ce47ec 100644 --- a/src/Umbraco.Core/Webhooks/Events/Relation/RelationDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Relation/RelationDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a relation is deleted. +/// [WebhookEvent("Relation Deleted")] public class RelationDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public RelationDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public RelationDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.RelationDeleted; + /// public override object ConvertNotificationToRequestPayload(RelationDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/Relation/RelationSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/Relation/RelationSavedWebhookEvent.cs index 219abbc28040..9b18b6fe62c3 100644 --- a/src/Umbraco.Core/Webhooks/Events/Relation/RelationSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/Relation/RelationSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a relation is saved. +/// [WebhookEvent("Relation Saved")] public class RelationSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public RelationSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public RelationSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.RelationSaved; + /// public override object ConvertNotificationToRequestPayload(RelationSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/RelationType/RelationTypeDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/RelationType/RelationTypeDeletedWebhookEvent.cs index e26ccc3dfab0..0a881f18683f 100644 --- a/src/Umbraco.Core/Webhooks/Events/RelationType/RelationTypeDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/RelationType/RelationTypeDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a relation type is deleted. +/// [WebhookEvent("Relation Type Deleted")] public class RelationTypeDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public RelationTypeDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,9 +29,10 @@ public RelationTypeDeletedWebhookEvent( { } - + /// public override string Alias => Constants.WebhookEvents.Aliases.RelationTypeDeleted; + /// public override object ConvertNotificationToRequestPayload(RelationTypeDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/RelationType/RelationTypeSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/RelationType/RelationTypeSavedWebhookEvent.cs index 04a509c19dea..9e84c43697fa 100644 --- a/src/Umbraco.Core/Webhooks/Events/RelationType/RelationTypeSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/RelationType/RelationTypeSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a relation type is saved. +/// [WebhookEvent("Relation Type Saved")] public class RelationTypeSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public RelationTypeSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public RelationTypeSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.RelationTypeSaved; + /// public override object ConvertNotificationToRequestPayload(RelationTypeSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserDeletedWebhookEvent.cs index f848570d8e99..c1ce338227ba 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user is deleted. +/// [WebhookEvent("User Deleted")] public class UserDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public UserDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserDeleted; + /// public override object ConvertNotificationToRequestPayload(UserDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserForgotPasswordRequestedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserForgotPasswordRequestedWebhookEvent.cs index e791206e6a12..3a3e1568291b 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserForgotPasswordRequestedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserForgotPasswordRequestedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user requests a forgotten password reset. +/// [WebhookEvent("User Forgot Password Requested")] public class UserForgotPasswordRequestedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserForgotPasswordRequestedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public UserForgotPasswordRequestedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserForgotPasswordRequested; + /// public override object ConvertNotificationToRequestPayload(UserForgotPasswordRequestedNotification notification) => new DefaultPayloadModel { diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserGroupDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserGroupDeletedWebhookEvent.cs index 3b00be82e05a..d8e0f5c5fa20 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserGroupDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserGroupDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user group is deleted. +/// [WebhookEvent("User Group Deleted")] public class UserGroupDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserGroupDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public UserGroupDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserGroupDeleted; + /// public override object ConvertNotificationToRequestPayload(UserGroupDeletedNotification notification) => notification.DeletedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserGroupSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserGroupSavedWebhookEvent.cs index 8cda0d25c4be..0a0de924a045 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserGroupSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserGroupSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user group is saved. +/// [WebhookEvent("User Group Saved")] public class UserGroupSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserGroupSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public UserGroupSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserGroupSaved; + /// public override object ConvertNotificationToRequestPayload(UserGroupSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserLockedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserLockedWebhookEvent.cs index 184e85704ac7..dd819959136f 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserLockedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserLockedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user is locked. +/// [WebhookEvent("User Locked")] public class UserLockedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserLockedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public UserLockedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserLocked; + /// public override object ConvertNotificationToRequestPayload(UserLockedNotification notification) => new DefaultPayloadModel { diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserLoginFailedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserLoginFailedWebhookEvent.cs index b79a84181348..ae64a0c68a78 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserLoginFailedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserLoginFailedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user login fails. +/// [WebhookEvent("User Login Failed")] public class UserLoginFailedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserLoginFailedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public UserLoginFailedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserLoginFailed; + /// public override object ConvertNotificationToRequestPayload(UserLoginFailedNotification notification) => new DefaultPayloadModel { diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserLoginRequiresVerificationWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserLoginRequiresVerificationWebhookEvent.cs index c35a0729ecf8..97f204aaa4b8 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserLoginRequiresVerificationWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserLoginRequiresVerificationWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user login requires verification (e.g., two-factor authentication). +/// [WebhookEvent("User Login Requires Verification")] public class UserLoginRequiresVerificationWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserLoginRequiresVerificationWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public UserLoginRequiresVerificationWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserLoginRequiresVerification; + /// public override object ConvertNotificationToRequestPayload(UserLoginRequiresVerificationNotification notification) => new DefaultPayloadModel { diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserLoginSuccessWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserLoginSuccessWebhookEvent.cs index d98bd63a26fe..9a6d5ee01d6e 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserLoginSuccessWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserLoginSuccessWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user successfully logs in. +/// [WebhookEvent("User Login Success")] public class UserLoginSuccessWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserLoginSuccessWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public UserLoginSuccessWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserLoginSuccess; + /// public override object ConvertNotificationToRequestPayload(UserLoginSuccessNotification notification) => new DefaultPayloadModel { diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserLogoutSuccessWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserLogoutSuccessWebhookEvent.cs index f89c528038e8..6ea46df390e9 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserLogoutSuccessWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserLogoutSuccessWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user successfully logs out. +/// [WebhookEvent("User Logout Success")] public class UserLogoutSuccessWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserLogoutSuccessWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public UserLogoutSuccessWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserLogoutSuccess; + /// public override object ConvertNotificationToRequestPayload(UserLogoutSuccessNotification notification) => new DefaultPayloadModel { diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserPasswordChangedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserPasswordChangedWebhookEvent.cs index b02d80da0e54..a6f766cd4c69 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserPasswordChangedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserPasswordChangedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user's password is changed. +/// [WebhookEvent("User Password Changed")] public class UserPasswordChangedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserPasswordChangedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public UserPasswordChangedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserPasswordChanged; + /// public override object ConvertNotificationToRequestPayload(UserPasswordChangedNotification notification) => new { diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserPasswordResetWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserPasswordResetWebhookEvent.cs index 811ca8dbd125..20c7e99dfde0 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserPasswordResetWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserPasswordResetWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user's password is reset. +/// [WebhookEvent("User Password Reset")] public class UserPasswordResetWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserPasswordResetWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public UserPasswordResetWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserPasswordReset; + /// public override object ConvertNotificationToRequestPayload(UserPasswordResetNotification notification) => new { diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserSavedWebhookEvent.cs index 115b3406dbd0..6b4b5ca24683 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserSavedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user is saved. +/// [WebhookEvent("User Saved")] public class UserSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public UserSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserSaved; + /// public override object ConvertNotificationToRequestPayload(UserSavedNotification notification) => notification.SavedEntities.Select(entity => new DefaultPayloadModel { Id = entity.Key }); } diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserTwoFactorRequestedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserTwoFactorRequestedWebhookEvent.cs index 2183498e6986..bd0ca1475e08 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserTwoFactorRequestedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserTwoFactorRequestedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when two-factor authentication is requested for a user. +/// [WebhookEvent("User Two Factor Requested")] public class UserTwoFactorRequestedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserTwoFactorRequestedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -19,8 +29,10 @@ public UserTwoFactorRequestedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserTwoFactorRequested; + /// public override object ConvertNotificationToRequestPayload(UserTwoFactorRequestedNotification notification) => new DefaultPayloadModel { Id = notification.UserKey }; } diff --git a/src/Umbraco.Core/Webhooks/Events/User/UserUnlockedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/Events/User/UserUnlockedWebhookEvent.cs index f2835ed2eef5..6a39b00e37b0 100644 --- a/src/Umbraco.Core/Webhooks/Events/User/UserUnlockedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/Events/User/UserUnlockedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Webhook event that fires when a user is unlocked. +/// [WebhookEvent("User Unlocked")] public class UserUnlockedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public UserUnlockedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public UserUnlockedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserUnlocked; + /// public override object ConvertNotificationToRequestPayload(UserUnlockedNotification notification) => new { diff --git a/src/Umbraco.Core/Webhooks/ExtendedEvents/Content/ExtendedContentPublishedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/ExtendedEvents/Content/ExtendedContentPublishedWebhookEvent.cs index 733352fb7db7..33f3e0811b03 100644 --- a/src/Umbraco.Core/Webhooks/ExtendedEvents/Content/ExtendedContentPublishedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/ExtendedEvents/Content/ExtendedContentPublishedWebhookEvent.cs @@ -11,12 +11,26 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Extended webhook event that fires when content is published, including full Delivery API content payloads. +/// [WebhookEvent("Content Published", Constants.WebhookEvents.Types.Content)] public class ExtendedContentPublishedWebhookEvent : ExtendedContentWebhookEventBase { private readonly IApiContentResponseBuilder _apiContentBuilder; private readonly IPublishedContentCache _publishedContentCache; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The API content response builder. + /// The published content cache. + /// The output expansion strategy accessor. + /// The variation context accessor. public ExtendedContentPublishedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -38,11 +52,14 @@ public ExtendedContentPublishedWebhookEvent( _publishedContentCache = publishedContentCache; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentPublish; + /// protected override IEnumerable GetEntitiesFromNotification(ContentPublishedNotification notification) => notification.PublishedEntities; + /// protected override object? ConvertEntityToRequestPayload(IContent entity) { IPublishedContent? publishedContent = _publishedContentCache.GetById(entity.Key); diff --git a/src/Umbraco.Core/Webhooks/ExtendedEvents/Content/ExtendedContentSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/ExtendedEvents/Content/ExtendedContentSavedWebhookEvent.cs index a8ceb26ce1ef..149a6e67df57 100644 --- a/src/Umbraco.Core/Webhooks/ExtendedEvents/Content/ExtendedContentSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/ExtendedEvents/Content/ExtendedContentSavedWebhookEvent.cs @@ -11,6 +11,9 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Extended webhook event that fires when content is saved, including full Delivery API content payloads. +/// [WebhookEvent("Content Saved", Constants.WebhookEvents.Types.Content)] public class ExtendedContentSavedWebhookEvent : ExtendedContentWebhookEventBase { @@ -19,6 +22,17 @@ public class ExtendedContentSavedWebhookEvent : ExtendedContentWebhookEventBase< private readonly IVariationContextAccessor _variationContextAccessor; private readonly IOutputExpansionStrategyAccessor _outputExpansionStrategyAccessor; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The API content response builder. + /// The published content cache. + /// The variation context accessor. + /// The output expansion strategy accessor. public ExtendedContentSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -42,11 +56,14 @@ public ExtendedContentSavedWebhookEvent( _outputExpansionStrategyAccessor = outputExpansionStrategyAccessor; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentSaved; + /// protected override IEnumerable GetEntitiesFromNotification(ContentSavedNotification notification) => notification.SavedEntities; + /// protected override object? ConvertEntityToRequestPayload(IContent entity) { // Get preview/saved version of content diff --git a/src/Umbraco.Core/Webhooks/ExtendedEvents/Content/ExtendedContentWebhookEventBase.cs b/src/Umbraco.Core/Webhooks/ExtendedEvents/Content/ExtendedContentWebhookEventBase.cs index 60a8cf91e09e..cdbc3bf65031 100644 --- a/src/Umbraco.Core/Webhooks/ExtendedEvents/Content/ExtendedContentWebhookEventBase.cs +++ b/src/Umbraco.Core/Webhooks/ExtendedEvents/Content/ExtendedContentWebhookEventBase.cs @@ -10,12 +10,25 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Abstract base class for extended content webhook events that include full Delivery API content payloads. +/// +/// The type of notification this webhook event handles. public abstract class ExtendedContentWebhookEventBase : WebhookEventContentBase where TNotification : INotification { private readonly IOutputExpansionStrategyAccessor _outputExpansionStrategyAccessor; private readonly IVariationContextAccessor _variationContextAccessor; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The output expansion strategy accessor. + /// The variation context accessor. public ExtendedContentWebhookEventBase( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -29,6 +42,12 @@ public ExtendedContentWebhookEventBase( _variationContextAccessor = variationContextAccessor; } + /// + /// Builds a dictionary of culture-specific properties for the given content. + /// + /// The published content. + /// The Delivery API content response. + /// A dictionary containing culture codes as keys and culture-specific data as values. public Dictionary BuildCultureProperties( IPublishedContent publishedContent, IApiContentResponse deliveryContent) diff --git a/src/Umbraco.Core/Webhooks/ExtendedEvents/Media/ExtendedMediaSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/ExtendedEvents/Media/ExtendedMediaSavedWebhookEvent.cs index a5146daa5045..fee40fa277cd 100644 --- a/src/Umbraco.Core/Webhooks/ExtendedEvents/Media/ExtendedMediaSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/ExtendedEvents/Media/ExtendedMediaSavedWebhookEvent.cs @@ -10,6 +10,9 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Extended webhook event that fires when media is saved, including full Delivery API media payloads. +/// // todo: convert to proper extended media event when deliveryApi models are fixed [WebhookEvent("Media Saved", Constants.WebhookEvents.Types.Media)] public class ExtendedMediaSavedWebhookEvent : WebhookEventContentBase @@ -17,6 +20,15 @@ public class ExtendedMediaSavedWebhookEvent : WebhookEventContentBase + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The published media cache. + /// The API media builder. public ExtendedMediaSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -34,10 +46,13 @@ public ExtendedMediaSavedWebhookEvent( _apiMediaBuilder = apiMediaBuilder; } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaSave; + /// protected override IEnumerable GetEntitiesFromNotification(MediaSavedNotification notification) => notification.SavedEntities; + /// protected override object? ConvertEntityToRequestPayload(IMedia entity) { IPublishedContent? publishedContent = _mediaCache.GetById(entity.Key); diff --git a/src/Umbraco.Core/Webhooks/IWebhookEvent.cs b/src/Umbraco.Core/Webhooks/IWebhookEvent.cs index 693cc2219389..fc7e74c06449 100644 --- a/src/Umbraco.Core/Webhooks/IWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/IWebhookEvent.cs @@ -1,10 +1,22 @@ -namespace Umbraco.Cms.Core.Webhooks; +namespace Umbraco.Cms.Core.Webhooks; +/// +/// Represents a webhook event that can be triggered by the CMS. +/// public interface IWebhookEvent { + /// + /// Gets the friendly display name of the webhook event. + /// string EventName { get; } + /// + /// Gets the type/category of the webhook event. + /// string EventType { get; } + /// + /// Gets the unique alias used to identify this webhook event. + /// string Alias { get; } } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentCopiedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentCopiedWebhookEvent.cs index 6598782606a9..65ebf5eb24f6 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentCopiedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentCopiedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when content is copied, using the legacy payload format. +/// [WebhookEvent("Content Copied", Constants.WebhookEvents.Types.Content)] public class LegacyContentCopiedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyContentCopiedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -22,8 +32,10 @@ public LegacyContentCopiedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentCopied; + /// public override object ConvertNotificationToRequestPayload(ContentCopiedNotification notification) { return new diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentDeletedBlueprintWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentDeletedBlueprintWebhookEvent.cs index eadb7ec80c86..5840a4614674 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentDeletedBlueprintWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentDeletedBlueprintWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a content template (blueprint) is deleted, using the legacy payload format. +/// [WebhookEvent("Content Template [Blueprint] Deleted", Constants.WebhookEvents.Types.Content)] public class LegacyContentDeletedBlueprintWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyContentDeletedBlueprintWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -23,10 +33,13 @@ public LegacyContentDeletedBlueprintWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentDeletedBlueprint; + /// protected override IEnumerable GetEntitiesFromNotification(ContentDeletedBlueprintNotification notification) => notification.DeletedBlueprints; + /// protected override object ConvertEntityToRequestPayload(IContent entity) => entity; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentDeletedVersionsWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentDeletedVersionsWebhookEvent.cs index dee9d7c79fd1..86334d3a6d7b 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentDeletedVersionsWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentDeletedVersionsWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when content versions are deleted, using the legacy payload format. +/// [WebhookEvent("Content Versions Deleted", Constants.WebhookEvents.Types.Content)] public class LegacyContentDeletedVersionsWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyContentDeletedVersionsWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -22,8 +32,10 @@ public LegacyContentDeletedVersionsWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentDeletedVersions; + /// public override object ConvertNotificationToRequestPayload(ContentDeletedVersionsNotification notification) { return new diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentDeletedWebhookEvent.cs index 76c080175091..3d633ee339f0 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when content is deleted, using the legacy payload format. +/// [WebhookEvent("Content Deleted", Constants.WebhookEvents.Types.Content)] public class LegacyContentDeletedWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyContentDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -23,10 +33,13 @@ public LegacyContentDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentDelete; + /// protected override IEnumerable GetEntitiesFromNotification(ContentDeletedNotification notification) => notification.DeletedEntities; + /// protected override object ConvertEntityToRequestPayload(IContent entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentEmptiedRecycleBinWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentEmptiedRecycleBinWebhookEvent.cs index f117f83d149a..347f2728a9ff 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentEmptiedRecycleBinWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentEmptiedRecycleBinWebhookEvent.cs @@ -8,11 +8,22 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when the content recycle bin is emptied, using the legacy payload format. +/// [WebhookEvent("Content Recycle Bin Emptied", Constants.WebhookEvents.Types.Content)] public class LegacyContentEmptiedRecycleBinWebhookEvent : WebhookEventContentBase { private readonly IApiContentBuilder _apiContentBuilder; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The API content builder. public LegacyContentEmptiedRecycleBinWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -28,10 +39,13 @@ public LegacyContentEmptiedRecycleBinWebhookEvent( _apiContentBuilder = apiContentBuilder; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentEmptiedRecycleBin; + /// protected override IEnumerable GetEntitiesFromNotification(ContentEmptiedRecycleBinNotification notification) => notification.DeletedEntities; + /// protected override object? ConvertEntityToRequestPayload(IContent entity) => entity; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentMovedToRecycleBinWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentMovedToRecycleBinWebhookEvent.cs index 0940a899c63d..741d703fe411 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentMovedToRecycleBinWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentMovedToRecycleBinWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when content is moved to the recycle bin, using the legacy payload format. +/// [WebhookEvent("Content Moved to Recycle Bin", Constants.WebhookEvents.Types.Content)] public class LegacyContentMovedToRecycleBinWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyContentMovedToRecycleBinWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -22,8 +32,10 @@ public LegacyContentMovedToRecycleBinWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentMovedToRecycleBin; + /// public override object ConvertNotificationToRequestPayload(ContentMovedToRecycleBinNotification notification) => notification.MoveInfoCollection; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentMovedWebhookEvent.cs index 247790529d35..3e6a222e0c74 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentMovedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentMovedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when content is moved, using the legacy payload format. +/// [WebhookEvent("Content Moved", Constants.WebhookEvents.Types.Content)] public class LegacyContentMovedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyContentMovedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -22,8 +32,10 @@ public LegacyContentMovedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentMoved; + /// public override object ConvertNotificationToRequestPayload(ContentMovedNotification notification) => notification.MoveInfoCollection; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentPublishedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentPublishedWebhookEvent.cs index 5ffb82b18169..a5a5bdcabbff 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentPublishedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentPublishedWebhookEvent.cs @@ -10,12 +10,24 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when content is published, using the legacy payload format. +/// [WebhookEvent("Content Published", Constants.WebhookEvents.Types.Content)] public class LegacyContentPublishedWebhookEvent : WebhookEventContentBase { private readonly IApiContentBuilder _apiContentBuilder; private readonly IPublishedContentCache _publishedContentCache; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The API content builder. + /// The published content cache. public LegacyContentPublishedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -33,10 +45,13 @@ public LegacyContentPublishedWebhookEvent( _publishedContentCache = publishedContentCache; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentPublish; + /// protected override IEnumerable GetEntitiesFromNotification(ContentPublishedNotification notification) => notification.PublishedEntities; + /// protected override object? ConvertEntityToRequestPayload(IContent entity) { IPublishedContent? publishedContent = _publishedContentCache.GetById(entity.Key); diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentRolledBackWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentRolledBackWebhookEvent.cs index b97229e33687..4b245be9b7e0 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentRolledBackWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentRolledBackWebhookEvent.cs @@ -10,12 +10,24 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when content is rolled back, using the legacy payload format. +/// [WebhookEvent("Content Rolled Back", Constants.WebhookEvents.Types.Content)] public class LegacyContentRolledBackWebhookEvent : WebhookEventContentBase { private readonly IPublishedContentCache _contentCache; private readonly IApiContentBuilder _apiContentBuilder; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The published content cache. + /// The API content builder. public LegacyContentRolledBackWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -33,11 +45,14 @@ public LegacyContentRolledBackWebhookEvent( _apiContentBuilder = apiContentBuilder; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentRolledBack; + /// protected override IEnumerable GetEntitiesFromNotification(ContentRolledBackNotification notification) => new List { notification.Entity }; + /// protected override object? ConvertEntityToRequestPayload(IContent entity) { // Get preview/saved version of content for a rollback diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentSavedBlueprintWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentSavedBlueprintWebhookEvent.cs index 2d5faf1ef50f..92c939893971 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentSavedBlueprintWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentSavedBlueprintWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a content template (blueprint) is saved, using the legacy payload format. +/// [WebhookEvent("Content Template [Blueprint] Saved", Constants.WebhookEvents.Types.Content)] public class LegacyContentSavedBlueprintWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyContentSavedBlueprintWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -23,11 +33,14 @@ public LegacyContentSavedBlueprintWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentSavedBlueprint; + /// protected override IEnumerable GetEntitiesFromNotification(ContentSavedBlueprintNotification notification) => new List { notification.SavedBlueprint }; + /// protected override object ConvertEntityToRequestPayload(IContent entity) => entity; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentSavedWebhookEvent.cs index 4e7ff83e547d..0447172201e7 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentSavedWebhookEvent.cs @@ -10,12 +10,24 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when content is saved, using the legacy payload format. +/// [WebhookEvent("Content Saved", Constants.WebhookEvents.Types.Content)] public class LegacyContentSavedWebhookEvent : WebhookEventContentBase { private readonly IApiContentBuilder _apiContentBuilder; private readonly IPublishedContentCache _contentCache; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The API content builder. + /// The published content cache. public LegacyContentSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -33,11 +45,14 @@ public LegacyContentSavedWebhookEvent( _contentCache = contentCache; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentSaved; + /// protected override IEnumerable GetEntitiesFromNotification(ContentSavedNotification notification) => notification.SavedEntities; + /// protected override object? ConvertEntityToRequestPayload(IContent entity) { // Get preview/saved version of content diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentSortedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentSortedWebhookEvent.cs index 79d4c1fd0c93..dae8fdb24454 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentSortedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentSortedWebhookEvent.cs @@ -10,12 +10,24 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when content is sorted, using the legacy payload format. +/// [WebhookEvent("Content Sorted", Constants.WebhookEvents.Types.Content)] public class LegacyContentSortedWebhookEvent : WebhookEventBase { private readonly IPublishedContentCache _contentCache; private readonly IApiContentBuilder _apiContentBuilder; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The published content cache. + /// The API content builder. public LegacyContentSortedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -33,8 +45,10 @@ public LegacyContentSortedWebhookEvent( _apiContentBuilder = apiContentBuilder; } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentSorted; + /// public override object ConvertNotificationToRequestPayload(ContentSortedNotification notification) { var sortedEntities = new List(); diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentUnpublishedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentUnpublishedWebhookEvent.cs index e0b376025c84..3cba189527a7 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentUnpublishedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Content/LegacyContentUnpublishedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when content is unpublished, using the legacy payload format. +/// [WebhookEvent("Content Unpublished", Constants.WebhookEvents.Types.Content)] public class LegacyContentUnpublishedWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyContentUnpublishedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -23,9 +33,12 @@ public LegacyContentUnpublishedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ContentUnpublish; + /// protected override IEnumerable GetEntitiesFromNotification(ContentUnpublishedNotification notification) => notification.UnpublishedEntities; + /// protected override object ConvertEntityToRequestPayload(IContent entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeChangedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeChangedWebhookEvent.cs index fe563b6e735e..8252d5661538 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeChangedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeChangedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a document type is changed, using the legacy payload format. +/// [WebhookEvent("Document Type Changed")] public class LegacyDocumentTypeChangedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyDocumentTypeChangedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyDocumentTypeChangedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DocumentTypeChanged; + /// public override object ConvertNotificationToRequestPayload(ContentTypeChangedNotification notification) => notification.Changes; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeDeletedWebhookEvent.cs index 3be9de263fe4..9d9ec5f61244 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a document type is deleted, using the legacy payload format. +/// [WebhookEvent("Document Type Deleted")] public class LegacyDocumentTypeDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyDocumentTypeDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyDocumentTypeDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DocumentTypeDeleted; + /// public override object ConvertNotificationToRequestPayload(ContentTypeDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeMovedWebhookEvent.cs index 237f4f4c7672..998e7a535c4f 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeMovedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeMovedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a document type is moved, using the legacy payload format. +/// [WebhookEvent("Document Type Moved")] public class LegacyDocumentTypeMovedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyDocumentTypeMovedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyDocumentTypeMovedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DocumentTypeMoved; + /// public override object ConvertNotificationToRequestPayload(ContentTypeMovedNotification notification) => notification.MoveInfoCollection; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeSavedWebhookEvent.cs index c1a4b8c54c97..814718166242 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyDocumentTypeSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a document type is saved, using the legacy payload format. +/// [WebhookEvent("Document Type Saved")] public class LegacyDocumentTypeSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyDocumentTypeSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyDocumentTypeSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DocumentTypeSaved; + /// public override object ConvertNotificationToRequestPayload(ContentTypeSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeChangedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeChangedWebhookEvent.cs index 410cc691dd4b..5fc385394a9b 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeChangedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeChangedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a media type is changed, using the legacy payload format. +/// [WebhookEvent("Media Type Changed")] public class LegacyMediaTypeChangedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMediaTypeChangedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyMediaTypeChangedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaTypeChanged; + /// public override object ConvertNotificationToRequestPayload(MediaTypeChangedNotification notification) => notification.Changes; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeDeletedWebhookEvent.cs index 56f59185a280..02c0780de4e8 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a media type is deleted, using the legacy payload format. +/// [WebhookEvent("Media Type Deleted")] public class LegacyMediaTypeDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMediaTypeDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyMediaTypeDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaTypeDeleted; + /// public override object ConvertNotificationToRequestPayload(MediaTypeDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeMovedWebhookEvent.cs index 4f7153517c23..43cd470b43be 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeMovedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeMovedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a media type is moved, using the legacy payload format. +/// [WebhookEvent("Media Type Moved")] public class LegacyMediaTypeMovedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMediaTypeMovedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyMediaTypeMovedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaTypeMoved; + /// public override object ConvertNotificationToRequestPayload(MediaTypeMovedNotification notification) => notification.MoveInfoCollection; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeSavedWebhookEvent.cs index d2e97e3aa09d..14edb1c32808 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMediaTypeSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a media type is saved, using the legacy payload format. +/// [WebhookEvent("Media Type Saved")] public class LegacyMediaTypeSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMediaTypeSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyMediaTypeSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaTypeSaved; + /// public override object ConvertNotificationToRequestPayload(MediaTypeSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeChangedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeChangedWebhookEvent.cs index d551bed79596..2a285d2a7491 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeChangedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeChangedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a member type is changed, using the legacy payload format. +/// [WebhookEvent("Member Type Changed")] public class LegacyMemberTypeChangedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMemberTypeChangedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyMemberTypeChangedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberTypeChanged; + /// public override object ConvertNotificationToRequestPayload(MemberTypeChangedNotification notification) => notification.Changes; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeDeletedWebhookEvent.cs index cca712e1ce79..bc3ecdef267e 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a member type is deleted, using the legacy payload format. +/// [WebhookEvent("Member Type Deleted")] public class LegacyMemberTypeDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMemberTypeDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyMemberTypeDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberTypeDeleted; + /// public override object ConvertNotificationToRequestPayload(MemberTypeDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeMovedWebhookEvent.cs index ae5bd2cf66cb..15eaf2afa272 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeMovedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeMovedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a member type is moved, using the legacy payload format. +/// [WebhookEvent("Member Type Moved")] public class LegacyMemberTypeMovedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMemberTypeMovedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyMemberTypeMovedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberTypeMoved; + /// public override object ConvertNotificationToRequestPayload(MemberTypeMovedNotification notification) => notification.MoveInfoCollection; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeSavedWebhookEvent.cs index 5eb60eafa844..091b03fb5a9c 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/ContentType/LegacyMemberTypeSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a member type is saved, using the legacy payload format. +/// [WebhookEvent("Member Type Saved")] public class LegacyMemberTypeSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMemberTypeSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyMemberTypeSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberTypeSaved; + /// public override object ConvertNotificationToRequestPayload(MemberTypeSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/DataType/LegacyDataTypeDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/DataType/LegacyDataTypeDeletedWebhookEvent.cs index 0bb7b040312e..b8fe751aaecc 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/DataType/LegacyDataTypeDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/DataType/LegacyDataTypeDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a data type is deleted, using the legacy payload format. +/// [WebhookEvent("Data Type Deleted")] public class LegacyDataTypeDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyDataTypeDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyDataTypeDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DataTypeDeleted; + /// public override object ConvertNotificationToRequestPayload(DataTypeDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/DataType/LegacyDataTypeMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/DataType/LegacyDataTypeMovedWebhookEvent.cs index 164065e6db32..812d867ef7c8 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/DataType/LegacyDataTypeMovedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/DataType/LegacyDataTypeMovedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a data type is moved, using the legacy payload format. +/// [WebhookEvent("Data Type Moved")] public class LegacyDataTypeMovedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyDataTypeMovedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyDataTypeMovedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DataTypeMoved; + /// public override object ConvertNotificationToRequestPayload(DataTypeMovedNotification notification) => notification.MoveInfoCollection; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/DataType/LegacyDataTypeSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/DataType/LegacyDataTypeSavedWebhookEvent.cs index 8a4ae1cdb725..8f26b9e6297e 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/DataType/LegacyDataTypeSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/DataType/LegacyDataTypeSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a data type is saved, using the legacy payload format. +/// [WebhookEvent("Data Type Saved")] public class LegacyDataTypeSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyDataTypeSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyDataTypeSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DataTypeSaved; + /// public override object ConvertNotificationToRequestPayload(DataTypeSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Dictionary/LegacyDictionaryItemDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Dictionary/LegacyDictionaryItemDeletedWebhookEvent.cs index 926421da049a..d53436b67a83 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Dictionary/LegacyDictionaryItemDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Dictionary/LegacyDictionaryItemDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a dictionary item is deleted, using the legacy payload format. +/// [WebhookEvent("Dictionary Item Deleted")] public class LegacyDictionaryItemDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyDictionaryItemDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyDictionaryItemDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DictionaryItemDeleted; + /// public override object ConvertNotificationToRequestPayload(DictionaryItemDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Dictionary/LegacyDictionaryItemSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Dictionary/LegacyDictionaryItemSavedWebhookEvent.cs index 8c39b58e1a86..a37b70f402ae 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Dictionary/LegacyDictionaryItemSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Dictionary/LegacyDictionaryItemSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a dictionary item is saved, using the legacy payload format. +/// [WebhookEvent("Dictionary Item Saved")] public class LegacyDictionaryItemSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyDictionaryItemSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyDictionaryItemSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DictionaryItemSaved; + /// public override object ConvertNotificationToRequestPayload(DictionaryItemSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Domain/LegacyDomainDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Domain/LegacyDomainDeletedWebhookEvent.cs index 6187e3ecdf9a..e032d8087686 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Domain/LegacyDomainDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Domain/LegacyDomainDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a domain is deleted, using the legacy payload format. +/// [WebhookEvent("Domain Deleted")] public class LegacyDomainDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyDomainDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyDomainDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DomainDeleted; + /// public override object ConvertNotificationToRequestPayload(DomainDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Domain/LegacyDomainSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Domain/LegacyDomainSavedWebhookEvent.cs index 5a39d882b81a..f95c4543bcfa 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Domain/LegacyDomainSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Domain/LegacyDomainSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a domain is saved, using the legacy payload format. +/// [WebhookEvent("Domain Saved")] public class LegacyDomainSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyDomainSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyDomainSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.DomainSaved; + /// public override object ConvertNotificationToRequestPayload(DomainSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyPartialViewDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyPartialViewDeletedWebhookEvent.cs index 02e7a1e14204..5374e335fc62 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyPartialViewDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyPartialViewDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a partial view is deleted, using the legacy payload format. +/// [WebhookEvent("Partial View Deleted")] public class LegacyPartialViewDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyPartialViewDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyPartialViewDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.PartialViewDeleted; + /// public override object ConvertNotificationToRequestPayload(PartialViewDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyPartialViewSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyPartialViewSavedWebhookEvent.cs index 751d4ab391b8..1e4894dc1b8f 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyPartialViewSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyPartialViewSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a partial view is saved, using the legacy payload format. +/// [WebhookEvent("Partial View Saved")] public class LegacyPartialViewSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyPartialViewSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyPartialViewSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.PartialViewSaved; + /// public override object ConvertNotificationToRequestPayload(PartialViewSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyScriptDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyScriptDeletedWebhookEvent.cs index 16503c81ea4d..89ce77f4c782 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyScriptDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyScriptDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a script is deleted, using the legacy payload format. +/// [WebhookEvent("Script Deleted")] public class LegacyScriptDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyScriptDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyScriptDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ScriptDeleted; + /// public override object ConvertNotificationToRequestPayload(ScriptDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyScriptSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyScriptSavedWebhookEvent.cs index c16a2f48f60b..fc0bfbea280f 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyScriptSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyScriptSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a script is saved, using the legacy payload format. +/// [WebhookEvent("Script Saved")] public class LegacyScriptSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyScriptSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyScriptSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ScriptSaved; + /// public override object ConvertNotificationToRequestPayload(ScriptSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyStylesheetDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyStylesheetDeletedWebhookEvent.cs index 2f5c3c3990f3..9bed801bc965 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyStylesheetDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyStylesheetDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a stylesheet is deleted, using the legacy payload format. +/// [WebhookEvent("Stylesheet Deleted")] public class LegacyStylesheetDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyStylesheetDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyStylesheetDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.StylesheetDeleted; + /// public override object ConvertNotificationToRequestPayload(StylesheetDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyStylesheetSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyStylesheetSavedWebhookEvent.cs index 9ddc79780cd1..4414e81b8288 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyStylesheetSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyStylesheetSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a stylesheet is saved, using the legacy payload format. +/// [WebhookEvent("Stylesheet Saved")] public class LegacyStylesheetSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyStylesheetSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyStylesheetSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.StylesheetSaved; + /// public override object ConvertNotificationToRequestPayload(StylesheetSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyTemplateDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyTemplateDeletedWebhookEvent.cs index 95a71dd1ff94..421341edbea2 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyTemplateDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyTemplateDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a template is deleted, using the legacy payload format. +/// [WebhookEvent("Template Deleted")] public class LegacyTemplateDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyTemplateDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyTemplateDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.TemplateDeleted; + /// public override object ConvertNotificationToRequestPayload(TemplateDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyTemplateSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyTemplateSavedWebhookEvent.cs index 133d4685c9c6..41501d2b16ac 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyTemplateSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/File/LegacyTemplateSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a template is saved, using the legacy payload format. +/// [WebhookEvent("Template Saved")] public class LegacyTemplateSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyTemplateSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyTemplateSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.TemplateSaved; + /// public override object ConvertNotificationToRequestPayload(TemplateSavedNotification notification) { // Create a new anonymous object with the properties we want diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/HealthCheck/LegacyHealthCheckCompletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/HealthCheck/LegacyHealthCheckCompletedWebhookEvent.cs index 9291259bc73e..477d721f5b37 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/HealthCheck/LegacyHealthCheckCompletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/HealthCheck/LegacyHealthCheckCompletedWebhookEvent.cs @@ -6,15 +6,27 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a health check is completed, using the legacy payload format. +/// [WebhookEvent("Health Check Completed")] public class LegacyHealthCheckCompletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyHealthCheckCompletedWebhookEvent(IWebhookFiringService webhookFiringService, IWebhookService webhookService, IOptionsMonitor webhookSettings, IServerRoleAccessor serverRoleAccessor) : base(webhookFiringService, webhookService, webhookSettings, serverRoleAccessor) { } + /// public override string Alias => Constants.WebhookEvents.Aliases.HealthCheckCompleted; + /// public override object ConvertNotificationToRequestPayload(HealthCheckCompletedNotification notification) => new { diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Language/LegacyLanguageDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Language/LegacyLanguageDeletedWebhookEvent.cs index 43750f1cae85..6af4f647830b 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Language/LegacyLanguageDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Language/LegacyLanguageDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a language is deleted, using the legacy payload format. +/// [WebhookEvent("Language Deleted")] public class LegacyLanguageDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyLanguageDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyLanguageDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.LanguageDeleted; + /// public override object ConvertNotificationToRequestPayload(LanguageDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Language/LegacyLanguageSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Language/LegacyLanguageSavedWebhookEvent.cs index 4173efab625d..5b1814349740 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Language/LegacyLanguageSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Language/LegacyLanguageSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a language is saved, using the legacy payload format. +/// [WebhookEvent("Language Saved")] public class LegacyLanguageSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyLanguageSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyLanguageSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.LanguageSaved; + /// public override object ConvertNotificationToRequestPayload(LanguageSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaDeletedWebhookEvent.cs index 6e46e98df3b4..31df25da4f40 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaDeletedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when media is deleted, using the legacy payload format. +/// [WebhookEvent("Media Deleted", Constants.WebhookEvents.Types.Media)] public class LegacyMediaDeletedWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMediaDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -23,9 +33,12 @@ public LegacyMediaDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaDelete; + /// protected override IEnumerable GetEntitiesFromNotification(MediaDeletedNotification notification) => notification.DeletedEntities; + /// protected override object ConvertEntityToRequestPayload(IMedia entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaEmptiedRecycleBinWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaEmptiedRecycleBinWebhookEvent.cs index a8f2cfd86be1..093ec64f0bde 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaEmptiedRecycleBinWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaEmptiedRecycleBinWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when the media recycle bin is emptied, using the legacy payload format. +/// [WebhookEvent("Media Recycle Bin Emptied", Constants.WebhookEvents.Types.Media)] public class LegacyMediaEmptiedRecycleBinWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMediaEmptiedRecycleBinWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -23,9 +33,12 @@ public LegacyMediaEmptiedRecycleBinWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaEmptiedRecycleBin; + /// protected override IEnumerable GetEntitiesFromNotification(MediaEmptiedRecycleBinNotification notification) => notification.DeletedEntities; + /// protected override object ConvertEntityToRequestPayload(IMedia entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaMovedToRecycleBinWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaMovedToRecycleBinWebhookEvent.cs index 0c3f1ffcae5e..3522ad95c1f9 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaMovedToRecycleBinWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaMovedToRecycleBinWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when media is moved to the recycle bin, using the legacy payload format. +/// [WebhookEvent("Media Moved to Recycle Bin", Constants.WebhookEvents.Types.Media)] public class LegacyMediaMovedToRecycleBinWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMediaMovedToRecycleBinWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -23,9 +33,12 @@ public LegacyMediaMovedToRecycleBinWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaMovedToRecycleBin; + /// protected override IEnumerable GetEntitiesFromNotification(MediaMovedToRecycleBinNotification notification) => notification.MoveInfoCollection.Select(x => x.Entity); + /// protected override object ConvertEntityToRequestPayload(IMedia entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaMovedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaMovedWebhookEvent.cs index 670ca90720e5..3746788b6b61 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaMovedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaMovedWebhookEvent.cs @@ -7,9 +7,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when media is moved, using the legacy payload format. +/// [WebhookEvent("Media Moved", Constants.WebhookEvents.Types.Media)] public class LegacyMediaMovedWebhookEvent : WebhookEventContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMediaMovedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -23,9 +33,12 @@ public LegacyMediaMovedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaMoved; + /// protected override IEnumerable GetEntitiesFromNotification(MediaMovedNotification notification) => notification.MoveInfoCollection.Select(x => x.Entity); + /// protected override object ConvertEntityToRequestPayload(IMedia entity) => new DefaultPayloadModel { Id = entity.Key }; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaSavedWebhookEvent.cs index 5774bfd7d143..ed8541c312c2 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Media/LegacyMediaSavedWebhookEvent.cs @@ -10,12 +10,24 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when media is saved, using the legacy payload format. +/// [WebhookEvent("Media Saved", Constants.WebhookEvents.Types.Media)] public class LegacyMediaSavedWebhookEvent : WebhookEventContentBase { private readonly IPublishedMediaCache _mediaCache; private readonly IApiMediaBuilder _apiMediaBuilder; + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. + /// The published media cache. + /// The API media builder. public LegacyMediaSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -33,10 +45,13 @@ public LegacyMediaSavedWebhookEvent( _apiMediaBuilder = apiMediaBuilder; } + /// public override string Alias => Constants.WebhookEvents.Aliases.MediaSave; + /// protected override IEnumerable GetEntitiesFromNotification(MediaSavedNotification notification) => notification.SavedEntities; + /// protected override object? ConvertEntityToRequestPayload(IMedia entity) { IPublishedContent? publishedContent = _mediaCache.GetById(entity.Key); diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyAssignedMemberRolesWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyAssignedMemberRolesWebhookEvent.cs index fb1be0c4e50a..da32d4a3b94e 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyAssignedMemberRolesWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyAssignedMemberRolesWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when member roles are assigned, using the legacy payload format. +/// [WebhookEvent("Member Roles Assigned")] public class LegacyAssignedMemberRolesWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyAssignedMemberRolesWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,5 +28,6 @@ public LegacyAssignedMemberRolesWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.AssignedMemberRoles; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyExportedMemberWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyExportedMemberWebhookEvent.cs index 189a5f535b52..d63718294591 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyExportedMemberWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyExportedMemberWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a member is exported, using the legacy payload format. +/// [WebhookEvent("Member Exported")] public class LegacyExportedMemberWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyExportedMemberWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyExportedMemberWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.ExportedMember; + /// public override object ConvertNotificationToRequestPayload(ExportedMemberNotification notification) { // No need to return the original member in the notification as well diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberDeletedWebhookEvent.cs index 44a671b05cec..8dcf2eafb94f 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a member is deleted, using the legacy payload format. +/// [WebhookEvent("Member Deleted")] public class LegacyMemberDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMemberDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyMemberDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberDeleted; + /// public override object ConvertNotificationToRequestPayload(MemberDeletedNotification notification) { var result = notification.DeletedEntities.Select(entity => new diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberGroupDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberGroupDeletedWebhookEvent.cs index 19096e58d009..712044e42991 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberGroupDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberGroupDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a member group is deleted, using the legacy payload format. +/// [WebhookEvent("Member Group Deleted")] public class LegacyMemberGroupDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMemberGroupDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyMemberGroupDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberGroupDeleted; + /// public override object ConvertNotificationToRequestPayload(MemberGroupDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberGroupSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberGroupSavedWebhookEvent.cs index 11781be4c560..09bb828ae441 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberGroupSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberGroupSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a member group is saved, using the legacy payload format. +/// [WebhookEvent("Member Group Saved")] public class LegacyMemberGroupSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMemberGroupSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyMemberGroupSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberGroupSaved; + /// public override object ConvertNotificationToRequestPayload(MemberGroupSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberSavedWebhookEvent.cs index 0fd7599bf7d9..18c0fa88be9b 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyMemberSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a member is saved, using the legacy payload format. +/// [WebhookEvent("Member Saved")] public class LegacyMemberSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyMemberSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyMemberSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.MemberSaved; + /// public override object ConvertNotificationToRequestPayload(MemberSavedNotification notification) { var result = notification.SavedEntities.Select(entity => new diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyRemovedMemberRolesWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyRemovedMemberRolesWebhookEvent.cs index cb443799df0b..aaf09d299df3 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyRemovedMemberRolesWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Member/LegacyRemovedMemberRolesWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when member roles are removed, using the legacy payload format. +/// [WebhookEvent("Member Roles Removed")] public class LegacyRemovedMemberRolesWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyRemovedMemberRolesWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,5 +28,6 @@ public LegacyRemovedMemberRolesWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.RemovedMemberRoles; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Package/LegacyImportedPackageWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Package/LegacyImportedPackageWebhookEvent.cs index 16f1a8b7d1bb..0cae36c381ff 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Package/LegacyImportedPackageWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Package/LegacyImportedPackageWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a package is imported, using the legacy payload format. +/// [WebhookEvent("Package Imported")] public class LegacyImportedPackageWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyImportedPackageWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,5 +28,6 @@ public LegacyImportedPackageWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.PackageImported; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/PublicAccess/LegacyPublicAccessEntryDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/PublicAccess/LegacyPublicAccessEntryDeletedWebhookEvent.cs index f857ed41e816..503bab90d674 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/PublicAccess/LegacyPublicAccessEntryDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/PublicAccess/LegacyPublicAccessEntryDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a public access entry is deleted, using the legacy payload format. +/// [WebhookEvent("Public Access Entry Deleted")] public class LegacyPublicAccessEntryDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyPublicAccessEntryDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,7 +28,9 @@ public LegacyPublicAccessEntryDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.PublicAccessEntryDeleted; + /// public override object ConvertNotificationToRequestPayload(PublicAccessEntryDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/PublicAccess/LegacyPublicAccessEntrySavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/PublicAccess/LegacyPublicAccessEntrySavedWebhookEvent.cs index 95c0240b2dd9..5fb82d9f777b 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/PublicAccess/LegacyPublicAccessEntrySavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/PublicAccess/LegacyPublicAccessEntrySavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a public access entry is saved, using the legacy payload format. +/// [WebhookEvent("Public Access Entry Saved")] public class LegacyPublicAccessEntrySavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyPublicAccessEntrySavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyPublicAccessEntrySavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.PublicAccessEntrySaved; + /// public override object ConvertNotificationToRequestPayload(PublicAccessEntrySavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Relation/LegacyRelationDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Relation/LegacyRelationDeletedWebhookEvent.cs index a07e1a9f8e5c..fcc4b04bdba6 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Relation/LegacyRelationDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Relation/LegacyRelationDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a relation is deleted, using the legacy payload format. +/// [WebhookEvent("Relation Deleted")] public class LegacyRelationDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyRelationDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyRelationDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.RelationDeleted; + /// public override object ConvertNotificationToRequestPayload(RelationDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/Relation/LegacyRelationSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/Relation/LegacyRelationSavedWebhookEvent.cs index 90d3b89caf06..d71f794b2706 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/Relation/LegacyRelationSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/Relation/LegacyRelationSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a relation is saved, using the legacy payload format. +/// [WebhookEvent("Relation Saved")] public class LegacyRelationSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyRelationSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyRelationSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.RelationSaved; + /// public override object ConvertNotificationToRequestPayload(RelationSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/RelationType/LegacyRelationTypeDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/RelationType/LegacyRelationTypeDeletedWebhookEvent.cs index 0ddc21ebdb43..d79647a91724 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/RelationType/LegacyRelationTypeDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/RelationType/LegacyRelationTypeDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a relation type is deleted, using the legacy payload format. +/// [WebhookEvent("Relation Type Deleted")] public class LegacyRelationTypeDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyRelationTypeDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,9 +28,10 @@ public LegacyRelationTypeDeletedWebhookEvent( { } - + /// public override string Alias => Constants.WebhookEvents.Aliases.RelationTypeDeleted; + /// public override object ConvertNotificationToRequestPayload(RelationTypeDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/RelationType/LegacyRelationTypeSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/RelationType/LegacyRelationTypeSavedWebhookEvent.cs index 6876dc66533a..6654d7499ed2 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/RelationType/LegacyRelationTypeSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/RelationType/LegacyRelationTypeSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a relation type is saved, using the legacy payload format. +/// [WebhookEvent("Relation Type Saved")] public class LegacyRelationTypeSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyRelationTypeSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyRelationTypeSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.RelationTypeSaved; + /// public override object ConvertNotificationToRequestPayload(RelationTypeSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyAssignedUserGroupPermissionsWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyAssignedUserGroupPermissionsWebhookEvent.cs index da2bbac6927a..2dfec459ff67 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyAssignedUserGroupPermissionsWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyAssignedUserGroupPermissionsWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when user group permissions are assigned, using the legacy payload format. +/// [WebhookEvent("User Group Permissions Assigned")] public class LegacyAssignedUserGroupPermissionsWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyAssignedUserGroupPermissionsWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyAssignedUserGroupPermissionsWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.AssignedUserGroupPermissions; + /// public override object ConvertNotificationToRequestPayload(AssignedUserGroupPermissionsNotification notification) => notification.EntityPermissions; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserDeletedWebhookEvent.cs index 0d6e26845406..6577d40659a1 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user is deleted, using the legacy payload format. +/// [WebhookEvent("User Deleted")] public class LegacyUserDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyUserDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserDeleted; + /// public override object ConvertNotificationToRequestPayload(UserDeletedNotification notification) { var result = notification.DeletedEntities.Select(entity => new diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserForgotPasswordRequestedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserForgotPasswordRequestedWebhookEvent.cs index 8e01f63df047..42a706a17f74 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserForgotPasswordRequestedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserForgotPasswordRequestedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user requests a forgot password reset, using the legacy payload format. +/// [WebhookEvent("User Forgot Password Requested")] public class LegacyUserForgotPasswordRequestedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserForgotPasswordRequestedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,6 +28,6 @@ public LegacyUserForgotPasswordRequestedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserForgotPasswordRequested; - } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserGroupDeletedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserGroupDeletedWebhookEvent.cs index 336921bda2eb..44e4842e8aaf 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserGroupDeletedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserGroupDeletedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user group is deleted, using the legacy payload format. +/// [WebhookEvent("User Group Deleted")] public class LegacyUserGroupDeletedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserGroupDeletedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,7 +28,9 @@ public LegacyUserGroupDeletedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserGroupDeleted; + /// public override object ConvertNotificationToRequestPayload(UserGroupDeletedNotification notification) => notification.DeletedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserGroupSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserGroupSavedWebhookEvent.cs index 2131596be470..9da57e9b5773 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserGroupSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserGroupSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user group is saved, using the legacy payload format. +/// [WebhookEvent("User Group Saved")] public class LegacyUserGroupSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserGroupSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,7 +28,9 @@ public LegacyUserGroupSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserGroupSaved; + /// public override object ConvertNotificationToRequestPayload(UserGroupSavedNotification notification) => notification.SavedEntities; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLockedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLockedWebhookEvent.cs index 4986a312a6a2..100296f27017 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLockedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLockedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user is locked, using the legacy payload format. +/// [WebhookEvent("User Locked")] public class LegacyUserLockedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserLockedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,5 +28,6 @@ public LegacyUserLockedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserLocked; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLoginFailedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLoginFailedWebhookEvent.cs index 9105d1739384..026aadcb766a 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLoginFailedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLoginFailedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user login fails, using the legacy payload format. +/// [WebhookEvent("User Login Failed")] public class LegacyUserLoginFailedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserLoginFailedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,5 +28,6 @@ public LegacyUserLoginFailedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserLoginFailed; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLoginRequiresVerificationWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLoginRequiresVerificationWebhookEvent.cs index 936368cdaf3e..dee5aaf0bff4 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLoginRequiresVerificationWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLoginRequiresVerificationWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user login requires verification, using the legacy payload format. +/// [WebhookEvent("User Login Requires Verification")] public class LegacyUserLoginRequiresVerificationWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserLoginRequiresVerificationWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,6 +28,6 @@ public LegacyUserLoginRequiresVerificationWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserLoginRequiresVerification; - } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLoginSuccessWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLoginSuccessWebhookEvent.cs index c7274dc5b303..32c4db5811fd 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLoginSuccessWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLoginSuccessWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user successfully logs in, using the legacy payload format. +/// [WebhookEvent("User Login Success")] public class LegacyUserLoginSuccessWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserLoginSuccessWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,5 +28,6 @@ public LegacyUserLoginSuccessWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserLoginSuccess; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLogoutSuccessWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLogoutSuccessWebhookEvent.cs index 0cfb0a91fb73..d2908b8eac58 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLogoutSuccessWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserLogoutSuccessWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user successfully logs out, using the legacy payload format. +/// [WebhookEvent("User Logout Success")] public class LegacyUserLogoutSuccessWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserLogoutSuccessWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,5 +28,6 @@ public LegacyUserLogoutSuccessWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserLogoutSuccess; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserPasswordChangedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserPasswordChangedWebhookEvent.cs index 2a0272161433..c23f5c2d5017 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserPasswordChangedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserPasswordChangedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user's password is changed, using the legacy payload format. +/// [WebhookEvent("User Password Changed")] public class LegacyUserPasswordChangedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserPasswordChangedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,6 +28,6 @@ public LegacyUserPasswordChangedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserPasswordChanged; - } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserPasswordResetWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserPasswordResetWebhookEvent.cs index 05ca5aac1a67..c2799f9c5fcf 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserPasswordResetWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserPasswordResetWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user's password is reset, using the legacy payload format. +/// [WebhookEvent("User Password Reset")] public class LegacyUserPasswordResetWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserPasswordResetWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,5 +28,6 @@ public LegacyUserPasswordResetWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserPasswordReset; } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserSavedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserSavedWebhookEvent.cs index 383119dd622d..6f9cfa82e1d8 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserSavedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserSavedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user is saved, using the legacy payload format. +/// [WebhookEvent("User Saved")] public class LegacyUserSavedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserSavedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,8 +28,10 @@ public LegacyUserSavedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserSaved; + /// public override object ConvertNotificationToRequestPayload(UserSavedNotification notification) { var result = notification.SavedEntities.Select(entity => new diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserTwoFactorRequestedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserTwoFactorRequestedWebhookEvent.cs index a0caf46b43c6..d451dbad065f 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserTwoFactorRequestedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserTwoFactorRequestedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when two-factor authentication is requested for a user, using the legacy payload format. +/// [WebhookEvent("User Two Factor Requested")] public class LegacyUserTwoFactorRequestedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserTwoFactorRequestedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,6 +28,6 @@ public LegacyUserTwoFactorRequestedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserTwoFactorRequested; - } diff --git a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserUnlockedWebhookEvent.cs b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserUnlockedWebhookEvent.cs index c82b300f6fad..e48500d6fe92 100644 --- a/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserUnlockedWebhookEvent.cs +++ b/src/Umbraco.Core/Webhooks/LegacyEvents/User/LegacyUserUnlockedWebhookEvent.cs @@ -6,9 +6,19 @@ namespace Umbraco.Cms.Core.Webhooks.Events; +/// +/// Legacy webhook event that fires when a user is unlocked, using the legacy payload format. +/// [WebhookEvent("User Unlocked")] public class LegacyUserUnlockedWebhookEvent : WebhookEventBase { + /// + /// Initializes a new instance of the class. + /// + /// The webhook firing service. + /// The webhook service. + /// The webhook settings. + /// The server role accessor. public LegacyUserUnlockedWebhookEvent( IWebhookFiringService webhookFiringService, IWebhookService webHookService, @@ -18,5 +28,6 @@ public LegacyUserUnlockedWebhookEvent( { } + /// public override string Alias => Constants.WebhookEvents.Aliases.UserUnlocked; } diff --git a/src/Umbraco.Core/Webhooks/WebhookEventAttribute.cs b/src/Umbraco.Core/Webhooks/WebhookEventAttribute.cs index 3c9015e8bf13..0d0fa18199fd 100644 --- a/src/Umbraco.Core/Webhooks/WebhookEventAttribute.cs +++ b/src/Umbraco.Core/Webhooks/WebhookEventAttribute.cs @@ -1,13 +1,25 @@ -namespace Umbraco.Cms.Core.Webhooks; +namespace Umbraco.Cms.Core.Webhooks; +/// +/// Attribute used to decorate webhook event classes with metadata such as name and event type. +/// [AttributeUsage(AttributeTargets.Class)] public class WebhookEventAttribute : Attribute { + /// + /// Initializes a new instance of the class with the specified name. + /// + /// The friendly name of the webhook event. public WebhookEventAttribute(string name) : this(name, Constants.WebhookEvents.Types.Other) { } + /// + /// Initializes a new instance of the class with the specified name and event type. + /// + /// The friendly name of the webhook event. + /// The type/category of the webhook event. public WebhookEventAttribute(string name, string eventType) { Name = name; diff --git a/src/Umbraco.Core/Webhooks/WebhookEventBase.cs b/src/Umbraco.Core/Webhooks/WebhookEventBase.cs index 138ebc56fdc3..084e0761cab3 100644 --- a/src/Umbraco.Core/Webhooks/WebhookEventBase.cs +++ b/src/Umbraco.Core/Webhooks/WebhookEventBase.cs @@ -10,25 +10,46 @@ namespace Umbraco.Cms.Core.Webhooks; +/// +/// Abstract base class for webhook events that handles notification processing and webhook firing. +/// +/// The type of notification this webhook event handles. public abstract class WebhookEventBase : IWebhookEvent, INotificationAsyncHandler where TNotification : INotification { private readonly IServerRoleAccessor _serverRoleAccessor; + /// public abstract string Alias { get; } + /// public string EventName { get; set; } + /// public string EventType { get; } + /// + /// Gets the webhook firing service used to send webhook requests. + /// protected IWebhookFiringService WebhookFiringService { get; } + /// + /// Gets the webhook service used to retrieve webhook configurations. + /// protected IWebhookService WebhookService { get; } + /// + /// Gets the current webhook settings configuration. + /// protected WebhookSettings WebhookSettings { get; private set; } - - + /// + /// Initializes a new instance of the class. + /// + /// The service responsible for firing webhooks. + /// The service for managing webhook configurations. + /// The webhook settings configuration. + /// The server role accessor to determine the current server role. protected WebhookEventBase( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -73,6 +94,7 @@ public virtual async Task ProcessWebhooks(TNotification notification, IEnumerabl public virtual bool ShouldFireWebhookForNotification(TNotification notificationObject) => true; + /// public async Task HandleAsync(TNotification notification, CancellationToken cancellationToken) { if (WebhookSettings.Enabled is false) diff --git a/src/Umbraco.Core/Webhooks/WebhookEventCollection.cs b/src/Umbraco.Core/Webhooks/WebhookEventCollection.cs index cf939f93aeb3..60984d0d69b7 100644 --- a/src/Umbraco.Core/Webhooks/WebhookEventCollection.cs +++ b/src/Umbraco.Core/Webhooks/WebhookEventCollection.cs @@ -1,9 +1,16 @@ -using Umbraco.Cms.Core.Composing; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.Webhooks; +/// +/// A collection of instances registered in the system. +/// public class WebhookEventCollection : BuilderCollectionBase { + /// + /// Initializes a new instance of the class. + /// + /// A factory function that returns the collection of webhook events. public WebhookEventCollection(Func> items) : base(items) { } diff --git a/src/Umbraco.Core/Webhooks/WebhookEventCollectionBuilder.cs b/src/Umbraco.Core/Webhooks/WebhookEventCollectionBuilder.cs index 1cd6f3dae841..f17dceee47bc 100644 --- a/src/Umbraco.Core/Webhooks/WebhookEventCollectionBuilder.cs +++ b/src/Umbraco.Core/Webhooks/WebhookEventCollectionBuilder.cs @@ -7,10 +7,16 @@ namespace Umbraco.Cms.Core.Webhooks; +/// +/// Builder for the that handles registration of webhook events +/// and their corresponding notification handlers with the dependency injection container. +/// public class WebhookEventCollectionBuilder : SetCollectionBuilderBase { + /// protected override WebhookEventCollectionBuilder This => this; + /// public override void RegisterWith(IServiceCollection services) { // register the collection @@ -21,6 +27,10 @@ public override void RegisterWith(IServiceCollection services) base.RegisterWith(services); } + /// + /// Registers webhook event types and their notification handlers with the service collection. + /// + /// The service collection to register with. private void RegisterTypes(IServiceCollection services) { Type[] types = GetRegisteringTypes(GetTypes()).ToArray(); @@ -49,6 +59,11 @@ private void RegisterTypes(IServiceCollection services) } } + /// + /// Gets the notification type that a webhook event handler handles. + /// + /// The webhook event handler type. + /// The notification type, or null if not found. private Type? GetNotificationType(Type handlerType) => handlerType.TryGetGenericArguments(typeof(INotificationAsyncHandler<>), out Type[]? genericArguments) ? genericArguments.FirstOrDefault(arg => typeof(INotification).IsAssignableFrom(arg)) diff --git a/src/Umbraco.Core/Webhooks/WebhookEventCollectionBuilderCmsExtensions.cs b/src/Umbraco.Core/Webhooks/WebhookEventCollectionBuilderCmsExtensions.cs index 66a5e74857fb..69725de942eb 100644 --- a/src/Umbraco.Core/Webhooks/WebhookEventCollectionBuilderCmsExtensions.cs +++ b/src/Umbraco.Core/Webhooks/WebhookEventCollectionBuilderCmsExtensions.cs @@ -570,9 +570,16 @@ public static WebhookEventCollectionBuilderCms AddUser(this WebhookEventCollecti /// public sealed class WebhookEventCollectionBuilderCmsContent { + /// + /// Initializes a new instance of the class. + /// + /// The webhook event collection builder. internal WebhookEventCollectionBuilderCmsContent(WebhookEventCollectionBuilder builder) => Builder = builder; + /// + /// Gets the underlying webhook event collection builder. + /// internal WebhookEventCollectionBuilder Builder { get; } } @@ -581,9 +588,16 @@ internal WebhookEventCollectionBuilderCmsContent(WebhookEventCollectionBuilder b /// public sealed class WebhookEventCollectionBuilderCmsContentType { + /// + /// Initializes a new instance of the class. + /// + /// The webhook event collection builder. internal WebhookEventCollectionBuilderCmsContentType(WebhookEventCollectionBuilder builder) => Builder = builder; + /// + /// Gets the underlying webhook event collection builder. + /// internal WebhookEventCollectionBuilder Builder { get; } } @@ -592,9 +606,16 @@ internal WebhookEventCollectionBuilderCmsContentType(WebhookEventCollectionBuild /// public sealed class WebhookEventCollectionBuilderCmsMember { + /// + /// Initializes a new instance of the class. + /// + /// The webhook event collection builder. internal WebhookEventCollectionBuilderCmsMember(WebhookEventCollectionBuilder builder) => Builder = builder; + /// + /// Gets the underlying webhook event collection builder. + /// internal WebhookEventCollectionBuilder Builder { get; } } @@ -603,9 +624,16 @@ internal WebhookEventCollectionBuilderCmsMember(WebhookEventCollectionBuilder bu /// public sealed class WebhookEventCollectionBuilderCmsFile { + /// + /// Initializes a new instance of the class. + /// + /// The webhook event collection builder. internal WebhookEventCollectionBuilderCmsFile(WebhookEventCollectionBuilder builder) => Builder = builder; + /// + /// Gets the underlying webhook event collection builder. + /// internal WebhookEventCollectionBuilder Builder { get; } } @@ -614,9 +642,16 @@ internal WebhookEventCollectionBuilderCmsFile(WebhookEventCollectionBuilder buil /// public sealed class WebhookEventCollectionBuilderCmsUser { + /// + /// Initializes a new instance of the class. + /// + /// The webhook event collection builder. internal WebhookEventCollectionBuilderCmsUser(WebhookEventCollectionBuilder builder) => Builder = builder; + /// + /// Gets the underlying webhook event collection builder. + /// internal WebhookEventCollectionBuilder Builder { get; } } } diff --git a/src/Umbraco.Core/Webhooks/WebhookEventCollectionBuilderExtensions.cs b/src/Umbraco.Core/Webhooks/WebhookEventCollectionBuilderExtensions.cs index 8dfc24aa0d84..39519263ff26 100644 --- a/src/Umbraco.Core/Webhooks/WebhookEventCollectionBuilderExtensions.cs +++ b/src/Umbraco.Core/Webhooks/WebhookEventCollectionBuilderExtensions.cs @@ -64,9 +64,16 @@ public static WebhookEventCollectionBuilder AddCms(this WebhookEventCollectionBu /// public sealed class WebhookEventCollectionBuilderCms { + /// + /// Initializes a new instance of the class. + /// + /// The webhook event collection builder. internal WebhookEventCollectionBuilderCms(WebhookEventCollectionBuilder builder) => Builder = builder; + /// + /// Gets the underlying webhook event collection builder. + /// internal WebhookEventCollectionBuilder Builder { get; } } } diff --git a/src/Umbraco.Core/Webhooks/WebhookEventContentBase.cs b/src/Umbraco.Core/Webhooks/WebhookEventContentBase.cs index e022f6c0a58b..9956e8d0b191 100644 --- a/src/Umbraco.Core/Webhooks/WebhookEventContentBase.cs +++ b/src/Umbraco.Core/Webhooks/WebhookEventContentBase.cs @@ -8,10 +8,23 @@ namespace Umbraco.Cms.Core.Webhooks; +/// +/// Abstract base class for webhook events that handle content-based notifications, +/// providing filtering by content type and per-entity webhook firing. +/// +/// The type of notification this webhook event handles. +/// The type of content entity associated with the notification. public abstract class WebhookEventContentBase : WebhookEventBase where TNotification : INotification where TEntity : IContentBase { + /// + /// Initializes a new instance of the class. + /// + /// The service responsible for firing webhooks. + /// The service for managing webhook configurations. + /// The webhook settings configuration. + /// The server role accessor to determine the current server role. protected WebhookEventContentBase( IWebhookFiringService webhookFiringService, IWebhookService webhookService, @@ -21,6 +34,7 @@ protected WebhookEventContentBase( { } + /// public override async Task ProcessWebhooks(TNotification notification, IEnumerable webhooks, CancellationToken cancellationToken) { foreach (IWebhook webhook in webhooks) @@ -42,7 +56,17 @@ public override async Task ProcessWebhooks(TNotification notification, IEnumerab } } + /// + /// Extracts the content entities from the notification. + /// + /// The notification containing the entities. + /// An enumerable of content entities from the notification. protected abstract IEnumerable GetEntitiesFromNotification(TNotification notification); + /// + /// Converts a content entity to the webhook request payload. + /// + /// The content entity to convert. + /// The payload object to be sent in the webhook request. protected abstract object? ConvertEntityToRequestPayload(TEntity entity); } diff --git a/src/Umbraco.Core/Webhooks/WebhookPayloadType.cs b/src/Umbraco.Core/Webhooks/WebhookPayloadType.cs index c908ddaea135..a640d6783823 100644 --- a/src/Umbraco.Core/Webhooks/WebhookPayloadType.cs +++ b/src/Umbraco.Core/Webhooks/WebhookPayloadType.cs @@ -1,5 +1,8 @@ namespace Umbraco.Cms.Core.Webhooks; +/// +/// Specifies the type of payload to include in webhook requests. +/// public enum WebhookPayloadType { /// diff --git a/src/Umbraco.Core/Xml/XmlNodeListFactory.cs b/src/Umbraco.Core/Xml/XmlNodeListFactory.cs index 74c0861d66ad..9bcbc601e30c 100644 --- a/src/Umbraco.Core/Xml/XmlNodeListFactory.cs +++ b/src/Umbraco.Core/Xml/XmlNodeListFactory.cs @@ -5,8 +5,18 @@ // source: mvpxml.codeplex.com namespace Umbraco.Cms.Core.Xml; +/// +/// Factory class for creating instances from various sources. +/// +/// +/// This factory provides methods to create XmlNodeList implementations from XPath iterators. +/// The class uses a private constructor to prevent direct instantiation. +/// public class XmlNodeListFactory { + /// + /// Prevents a default instance of the class from being created. + /// private XmlNodeListFactory() { } From b0c135b4585db03b1867bc9f47d2308ef618d7fa Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Wed, 4 Feb 2026 10:01:41 +0100 Subject: [PATCH 2/2] Revert any code changes in the PR. --- .../Collections/ConcurrentHashSet.cs | 7 ------ .../Models/Entities/EntitySlim.cs | 22 ------------------- 2 files changed, 29 deletions(-) diff --git a/src/Umbraco.Core/Collections/ConcurrentHashSet.cs b/src/Umbraco.Core/Collections/ConcurrentHashSet.cs index cbb024dcc2f9..41954618597e 100644 --- a/src/Umbraco.Core/Collections/ConcurrentHashSet.cs +++ b/src/Umbraco.Core/Collections/ConcurrentHashSet.cs @@ -14,13 +14,6 @@ public class ConcurrentHashSet : ICollection, ISet private readonly HashSet _innerSet = new(); private readonly ReaderWriterLockSlim _instanceLocker = new(LockRecursionPolicy.NoRecursion); - /// - /// Initializes a new instance of the class. - /// - public ConcurrentHashSet() - { - } - /// /// Gets the number of elements contained in the . /// diff --git a/src/Umbraco.Core/Models/Entities/EntitySlim.cs b/src/Umbraco.Core/Models/Entities/EntitySlim.cs index 5e0bd01703b8..e0a7c4fd9232 100644 --- a/src/Umbraco.Core/Models/Entities/EntitySlim.cs +++ b/src/Umbraco.Core/Models/Entities/EntitySlim.cs @@ -1,4 +1,3 @@ -using System.ComponentModel; using System.Runtime.Serialization; namespace Umbraco.Cms.Core.Models.Entities; @@ -97,27 +96,6 @@ public void SetParent(ITreeEntity? parent) => [DataMember] public virtual bool IsContainer { get; set; } - /// - /// Occurs when a property value changes. - /// - /// - /// This event is declared to satisfy the interface but is never raised - /// since does not track changes. - /// - public event PropertyChangedEventHandler? PropertyChanged; - - /// - /// Not implemented. Always throws . - /// - /// Always thrown as this method is not implemented. - public void DisableChangeTracking() => throw new InvalidOperationException("This method won't be implemented."); - - /// - /// Not implemented. Always throws . - /// - /// Always thrown as this method is not implemented. - public void EnableChangeTracking() => throw new InvalidOperationException("This method won't be implemented."); - #region IDeepCloneable ///