Merge branch 'kjac-v8-fix-use-client-culture' into temp8

This commit is contained in:
Shannon
2019-02-19 01:20:03 +11:00
9 changed files with 96 additions and 23 deletions

View File

@@ -66,8 +66,22 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
//no matter what we always must have node id ordered at the end
sql = ordering.Direction == Direction.Ascending ? sql.OrderBy("NodeId") : sql.OrderByDescending("NodeId");
var page = Database.Page<BaseDto>(pageIndex + 1, pageSize, sql);
var dtos = page.Items;
// for content we must query for ContentEntityDto entities to produce the correct culture variant entity names
var pageIndexToFetch = pageIndex + 1;
IEnumerable<BaseDto> dtos;
if(isContent)
{
var page = Database.Page<ContentEntityDto>(pageIndexToFetch, pageSize, sql);
dtos = page.Items;
totalRecords = page.TotalItems;
}
else
{
var page = Database.Page<BaseDto>(pageIndexToFetch, pageSize, sql);
dtos = page.Items;
totalRecords = page.TotalItems;
}
var entities = dtos.Select(x => BuildEntity(isContent, isMedia, x)).ToArray();
if (isContent)
@@ -75,9 +89,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
// TODO: see https://github.com/umbraco/Umbraco-CMS/pull/3460#issuecomment-434903930 we need to not load any property data at all for media
if (isMedia)
BuildProperties(entities, dtos);
BuildProperties(entities, dtos.ToList());
totalRecords = page.TotalItems;
return entities;
}

View File

@@ -7,4 +7,6 @@ angular.module('umbraco.interceptors', [])
$httpProvider.interceptors.push('securityInterceptor');
$httpProvider.interceptors.push('debugRequestInterceptor');
$httpProvider.interceptors.push('doNotPostDollarVariablesOnPostRequestInterceptor');
$httpProvider.interceptors.push('cultureRequestInterceptor');
}]);

View File

@@ -0,0 +1,30 @@
(function() {
'use strict';
/**
* Used to set the current client culture on all requests API requests
* @param {any} $q
* @param {any} $routeParams
*/
function cultureRequestInterceptor($q, $routeParams) {
return {
//dealing with requests:
'request': function (config) {
if (!Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath) {
// no settings available, we're probably on the login screen
return config;
}
if (!config.url.match(RegExp(Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + "\/backoffice\/", "i"))) {
// it's not an API request, no handling
return config;
}
// it's an API request, add the current client culture as a header value
config.headers["X-UMB-CULTURE"] = $routeParams.cculture ? $routeParams.cculture : $routeParams.mculture;
return config;
}
};
}
angular.module('umbraco.interceptors').factory('cultureRequestInterceptor', cultureRequestInterceptor);
})();

View File

@@ -148,9 +148,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
},
treeAlias: $scope.model.config.startNode.type,
section: $scope.model.config.startNode.type,
idType: "udi",
//only show the lang selector for content
showLanguageSelector: $scope.model.config.startNode.type === "content"
idType: "udi"
};
//since most of the pre-value config's are used in the dialog options (i.e. maxNumber, minNumber, etc...) we'll merge the

View File

