2021-02-09 11:26:22 +01:00
using Examine ;
2023-05-25 08:36:42 +02:00
using Microsoft.Extensions.DependencyInjection ;
2021-02-09 10:22:42 +01:00
using Umbraco.Cms.Core.Models ;
using Umbraco.Cms.Core.Models.Membership ;
using Umbraco.Cms.Core.PropertyEditors ;
2021-02-15 11:41:12 +01:00
using Umbraco.Cms.Core.Scoping ;
2021-02-09 10:22:42 +01:00
using Umbraco.Cms.Core.Services ;
using Umbraco.Cms.Core.Strings ;
2023-05-25 08:36:42 +02:00
using Umbraco.Cms.Web.Common.DependencyInjection ;
2021-02-09 11:26:22 +01:00
using Umbraco.Extensions ;
2022-06-02 08:18:31 +02:00
using IScope = Umbraco . Cms . Infrastructure . Scoping . IScope ;
2018-11-26 13:33:15 +11:00
2022-06-02 08:18:31 +02:00
namespace Umbraco.Cms.Infrastructure.Examine ;
/// <summary>
/// Builds <see cref="ValueSet" />s for <see cref="IContent" /> items
/// </summary>
public class ContentValueSetBuilder : BaseValueSetBuilder < IContent > , IContentValueSetBuilder ,
IPublishedContentValueSetBuilder
2018-11-26 13:33:15 +11:00
{
2022-07-19 10:58:21 +10:00
private static readonly object [ ] NoValue = new [ ] { "n" } ;
private static readonly object [ ] YesValue = new [ ] { "y" } ;
2023-11-14 08:12:05 +01:00
private readonly ICoreScopeProvider _scopeProvider ;
2022-06-02 08:18:31 +02:00
private readonly IShortStringHelper _shortStringHelper ;
private readonly UrlSegmentProviderCollection _urlSegmentProviders ;
private readonly IUserService _userService ;
2023-05-25 08:36:42 +02:00
private readonly ILocalizationService _localizationService ;
2023-11-14 08:12:05 +01:00
private readonly IContentTypeService _contentTypeService ;
2022-06-02 08:18:31 +02:00
public ContentValueSetBuilder (
PropertyEditorCollection propertyEditors ,
UrlSegmentProviderCollection urlSegmentProviders ,
IUserService userService ,
IShortStringHelper shortStringHelper ,
2023-11-14 08:12:05 +01:00
ICoreScopeProvider scopeProvider ,
2023-05-25 08:36:42 +02:00
bool publishedValuesOnly ,
2023-11-14 08:12:05 +01:00
ILocalizationService localizationService ,
IContentTypeService contentTypeService )
2022-06-02 08:18:31 +02:00
: base ( propertyEditors , publishedValuesOnly )
2018-11-26 13:33:15 +11:00
{
2022-06-02 08:18:31 +02:00
_urlSegmentProviders = urlSegmentProviders ;
_userService = userService ;
_shortStringHelper = shortStringHelper ;
_scopeProvider = scopeProvider ;
2023-05-25 08:36:42 +02:00
_localizationService = localizationService ;
2023-11-14 08:12:05 +01:00
_contentTypeService = contentTypeService ;
}
[Obsolete("Use non-obsolete ctor, scheduled for removal in v14")]
public ContentValueSetBuilder (
PropertyEditorCollection propertyEditors ,
UrlSegmentProviderCollection urlSegmentProviders ,
IUserService userService ,
IShortStringHelper shortStringHelper ,
IScopeProvider scopeProvider ,
bool publishedValuesOnly ,
ILocalizationService localizationService )
: this (
propertyEditors ,
urlSegmentProviders ,
userService ,
shortStringHelper ,
scopeProvider ,
publishedValuesOnly ,
localizationService ,
StaticServiceProvider . Instance . GetRequiredService < IContentTypeService > ( ) )
{
2023-05-25 08:36:42 +02:00
}
2023-11-14 08:12:05 +01:00
[Obsolete("Use non-obsolete ctor, scheduled for removal in v14")]
2023-05-25 08:36:42 +02:00
public ContentValueSetBuilder (
PropertyEditorCollection propertyEditors ,
UrlSegmentProviderCollection urlSegmentProviders ,
IUserService userService ,
IShortStringHelper shortStringHelper ,
IScopeProvider scopeProvider ,
bool publishedValuesOnly )
: this (
propertyEditors ,
urlSegmentProviders ,
userService ,
shortStringHelper ,
scopeProvider ,
publishedValuesOnly ,
2023-11-14 08:12:05 +01:00
StaticServiceProvider . Instance . GetRequiredService < ILocalizationService > ( ) ,
StaticServiceProvider . Instance . GetRequiredService < IContentTypeService > ( ) )
2023-05-25 08:36:42 +02:00
{
2022-06-02 08:18:31 +02:00
}
2018-11-26 13:33:15 +11:00
2022-06-02 08:18:31 +02:00
/// <inheritdoc />
public override IEnumerable < ValueSet > GetValueSets ( params IContent [ ] content )
{
Dictionary < int , IProfile > creatorIds ;
Dictionary < int , IProfile > writerIds ;
2018-11-26 13:33:15 +11:00
2022-06-02 08:18:31 +02:00
// We can lookup all of the creator/writer names at once which can save some
// processing below instead of one by one.
2023-11-14 08:12:05 +01:00
using ( ICoreScope scope = _scopeProvider . CreateCoreScope ( ) )
2018-11-26 13:33:15 +11:00
{
2022-06-02 08:18:31 +02:00
creatorIds = _userService . GetProfilesById ( content . Select ( x = > x . CreatorId ) . ToArray ( ) )
. ToDictionary ( x = > x . Id , x = > x ) ;
writerIds = _userService . GetProfilesById ( content . Select ( x = > x . WriterId ) . ToArray ( ) )
. ToDictionary ( x = > x . Id , x = > x ) ;
scope . Complete ( ) ;
2018-11-26 13:33:15 +11:00
}
2022-06-02 08:18:31 +02:00
return GetValueSetsEnumerable ( content , creatorIds , writerIds ) ;
}
2020-08-31 23:57:26 +10:00
2022-06-02 08:18:31 +02:00
private IEnumerable < ValueSet > GetValueSetsEnumerable ( IContent [ ] content , Dictionary < int , IProfile > creatorIds , Dictionary < int , IProfile > writerIds )
{
2023-11-14 08:12:05 +01:00
IDictionary < Guid , IContentType > contentTypeDictionary = _contentTypeService . GetAll ( ) . ToDictionary ( x = > x . Key ) ;
2022-06-02 08:18:31 +02:00
// TODO: There is a lot of boxing going on here and ultimately all values will be boxed by Lucene anyways
// but I wonder if there's a way to reduce the boxing that we have to do or if it will matter in the end since
// Lucene will do it no matter what? One idea was to create a `FieldValue` struct which would contain `object`, `object[]`, `ValueType` and `ValueType[]`
// references and then each array is an array of `FieldValue[]` and values are assigned accordingly. Not sure if it will make a difference or not.
foreach ( IContent c in content )
2020-08-31 23:57:26 +10:00
{
2022-06-02 08:18:31 +02:00
var isVariant = c . ContentType . VariesByCulture ( ) ;
2018-11-26 13:33:15 +11:00
2022-06-02 08:18:31 +02:00
var urlValue = c . GetUrlSegment ( _shortStringHelper , _urlSegmentProviders ) ; // Always add invariant urlName
var values = new Dictionary < string , IEnumerable < object? > >
2018-11-26 13:33:15 +11:00
{
2022-06-02 08:18:31 +02:00
{ "icon" , c . ContentType . Icon ? . Yield ( ) ? ? Enumerable . Empty < string > ( ) } ,
{
2022-07-19 10:58:21 +10:00
UmbracoExamineFieldNames . PublishedFieldName , c . Published ? YesValue : NoValue
2022-06-02 08:18:31 +02:00
} , // Always add invariant published value
{ "id" , new object [ ] { c . Id } } ,
{ UmbracoExamineFieldNames . NodeKeyFieldName , new object [ ] { c . Key } } ,
{ "parentID" , new object [ ] { c . Level > 1 ? c . ParentId : - 1 } } ,
{ "level" , new object [ ] { c . Level } } ,
{ "creatorID" , new object [ ] { c . CreatorId } } ,
{ "sortOrder" , new object [ ] { c . SortOrder } } ,
{ "createDate" , new object [ ] { c . CreateDate } } , // Always add invariant createDate
{ "updateDate" , new object [ ] { c . UpdateDate } } , // Always add invariant updateDate
2018-11-26 13:33:15 +11:00
{
2022-06-02 08:18:31 +02:00
UmbracoExamineFieldNames . NodeNameFieldName , ( PublishedValuesOnly // Always add invariant nodeName
2019-02-07 15:13:45 +11:00
? c . PublishName ? . Yield ( )
2022-06-02 08:18:31 +02:00
: c . Name ? . Yield ( ) ) ? ? Enumerable . Empty < string > ( )
} ,
{ "urlName" , urlValue ? . Yield ( ) ? ? Enumerable . Empty < string > ( ) } , // Always add invariant urlName
{ "path" , c . Path . Yield ( ) } ,
{ "nodeType" , c . ContentType . Id . ToString ( ) . Yield ( ) } ,
{
"creatorName" ,
( creatorIds . TryGetValue ( c . CreatorId , out IProfile ? creatorProfile ) ? creatorProfile . Name ! : "??" )
. Yield ( )
} ,
2018-11-26 13:33:15 +11:00
{
2022-06-02 08:18:31 +02:00
"writerName" ,
( writerIds . TryGetValue ( c . WriterId , out IProfile ? writerProfile ) ? writerProfile . Name ! : "??" )
. Yield ( )
} ,
{ "writerID" , new object [ ] { c . WriterId } } ,
{ "templateID" , new object [ ] { c . TemplateId ? ? 0 } } ,
2022-07-19 10:58:21 +10:00
{ UmbracoExamineFieldNames . VariesByCultureFieldName , NoValue } ,
2022-06-02 08:18:31 +02:00
} ;
2018-11-26 13:33:15 +11:00
2022-06-02 08:18:31 +02:00
if ( isVariant )
{
2022-07-19 10:58:21 +10:00
values [ UmbracoExamineFieldNames . VariesByCultureFieldName ] = YesValue ;
2022-06-02 08:18:31 +02:00
foreach ( var culture in c . AvailableCultures )
{
var variantUrl = c . GetUrlSegment ( _shortStringHelper , _urlSegmentProviders , culture ) ;
var lowerCulture = culture . ToLowerInvariant ( ) ;
values [ $"urlName_{lowerCulture}" ] = variantUrl ? . Yield ( ) ? ? Enumerable . Empty < string > ( ) ;
values [ $"nodeName_{lowerCulture}" ] = ( PublishedValuesOnly
? c . GetPublishName ( culture ) ? . Yield ( )
: c . GetCultureName ( culture ) ? . Yield ( ) ) ? ? Enumerable . Empty < string > ( ) ;
values [ $"{UmbracoExamineFieldNames.PublishedFieldName}_{lowerCulture}" ] =
( c . IsCulturePublished ( culture ) ? "y" : "n" ) . Yield < object > ( ) ;
values [ $"updateDate_{lowerCulture}" ] = ( PublishedValuesOnly
? c . GetPublishDate ( culture )
: c . GetUpdateDate ( culture ) ) ? . Yield < object > ( ) ? ? Enumerable . Empty < object > ( ) ;
2018-11-26 13:33:15 +11:00
}
2022-06-02 08:18:31 +02:00
}
2018-11-26 13:33:15 +11:00
2023-05-25 08:36:42 +02:00
var availableCultures = new List < string > ( c . AvailableCultures ) ;
if ( availableCultures . Any ( ) is false )
{
availableCultures . Add ( _localizationService . GetDefaultLanguageIsoCode ( ) ) ;
}
2022-06-02 08:18:31 +02:00
foreach ( IProperty property in c . Properties )
{
if ( ! property . PropertyType . VariesByCulture ( ) )
2018-11-26 13:33:15 +11:00
{
2023-11-14 08:12:05 +01:00
AddPropertyValue ( property , null , null , values , availableCultures , contentTypeDictionary ) ;
2022-06-02 08:18:31 +02:00
}
else
{
foreach ( var culture in c . AvailableCultures )
2018-11-26 13:33:15 +11:00
{
2023-11-14 08:12:05 +01:00
AddPropertyValue ( property , culture . ToLowerInvariant ( ) , null , values , availableCultures , contentTypeDictionary ) ;
2018-11-26 13:33:15 +11:00
}
}
2022-06-02 08:18:31 +02:00
}
2018-11-26 13:33:15 +11:00
2022-06-02 08:18:31 +02:00
var vs = new ValueSet ( c . Id . ToInvariantString ( ) , IndexTypes . Content , c . ContentType . Alias , values ) ;
2018-11-26 13:33:15 +11:00
2022-06-02 08:18:31 +02:00
yield return vs ;
2018-11-26 13:33:15 +11:00
}
}
}