public IEnumerable <ContentTypeBasic> GetAllowedChildren(int contentId) { if (contentId == Constants.System.RecycleBinContent) { return(Enumerable.Empty <ContentTypeBasic>()); } IEnumerable <IContentType> types; if (contentId == Constants.System.Root) { types = _contentTypeService.GetAll().Where(x => x.AllowedAsRoot).ToList(); } else { IContent?contentItem = _contentService.GetById(contentId); if (contentItem == null) { return(Enumerable.Empty <ContentTypeBasic>()); } IContentTypeComposition?contentType = _contentTypeBaseServiceProvider.GetContentTypeOf(contentItem); var ids = contentType?.AllowedContentTypes?.OrderBy(c => c.SortOrder).Select(x => x.Id.Value).ToArray(); if (ids is null || ids.Any() == false) { return(Enumerable.Empty <ContentTypeBasic>()); } types = _contentTypeService.GetAll(ids).OrderBy(c => ids.IndexOf(c.Id)).ToList(); } var basics = types.Where(type => type.IsElement == false) .Select(_umbracoMapper.Map <IContentType, ContentTypeBasic>).WhereNotNull().ToList(); ILocalizedTextService localizedTextService = _localizedTextService; foreach (ContentTypeBasic basic in basics) { basic.Name = localizedTextService.UmbracoDictionaryTranslate(CultureDictionary, basic.Name); basic.Description = localizedTextService.UmbracoDictionaryTranslate(CultureDictionary, basic.Description); } //map the blueprints IContent[]? blueprints = _contentService.GetBlueprintsForContentTypes(types.Select(x => x.Id).ToArray())?.ToArray(); foreach (ContentTypeBasic basic in basics) { IContent[]? docTypeBluePrints = blueprints?.Where(x => x.ContentTypeId == (int?)basic.Id).ToArray(); if (docTypeBluePrints is not null) { foreach (IContent blueprint in docTypeBluePrints) { basic.Blueprints[blueprint.Id] = blueprint.Name ?? string.Empty; } } } return(basics.OrderBy(c => contentId == Constants.System.Root ? c.Name : string.Empty)); }
// Umbraco.Code.MapAll -AllowPreview -Errors -PersistedContent private void Map(IContent source, ContentItemDisplay target, MapperContext context) { target.AllowedActions = GetActions(source); target.AllowedTemplates = GetAllowedTemplates(source); target.ContentApps = _commonMapper.GetContentApps(source); target.ContentTypeId = source.ContentType.Id; target.ContentTypeKey = source.ContentType.Key; target.ContentTypeAlias = source.ContentType.Alias; target.ContentTypeName = _localizedTextService.UmbracoDictionaryTranslate(source.ContentType.Name); target.DocumentType = _commonMapper.GetContentType(source, context); target.Icon = source.ContentType.Icon; target.Id = source.Id; target.IsBlueprint = source.Blueprint; target.IsChildOfListView = DetermineIsChildOfListView(source, context); target.IsContainer = source.ContentType.IsContainer; target.IsElement = source.ContentType.IsElement; target.Key = source.Key; target.Owner = _commonMapper.GetOwner(source, context); target.ParentId = source.ParentId; target.Path = source.Path; target.SortOrder = source.SortOrder; target.TemplateAlias = GetDefaultTemplate(source); target.TemplateId = source.TemplateId ?? default; target.Trashed = source.Trashed; target.TreeNodeUrl = _commonMapper.GetTreeNodeUrl <ContentTreeController>(source); target.Udi = Udi.Create(source.Blueprint ? Constants.UdiEntityType.DocumentBlueprint : Constants.UdiEntityType.Document, source.Key); target.UpdateDate = source.UpdateDate; target.Updater = _commonMapper.GetCreator(source, context); target.Urls = GetUrls(source); target.Variants = _contentVariantMapper.Map(source, context); target.ContentDto = new ContentPropertyCollectionDto(); target.ContentDto.Properties = context.MapEnumerable <Property, ContentPropertyDto>(source.Properties); }
// Umbraco.Code.MapAll -AllowPreview -Errors -PersistedContent private void Map <TVariant>(IContent source, ContentItemDisplay <TVariant> target, MapperContext context) where TVariant : ContentVariantDisplay { // Both GetActions and DetermineIsChildOfListView use parent, so get it once here // Parent might already be in context, so check there before using content service IContent?parent; if (context.Items.TryGetValue("Parent", out var parentObj) && parentObj is IContent typedParent) { parent = typedParent; } else { parent = _contentService.GetParent(source); } target.AllowedActions = GetActions(source, parent, context); target.AllowedTemplates = GetAllowedTemplates(source); target.ContentApps = _commonMapper.GetContentAppsForEntity(source); target.ContentTypeId = source.ContentType.Id; target.ContentTypeKey = source.ContentType.Key; target.ContentTypeAlias = source.ContentType.Alias; target.ContentTypeName = _localizedTextService.UmbracoDictionaryTranslate(_cultureDictionary, source.ContentType.Name); target.DocumentType = _commonMapper.GetContentType(source, context); target.Icon = source.ContentType.Icon; target.Id = source.Id; target.IsBlueprint = source.Blueprint; target.IsChildOfListView = DetermineIsChildOfListView(source, parent, context); target.IsContainer = source.ContentType.IsContainer; target.IsElement = source.ContentType.IsElement; target.Key = source.Key; target.Owner = _commonMapper.GetOwner(source, context); target.ParentId = source.ParentId; target.Path = source.Path; target.SortOrder = source.SortOrder; target.TemplateAlias = GetDefaultTemplate(source); target.TemplateId = source.TemplateId ?? default; target.Trashed = source.Trashed; target.TreeNodeUrl = _commonTreeNodeMapper.GetTreeNodeUrl <ContentTreeController>(source); target.Udi = Udi.Create(source.Blueprint ? Constants.UdiEntityType.DocumentBlueprint : Constants.UdiEntityType.Document, source.Key); target.UpdateDate = source.UpdateDate; target.Updater = _commonMapper.GetCreator(source, context); target.Urls = GetUrls(source); target.Variants = _contentVariantMapper.Map <TVariant>(source, context); target.ContentDto = new ContentPropertyCollectionDto { Properties = context.MapEnumerable <IProperty, ContentPropertyDto>(source.Properties).WhereNotNull() }; }
public override ContentPropertyDisplay Convert(ResolutionContext context) { var display = base.Convert(context); var originalProperty = context.SourceValue as Property; if (originalProperty == null) { throw new InvalidOperationException("Source value is not a property."); } var dataTypeService = DataTypeService; var preVals = dataTypeService.GetPreValuesCollectionByDataTypeId(originalProperty.PropertyType.DataTypeDefinitionId); //configure the editor for display with the pre-values var valEditor = display.PropertyEditor.ValueEditor; valEditor.ConfigureForDisplay(preVals); //set the display properties after mapping display.Alias = originalProperty.Alias; display.Description = originalProperty.PropertyType.Description; display.Label = originalProperty.PropertyType.Name; display.HideLabel = valEditor.HideLabel; //add the validation information display.Validation.Mandatory = originalProperty.PropertyType.Mandatory; display.Validation.Pattern = originalProperty.PropertyType.ValidationRegExp; if (display.PropertyEditor == null) { //display.Config = PreValueCollection.AsDictionary(preVals); //if there is no property editor it means that it is a legacy data type // we cannot support editing with that so we'll just render the readonly value view. display.View = "views/propertyeditors/readonlyvalue/readonlyvalue.html"; } else { //let the property editor format the pre-values display.Config = display.PropertyEditor.PreValueEditor.ConvertDbToEditor(display.PropertyEditor.DefaultPreValues, preVals); display.View = valEditor.View; } //Translate display.Label = _textService.UmbracoDictionaryTranslate(display.Label); display.Description = _textService.UmbracoDictionaryTranslate(display.Description); return(display); }
public override void Map(IProperty originalProp, ContentPropertyDisplay dest, MapperContext context) { base.Map(originalProp, dest, context); var config = originalProp.PropertyType is null ? null : DataTypeService.GetDataType(originalProp.PropertyType.DataTypeId)?.Configuration; // TODO: IDataValueEditor configuration - general issue // GetValueEditor() returns a non-configured IDataValueEditor // - for richtext and nested, configuration determines HideLabel, so we need to configure the value editor // - could configuration also determines ValueType, everywhere? // - does it make any sense to use a IDataValueEditor without configuring it? // configure the editor for display with configuration IDataValueEditor?valEditor = dest.PropertyEditor?.GetValueEditor(config); // set the display properties after mapping dest.Alias = originalProp.Alias; dest.Description = originalProp.PropertyType?.Description; dest.Label = originalProp.PropertyType?.Name; dest.HideLabel = valEditor?.HideLabel ?? false; dest.LabelOnTop = originalProp.PropertyType?.LabelOnTop; // add the validation information dest.Validation.Mandatory = originalProp.PropertyType?.Mandatory ?? false; dest.Validation.MandatoryMessage = originalProp.PropertyType?.MandatoryMessage; dest.Validation.Pattern = originalProp.PropertyType?.ValidationRegExp; dest.Validation.PatternMessage = originalProp.PropertyType?.ValidationRegExpMessage; if (dest.PropertyEditor == null) { // display.Config = PreValueCollection.AsDictionary(preVals); // if there is no property editor it means that it is a legacy data type // we cannot support editing with that so we'll just render the readonly value view. dest.View = "views/propertyeditors/readonlyvalue/readonlyvalue.html"; } else { // let the property editor format the pre-values dest.Config = dest.PropertyEditor.GetConfigurationEditor().ToValueEditor(config); dest.View = valEditor?.View; } // Translate dest.Label = _textService.UmbracoDictionaryTranslate(_cultureDictionary, dest.Label); dest.Description = _textService.UmbracoDictionaryTranslate(_cultureDictionary, dest.Description); }
protected override IEnumerable <ContentPropertyDisplay> GetCustomGenericProperties(IContentBase content) { var member = (IMember)content; var genericProperties = new List <ContentPropertyDisplay> { new ContentPropertyDisplay { Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}id", Label = _localizedTextService.Localize("general", "id"), Value = new List <string> { member.Id.ToString(), member.Key.ToString() }, View = "idwithguid" }, new ContentPropertyDisplay { Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}doctype", Label = _localizedTextService.Localize("content", "membertype"), Value = _localizedTextService.UmbracoDictionaryTranslate(CultureDictionary, member.ContentType.Name), View = _propertyEditorCollection[Constants.PropertyEditors.Aliases.Label].GetValueEditor().View }, GetLoginProperty(member, _localizedTextService), new ContentPropertyDisplay { Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}email", Label = _localizedTextService.Localize("general", "email"), Value = member.Email, View = "email", Validation = { Mandatory = true } }, new ContentPropertyDisplay { Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}password", Label = _localizedTextService.Localize(null, "password"), Value = new Dictionary <string, object> { // TODO: why ignoreCase, what are we doing here?! { "newPassword", member.GetAdditionalDataValueIgnoreCase("NewPassword", null) }, }, // TODO: Hard coding this because the changepassword doesn't necessarily need to be a resolvable (real) property editor View = "changepassword", // initialize the dictionary with the configuration from the default membership provider Config = GetPasswordConfig(member) }, new ContentPropertyDisplay { Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}membergroup", Label = _localizedTextService.Localize("content", "membergroup"), Value = GetMemberGroupValue(member.Username), View = "membergroups", Config = new Dictionary <string, object> { { "IsRequired", true } } } }; return(genericProperties); }
public IDictionary <string, string> Resolve(IContent source, ContentItemDisplay destination, IDictionary <string, string> destMember, ResolutionContext context) { var contentType = _contentTypeService.Get(source.ContentTypeId); return(contentType.AllowedTemplates .Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false) .ToDictionary(t => t.Alias, t => _localizedTextService.UmbracoDictionaryTranslate(t.Name))); }
protected override IEnumerable <ContentPropertyDisplay> GetCustomGenericProperties(IContentBase content) { var member = (IMember)content; var membersProvider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); var genericProperties = new List <ContentPropertyDisplay> { new ContentPropertyDisplay { Alias = string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = _localizedTextService.Localize("content/membertype"), //Value = localizedText.UmbracoDictionaryTranslate(display.ContentTypeName), Value = _localizedTextService.UmbracoDictionaryTranslate(member.ContentType.Name), View = PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View }, GetLoginProperty(_memberService, member, _localizedTextService), new ContentPropertyDisplay { Alias = string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = _localizedTextService.Localize("general/email"), Value = member.Email, View = "email", Validation = { Mandatory = true } }, new ContentPropertyDisplay { Alias = string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = _localizedTextService.Localize("password"), //NOTE: The value here is a json value - but the only property we care about is the generatedPassword one if it exists, the newPassword exists // only when creating a new member and we want to have a generated password pre-filled. Value = new Dictionary <string, object> { { "generatedPassword", member.GetAdditionalDataValueIgnoreCase("GeneratedPassword", null) }, { "newPassword", member.GetAdditionalDataValueIgnoreCase("NewPassword", null) }, }, //TODO: Hard coding this because the changepassword doesn't necessarily need to be a resolvable (real) property editor View = "changepassword", //initialize the dictionary with the configuration from the default membership provider Config = new Dictionary <string, object>(membersProvider.GetConfiguration(_userService)) { //the password change toggle will only be displayed if there is already a password assigned. { "hasPassword", member.RawPasswordValue.IsNullOrWhiteSpace() == false } } }, new ContentPropertyDisplay { Alias = string.Format("{0}membergroup", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = _localizedTextService.Localize("content/membergroup"), Value = GetMemberGroupValue(member.Username), View = "membergroups", Config = new Dictionary <string, object> { { "IsRequired", true } } } }; return(genericProperties); }
public override ContentPropertyDisplay Convert(Property originalProp, ContentPropertyDisplay dest, ResolutionContext context) { var display = base.Convert(originalProp, dest, context); var config = DataTypeService.GetDataType(originalProp.PropertyType.DataTypeId).Configuration; // fixme - IDataValueEditor configuration - general issue // GetValueEditor() returns a non-configured IDataValueEditor // - for richtext and nested, configuration determines HideLabel, so we need to configure the value editor // - could configuration also determines ValueType, everywhere? // - does it make any sense to use a IDataValueEditor without configuring it? // configure the editor for display with configuration var valEditor = display.PropertyEditor.GetValueEditor(config); //set the display properties after mapping display.Alias = originalProp.Alias; display.Description = originalProp.PropertyType.Description; display.Label = originalProp.PropertyType.Name; display.HideLabel = valEditor.HideLabel; //add the validation information display.Validation.Mandatory = originalProp.PropertyType.Mandatory; display.Validation.Pattern = originalProp.PropertyType.ValidationRegExp; if (display.PropertyEditor == null) { //display.Config = PreValueCollection.AsDictionary(preVals); //if there is no property editor it means that it is a legacy data type // we cannot support editing with that so we'll just render the readonly value view. display.View = "views/propertyeditors/readonlyvalue/readonlyvalue.html"; } else { //let the property editor format the pre-values display.Config = display.PropertyEditor.GetConfigurationEditor().ToValueEditor(config); display.View = valEditor.View; } //Translate display.Label = _textService.UmbracoDictionaryTranslate(display.Label); display.Description = _textService.UmbracoDictionaryTranslate(display.Description); return(display); }
/// <summary> /// Create the list of tabs for the <see cref="IContentBase"/> /// </summary> /// <param name="umbracoContext"></param> /// <param name="content">Source value</param> /// <returns>Destination</returns> protected virtual List <Tab <ContentPropertyDisplay> > ResolveCore(UmbracoContext umbracoContext, TSource content) { var tabs = new List <Tab <ContentPropertyDisplay> >(); // add the tabs, for properties that belong to a tab // need to aggregate the tabs, as content.PropertyGroups contains all the composition tabs, // and there might be duplicates (content does not work like contentType and there is no // content.CompositionPropertyGroups). var groupsGroupsByName = content.PropertyGroups.OrderBy(x => x.SortOrder).GroupBy(x => x.Name); foreach (var groupsByName in groupsGroupsByName) { var properties = new List <Property>(); // merge properties for groups with the same name foreach (var group in groupsByName) { var groupProperties = content.GetPropertiesForGroup(group) .Where(x => IgnoreProperties.Contains(x.Alias) == false); // skip ignored properties.AddRange(groupProperties); } if (properties.Count == 0) { continue; } //map the properties var mappedProperties = MapProperties(umbracoContext, content, properties); // add the tab // we need to pick an identifier... there is no "right" way... var g = groupsByName.FirstOrDefault(x => x.Id == content.ContentTypeId) // try local ?? groupsByName.First(); // else pick one randomly var groupId = g.Id; var groupName = groupsByName.Key; tabs.Add(new Tab <ContentPropertyDisplay> { Id = groupId, Alias = groupName, Label = _localizedTextService.UmbracoDictionaryTranslate(groupName), Properties = mappedProperties, IsActive = false }); } MapGenericProperties(umbracoContext, content, tabs); // activate the first tab if (tabs.Count > 0) { tabs[0].IsActive = true; } return(tabs); }
private static void AfterMap(IMedia media, MediaItemDisplay display, IDataTypeService dataTypeService, ILocalizedTextService localizedText, IContentTypeService contentTypeService, ILogger logger) { // Adapted from ContentModelMapper //map the IsChildOfListView (this is actually if it is a descendant of a list view!) var parent = media.Parent(); display.IsChildOfListView = parent != null && (parent.ContentType.IsContainer || contentTypeService.HasContainerInPath(parent.Path)); //map the tree node url if (HttpContext.Current != null) { var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext); var url = urlHelper.GetUmbracoApiService <MediaTreeController>(controller => controller.GetTreeNode(display.Id.ToString(), null)); display.TreeNodeUrl = url; } if (media.ContentType.IsContainer) { TabsAndPropertiesResolver.AddListView(display, "media", dataTypeService, localizedText); } var genericProperties = new List <ContentPropertyDisplay> { new ContentPropertyDisplay { Alias = string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("content/mediatype"), Value = localizedText.UmbracoDictionaryTranslate(display.ContentTypeName), View = PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View } }; TabsAndPropertiesResolver.MapGenericProperties(media, display, localizedText, genericProperties, properties => { if (HttpContext.Current != null && UmbracoContext.Current != null && UmbracoContext.Current.Security.CurrentUser != null && UmbracoContext.Current.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings))) { var mediaTypeLink = string.Format("#/settings/mediatypes/edit/{0}", media.ContentTypeId); //Replace the doctype property var docTypeProperty = properties.First(x => x.Alias == string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); docTypeProperty.Value = new List <object> { new { linkText = media.ContentType.Name, url = mediaTypeLink, target = "_self", icon = "icon-item-arrangement" } }; docTypeProperty.View = "urllist"; } // inject 'Link to media' as the first generic property var links = media.GetUrls(UmbracoConfig.For.UmbracoSettings().Content, logger); if (links.Any()) { var link = new ContentPropertyDisplay { Alias = string.Format("{0}urls", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("media/urls"), Value = string.Join(",", links), View = "urllist" }; properties.Insert(0, link); } }); }
/// <summary> /// TODO: We need to refactor how we work with ICultureDictionary - this is supposed to be the 'fast' way to /// do readonly access to the Dictionary without using the ILocalizationService. See TODO Notes in `DefaultCultureDictionary` /// Also NOTE that the ICultureDictionary is based on the ILocalizationService not the ILocalizedTextService (which is used /// only for the localization files - not the dictionary) /// </summary> /// <param name="manager"></param> /// <param name="text"></param> /// <returns></returns> internal static string UmbracoDictionaryTranslate(this ILocalizedTextService manager, string text) { var cultureDictionary = CultureDictionary; return(manager.UmbracoDictionaryTranslate(text, cultureDictionary)); }
public ContentMapperProfile( ContentUrlResolver contentUrlResolver, ContentTreeNodeUrlResolver <IContent, ContentTreeController> contentTreeNodeUrlResolver, TabsAndPropertiesResolver <IContent, ContentVariantDisplay> tabsAndPropertiesResolver, ContentAppResolver contentAppResolver, IUserService userService, IContentService contentService, IContentTypeService contentTypeService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, ILocalizationService localizationService, ILocalizedTextService localizedTextService) { // create, capture, cache var contentOwnerResolver = new OwnerResolver <IContent>(userService); var creatorResolver = new CreatorResolver(userService); var actionButtonsResolver = new ActionButtonsResolver(userService, contentService); var childOfListViewResolver = new ContentChildOfListViewResolver(contentService, contentTypeService); var contentTypeBasicResolver = new ContentTypeBasicResolver <IContent, ContentItemDisplay>(contentTypeBaseServiceProvider); var allowedTemplatesResolver = new AllowedTemplatesResolver(contentTypeService, localizedTextService); var defaultTemplateResolver = new DefaultTemplateResolver(); var variantResolver = new ContentVariantResolver(localizationService); var schedPublishReleaseDateResolver = new ScheduledPublishDateResolver(ContentScheduleAction.Release); var schedPublishExpireDateResolver = new ScheduledPublishDateResolver(ContentScheduleAction.Expire); //FROM IContent TO ContentItemDisplay CreateMap <IContent, ContentItemDisplay>() .ForMember(dest => dest.Udi, opt => opt.MapFrom(src => Udi.Create(src.Blueprint ? Constants.UdiEntityType.DocumentBlueprint : Constants.UdiEntityType.Document, src.Key))) .ForMember(dest => dest.Owner, opt => opt.MapFrom(src => contentOwnerResolver.Resolve(src))) .ForMember(dest => dest.Updater, opt => opt.MapFrom(src => creatorResolver.Resolve(src))) .ForMember(dest => dest.Variants, opt => opt.MapFrom(variantResolver)) .ForMember(dest => dest.ContentApps, opt => opt.MapFrom(contentAppResolver)) .ForMember(dest => dest.Icon, opt => opt.MapFrom(src => src.ContentType.Icon)) .ForMember(dest => dest.ContentTypeAlias, opt => opt.MapFrom(src => src.ContentType.Alias)) .ForMember(dest => dest.ContentTypeName, opt => opt.MapFrom(src => localizedTextService.UmbracoDictionaryTranslate(src.ContentType.Name))) .ForMember(dest => dest.IsContainer, opt => opt.MapFrom(src => src.ContentType.IsContainer)) .ForMember(dest => dest.IsElement, opt => opt.MapFrom(src => src.ContentType.IsElement)) .ForMember(dest => dest.IsBlueprint, opt => opt.MapFrom(src => src.Blueprint)) .ForMember(dest => dest.IsChildOfListView, opt => opt.MapFrom(childOfListViewResolver)) .ForMember(dest => dest.Trashed, opt => opt.MapFrom(src => src.Trashed)) .ForMember(dest => dest.TemplateAlias, opt => opt.MapFrom(defaultTemplateResolver)) .ForMember(dest => dest.Urls, opt => opt.MapFrom(contentUrlResolver)) .ForMember(dest => dest.AllowPreview, opt => opt.Ignore()) .ForMember(dest => dest.TreeNodeUrl, opt => opt.MapFrom(contentTreeNodeUrlResolver)) .ForMember(dest => dest.Notifications, opt => opt.Ignore()) .ForMember(dest => dest.Errors, opt => opt.Ignore()) .ForMember(dest => dest.DocumentType, opt => opt.MapFrom(contentTypeBasicResolver)) .ForMember(dest => dest.AllowedTemplates, opt => opt.MapFrom(allowedTemplatesResolver)) .ForMember(dest => dest.AllowedActions, opt => opt.MapFrom(src => actionButtonsResolver.Resolve(src))) .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()); CreateMap <IContent, ContentVariantDisplay>() .ForMember(dest => dest.PublishDate, opt => opt.MapFrom(src => src.PublishDate)) .ForMember(dest => dest.ReleaseDate, opt => opt.MapFrom(schedPublishReleaseDateResolver)) .ForMember(dest => dest.ExpireDate, opt => opt.MapFrom(schedPublishExpireDateResolver)) .ForMember(dest => dest.Segment, opt => opt.Ignore()) .ForMember(dest => dest.Language, opt => opt.Ignore()) .ForMember(dest => dest.Notifications, opt => opt.Ignore()) .ForMember(dest => dest.State, opt => opt.MapFrom <ContentSavedStateResolver <ContentPropertyDisplay> >()) .ForMember(dest => dest.Tabs, opt => opt.MapFrom(tabsAndPropertiesResolver)); //FROM IContent TO ContentItemBasic<ContentPropertyBasic, IContent> CreateMap <IContent, ContentItemBasic <ContentPropertyBasic> >() .ForMember(dest => dest.Udi, opt => opt.MapFrom(src => Udi.Create(src.Blueprint ? Constants.UdiEntityType.DocumentBlueprint : Constants.UdiEntityType.Document, src.Key))) .ForMember(dest => dest.Owner, opt => opt.MapFrom(src => contentOwnerResolver.Resolve(src))) .ForMember(dest => dest.Updater, opt => opt.MapFrom(src => creatorResolver.Resolve(src))) .ForMember(dest => dest.Icon, opt => opt.MapFrom(src => src.ContentType.Icon)) .ForMember(dest => dest.Trashed, opt => opt.MapFrom(src => src.Trashed)) .ForMember(dest => dest.ContentTypeAlias, opt => opt.MapFrom(src => src.ContentType.Alias)) .ForMember(dest => dest.Alias, opt => opt.Ignore()) .ForMember(dest => dest.AdditionalData, opt => opt.Ignore()) .ForMember(dest => dest.UpdateDate, opt => opt.MapFrom <UpdateDateResolver>()) .ForMember(dest => dest.Name, opt => opt.MapFrom <NameResolver>()) .ForMember(dest => dest.State, opt => opt.MapFrom <ContentBasicSavedStateResolver <ContentPropertyBasic> >()) .ForMember(dest => dest.VariesByCulture, opt => opt.MapFrom(src => src.ContentType.VariesByCulture())); //FROM IContent TO ContentPropertyCollectionDto //NOTE: the property mapping for cultures relies on a culture being set in the mapping context CreateMap <IContent, ContentPropertyCollectionDto>(); }
/// <summary> /// Maps the generic tab with custom properties for content /// </summary> /// <param name="memberService"></param> /// <param name="userService"></param> /// <param name="member"></param> /// <param name="display"></param> /// <param name="localizedText"></param> /// <remarks> /// If this is a new entity and there is an approved field then we'll set it to true by default. /// </remarks> private static void MapGenericCustomProperties(IMemberService memberService, IUserService userService, IMember member, MemberDisplay display, ILocalizedTextService localizedText) { var membersProvider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); //map the tree node url if (HttpContext.Current != null) { var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext); var url = urlHelper.GetUmbracoApiService <MemberTreeController>(controller => controller.GetTreeNode(display.Key.ToString("N"), null)); display.TreeNodeUrl = url; } var genericProperties = new List <ContentPropertyDisplay> { new ContentPropertyDisplay { Alias = string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("content/membertype"), Value = localizedText.UmbracoDictionaryTranslate(display.ContentTypeName), View = PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View }, GetLoginProperty(memberService, member, display, localizedText), new ContentPropertyDisplay { Alias = string.Format("{0}email", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("general/email"), Value = display.Email, View = "email", Validation = { Mandatory = true } }, new ContentPropertyDisplay { Alias = string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("password"), //NOTE: The value here is a json value - but the only property we care about is the generatedPassword one if it exists, the newPassword exists // only when creating a new member and we want to have a generated password pre-filled. Value = new Dictionary <string, object> { { "generatedPassword", member.GetAdditionalDataValueIgnoreCase("GeneratedPassword", null) }, { "newPassword", member.GetAdditionalDataValueIgnoreCase("NewPassword", null) }, }, //TODO: Hard coding this because the changepassword doesn't necessarily need to be a resolvable (real) property editor View = "changepassword", //initialize the dictionary with the configuration from the default membership provider Config = new Dictionary <string, object>(membersProvider.GetConfiguration(userService)) { //the password change toggle will only be displayed if there is already a password assigned. { "hasPassword", member.RawPasswordValue.IsNullOrWhiteSpace() == false } } }, new ContentPropertyDisplay { Alias = string.Format("{0}membergroup", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("content/membergroup"), Value = GetMemberGroupValue(display.Username), View = "membergroups", Config = new Dictionary <string, object> { { "IsRequired", true } } } }; TabsAndPropertiesResolver.MapGenericProperties(member, display, localizedText, genericProperties, properties => { if (HttpContext.Current != null && UmbracoContext.Current != null && UmbracoContext.Current.Security.CurrentUser != null && UmbracoContext.Current.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings))) { var memberTypeLink = string.Format("#/member/memberTypes/edit/{0}", member.ContentTypeId); //Replace the doctype property var docTypeProperty = properties.First(x => x.Alias == string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); docTypeProperty.Value = new List <object> { new { linkText = member.ContentType.Name, url = memberTypeLink, target = "_self", icon = "icon-item-arrangement" } }; docTypeProperty.View = "urllist"; } }); //check if there's an approval field var provider = membersProvider as global::umbraco.providers.members.UmbracoMembershipProvider; if (member.HasIdentity == false && provider != null) { var approvedField = provider.ApprovedPropertyTypeAlias; var prop = display.Properties.FirstOrDefault(x => x.Alias == approvedField); if (prop != null) { prop.Value = 1; } } }
/// <summary> /// Maps the generic tab with custom properties for content /// </summary> /// <param name="content"></param> /// <param name="display"></param> /// <param name="dataTypeService"></param> /// <param name="localizedText"></param> /// <param name="contentTypeService"></param> private static void AfterMap(IContent content, ContentItemDisplay display, IDataTypeService dataTypeService, ILocalizedTextService localizedText, IContentTypeService contentTypeService) { // map the IsChildOfListView (this is actually if it is a descendant of a list view!) var parent = content.Parent(); display.IsChildOfListView = parent != null && (parent.ContentType.IsContainer || contentTypeService.HasContainerInPath(parent.Path)); //map the tree node url if (HttpContext.Current != null) { var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext); var url = urlHelper.GetUmbracoApiService <ContentTreeController>(controller => controller.GetTreeNode(display.Id.ToString(), null)); display.TreeNodeUrl = url; } //fill in the template config to be passed to the template drop down. var templateItemConfig = new Dictionary <string, string> { { "", localizedText.Localize("general/choose") } }; foreach (var t in content.ContentType.AllowedTemplates .Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false)) { templateItemConfig.Add(t.Alias, t.Name); } if (content.ContentType.IsContainer) { TabsAndPropertiesResolver.AddListView(display, "content", dataTypeService, localizedText); } var properties = new List <ContentPropertyDisplay> { new ContentPropertyDisplay { Alias = string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("content/documentType"), Value = localizedText.UmbracoDictionaryTranslate(display.ContentTypeName), View = PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View }, new ContentPropertyDisplay { Alias = string.Format("{0}releasedate", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("content/releaseDate"), Value = display.ReleaseDate.HasValue ? display.ReleaseDate.Value.ToIsoString() : null, //Not editible for people without publish permission (U4-287) View = display.AllowedActions.Contains(ActionPublish.Instance.Letter) ? "datepicker" : PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View, Config = new Dictionary <string, object> { { "offsetTime", "1" } } //TODO: Fix up hard coded datepicker }, new ContentPropertyDisplay { Alias = string.Format("{0}expiredate", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("content/unpublishDate"), Value = display.ExpireDate.HasValue ? display.ExpireDate.Value.ToIsoString() : null, //Not editible for people without publish permission (U4-287) View = display.AllowedActions.Contains(ActionPublish.Instance.Letter) ? "datepicker" : PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View, Config = new Dictionary <string, object> { { "offsetTime", "1" } } //TODO: Fix up hard coded datepicker }, new ContentPropertyDisplay { Alias = string.Format("{0}template", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("template/template"), Value = display.TemplateAlias, View = "dropdown", //TODO: Hard coding until we make a real dropdown property editor to lookup Config = new Dictionary <string, object> { { "items", templateItemConfig } } } }; TabsAndPropertiesResolver.MapGenericProperties(content, display, localizedText, properties.ToArray(), genericProperties => { //TODO: This would be much nicer with the IUmbracoContextAccessor so we don't use singletons //If this is a web request and there's a user signed in and the // user has access to the settings section, we will if (HttpContext.Current != null && UmbracoContext.Current != null && UmbracoContext.Current.Security.CurrentUser != null && UmbracoContext.Current.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings))) { var currentDocumentType = contentTypeService.GetContentType(display.ContentTypeAlias); var currentDocumentTypeName = currentDocumentType == null ? string.Empty : localizedText.UmbracoDictionaryTranslate(currentDocumentType.Name); var currentDocumentTypeId = currentDocumentType == null ? string.Empty : currentDocumentType.Id.ToString(CultureInfo.InvariantCulture); //TODO: Hard coding this is not good var docTypeLink = string.Format("#/settings/documenttypes/edit/{0}", currentDocumentTypeId); //Replace the doc type property var docTypeProperty = genericProperties.First(x => x.Alias == string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); docTypeProperty.Value = new List <object> { new { linkText = currentDocumentTypeName, url = docTypeLink, target = "_self", icon = "icon-item-arrangement" } }; //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor docTypeProperty.View = "urllist"; } // inject 'Link to document' as the first generic property genericProperties.Insert(0, new ContentPropertyDisplay { Alias = string.Format("{0}urls", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = localizedText.Localize("content/urls"), Value = string.Join(",", display.Urls), View = "urllist" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor }); }); }
protected override IEnumerable <Tab <ContentPropertyDisplay> > ResolveCore(IContentBase content) { var tabs = new List <Tab <ContentPropertyDisplay> >(); // add the tabs, for properties that belong to a tab // need to aggregate the tabs, as content.PropertyGroups contains all the composition tabs, // and there might be duplicates (content does not work like contentType and there is no // content.CompositionPropertyGroups). var groupsGroupsByName = content.PropertyGroups.OrderBy(x => x.SortOrder).GroupBy(x => x.Name); foreach (var groupsByName in groupsGroupsByName) { var properties = new List <Property>(); // merge properties for groups with the same name foreach (var group in groupsByName) { var groupProperties = content.GetPropertiesForGroup(group) .Where(x => IgnoreProperties.Contains(x.Alias) == false); // skip ignored properties.AddRange(groupProperties); } if (properties.Count == 0) { continue; } // Sort properties so items from different compositions appear in correct order (see U4-9298). Map sorted properties. var mappedProperties = Mapper.Map <IEnumerable <Property>, IEnumerable <ContentPropertyDisplay> >(properties.OrderBy(prop => prop.PropertyType.SortOrder)); TranslateProperties(mappedProperties); // add the tab // we need to pick an identifier... there is no "right" way... var g = groupsByName.FirstOrDefault(x => x.Id == content.ContentTypeId) // try local ?? groupsByName.First(); // else pick one randomly var groupId = g.Id; var groupName = groupsByName.Key; tabs.Add(new Tab <ContentPropertyDisplay> { Id = groupId, Alias = groupName, Label = _localizedTextService.UmbracoDictionaryTranslate(groupName), Properties = mappedProperties, IsActive = false }); } // add the generic properties tab, for properties that don't belong to a tab // get the properties, map and translate them, then add the tab var noGroupProperties = content.GetNonGroupedProperties() .Where(x => IgnoreProperties.Contains(x.Alias) == false); // skip ignored var genericproperties = Mapper.Map <IEnumerable <Property>, IEnumerable <ContentPropertyDisplay> >(noGroupProperties).ToList(); TranslateProperties(genericproperties); tabs.Add(new Tab <ContentPropertyDisplay> { Id = 0, Label = _localizedTextService.Localize("general/properties"), Alias = "Generic properties", Properties = genericproperties }); // activate the first tab tabs.First().IsActive = true; return(tabs); }