@@ -504,10 +504,14 @@ namespace Umbraco.Web.Editors
return new PagedResult<EntityBasic>(0, 0, 0);
}
var culture = ClientCulture();
var pagedResult = new PagedResult<EntityBasic>(totalRecords, pageNumber, pageSize)
{
Items = entities.Select(entity => Mapper.Map<IEntitySlim, EntityBasic>(entity, options =>
options.AfterMap((src, dest) => { dest.AdditionalData["hasChildren"] = src.HasChildren; })
{
options.SetCulture(culture);
options.AfterMap((src, dest) => { dest.AdditionalData["hasChildren"] = src.HasChildren; });
}
)
)
};
@@ -586,7 +590,7 @@ namespace Umbraco.Web.Editors
var pagedResult = new PagedResult<EntityBasic>(totalRecords, pageNumber, pageSize)
{
Items = entities.Select(Mapper.Map<EntityBasic>)
Items = entities.Select(MapEntities())
};
return pagedResult;
@@ -632,7 +636,7 @@ namespace Umbraco.Web.Editors
return Services.EntityService.GetChildren(id, objectType.Value)
.WhereNotNull()
.Select(Mapper.Map<EntityBasic>);
.Select(MapEntities());
}
//now we need to convert the unknown ones
switch (entityType)
@@ -693,7 +697,7 @@ namespace Umbraco.Web.Editors
: Services.EntityService.GetAll(objectType.Value, ids)
.WhereNotNull()
.OrderBy(x => x.Level)
.Select(x => Mapper.Map<EntityBasic>(x, opts => { opts.SetCulture(culture);}));
.Select(MapEntities(culture));
}
//now we need to convert the unknown ones
switch (entityType)
@@ -719,7 +723,7 @@ namespace Umbraco.Web.Editors
{
var entities = Services.EntityService.GetAll(objectType.Value, keys)
.WhereNotNull()
.Select(Mapper.Map<EntityBasic>);
.Select(MapEntities());
// entities are in "some" order, put them back in order
var xref = entities.ToDictionary(x => x.Key);
@@ -751,7 +755,7 @@ namespace Umbraco.Web.Editors
{
var entities = Services.EntityService.GetAll(objectType.Value, ids)
.WhereNotNull()
.Select(Mapper.Map<EntityBasic>);
.Select(MapEntities());
// entities are in "some" order, put them back in order
var xref = entities.ToDictionary(x => x.Id);
@@ -815,7 +819,7 @@ namespace Umbraco.Web.Editors
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return Mapper.Map<EntityBasic>(found);
return MapEntity(found);
}
//now we need to convert the unknown ones
switch (entityType)
@@ -886,7 +890,7 @@ namespace Umbraco.Web.Editors
if (objectType.HasValue)
{
// TODO: Should we order this by something ?
var entities = Services.EntityService.GetAll(objectType.Value).WhereNotNull().Select(Mapper.Map<EntityBasic>);
var entities = Services.EntityService.GetAll(objectType.Value).WhereNotNull().Select(MapEntities());
return ExecutePostFilter(entities, postFilter);
}
//now we need to convert the unknown ones
@@ -895,13 +899,13 @@ namespace Umbraco.Web.Editors
case UmbracoEntityTypes.Template:
var templates = Services.FileService.GetTemplates();
var filteredTemplates = ExecutePostFilter(templates, postFilter);
return filteredTemplates.Select(Mapper.Map<EntityBasic>);
return filteredTemplates.Select(MapEntities());
case UmbracoEntityTypes.Macro:
//Get all macros from the macro service
var macros = Services.MacroService.GetAll().WhereNotNull().OrderBy(x => x.Name);
var filteredMacros = ExecutePostFilter(macros, postFilter);
return filteredMacros.Select(Mapper.Map<EntityBasic>);
return filteredMacros.Select(MapEntities());
case UmbracoEntityTypes.PropertyType:
@@ -936,14 +940,14 @@ namespace Umbraco.Web.Editors
if (!postFilter.IsNullOrWhiteSpace())
throw new NotSupportedException("Filtering on stylesheets is not currently supported");
return Services.FileService.GetStylesheets().Select(Mapper.Map<EntityBasic>);
return Services.FileService.GetStylesheets().Select(MapEntities());
case UmbracoEntityTypes.Language:
if (!postFilter.IsNullOrWhiteSpace() )
throw new NotSupportedException("Filtering on languages is not currently supported");
return Services.LocalizationService.GetAllLanguages().Select(Mapper.Map<EntityBasic>);
return Services.LocalizationService.GetAllLanguages().Select(MapEntities());
case UmbracoEntityTypes.DictionaryItem:
if (!postFilter.IsNullOrWhiteSpace())
@@ -1039,8 +1043,19 @@ namespace Umbraco.Web.Editors
return queryCondition;
}
private Func<object, EntityBasic> MapEntities(string culture = null)
{
culture = culture ?? ClientCulture();
return x => MapEntity(x, culture);
}
private EntityBasic MapEntity(object entity, string culture = null)
{
culture = culture ?? ClientCulture();
return Mapper.Map<EntityBasic>(entity, opts => { opts.SetCulture(culture); });
}
private string ClientCulture() => Request.ClientCulture();
#region Methods to get all dictionary items
private IEnumerable<EntityBasic> GetAllDictionaryItems()

View File

@@ -139,7 +139,7 @@ namespace Umbraco.Web.Models.Mapping
// if we don't have a name for a culture, it means the culture is not available, and
// hey we should probably not be mapping it, but it's too late, return a fallback name
return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"(({source.Name}))";
return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"({source.Name})";
}
}

View File

@@ -209,7 +209,7 @@ namespace Umbraco.Web.Models.Mapping
// if we don't have a name for a culture, it means the culture is not available, and
// hey we should probably not be mapping it, but it's too late, return a fallback name
return doc.CultureNames.TryGetValue(culture, out var name) && !name.IsNullOrWhiteSpace() ? name : $"(({source.Name}))";
return doc.CultureNames.TryGetValue(culture, out var name) && !name.IsNullOrWhiteSpace() ? name : $"({source.Name})";
}
}
}

View File

@@ -1,7 +1,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Formatting;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
using Umbraco.Core;
namespace Umbraco.Web.WebApi.Filters
{
@@ -21,7 +23,13 @@ namespace Umbraco.Web.WebApi.Filters
{
if (actionContext.Request.Properties["MS_QueryNameValuePairs"] is IEnumerable<KeyValuePair<string, string>> queryStrings)
{
var formData = new FormDataCollection(queryStrings);
var queryStringKeys = queryStrings.Select(kvp => kvp.Key).ToArray();
var additionalParameters = new Dictionary<string, string>();
if(queryStringKeys.InvariantContains("culture") == false) {
additionalParameters["culture"] = actionContext.Request.ClientCulture();
}
var formData = new FormDataCollection(queryStrings.Union(additionalParameters));
bindingContext.Model = formData;
return true;
}
@@ -29,4 +37,4 @@ namespace Umbraco.Web.WebApi.Filters
return false;
}
}
}
}

View File

@@ -1,4 +1,6 @@
using System;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
@@ -158,6 +160,11 @@ namespace Umbraco.Web.WebApi
msg.Headers.Add("X-Status-Reason", "Validation failed");
return msg;
}
public static string ClientCulture(this HttpRequestMessage request)
{
return request.Headers.Contains("X-UMB-CULTURE") ? request.Headers.GetValues("X-UMB-CULTURE").First() : null;
}
}
}