|
|
|
|
@@ -9,6 +9,7 @@ using Umbraco.Core.Persistence.Dtos;
|
|
|
|
|
using Umbraco.Core.Persistence.Querying;
|
|
|
|
|
using Umbraco.Core.Scoping;
|
|
|
|
|
using static Umbraco.Core.Persistence.NPocoSqlExtensions.Statics;
|
|
|
|
|
using Umbraco.Core.Persistence.SqlSyntax;
|
|
|
|
|
|
|
|
|
|
namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
{
|
|
|
|
|
@@ -34,6 +35,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
|
|
|
|
|
protected IUmbracoDatabase Database => _scopeAccessor.AmbientScope.Database;
|
|
|
|
|
protected Sql<ISqlContext> Sql() => _scopeAccessor.AmbientScope.SqlContext.Sql();
|
|
|
|
|
protected ISqlSyntaxProvider SqlSyntax => _scopeAccessor.AmbientScope.SqlContext.SqlSyntax;
|
|
|
|
|
|
|
|
|
|
#region Repository
|
|
|
|
|
|
|
|
|
|
@@ -57,83 +59,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
//fixme - we should be able to do sql = sql.OrderBy(x => Alias(x.NodeId, "NodeId")); but we can't because the OrderBy extension don't support Alias currently
|
|
|
|
|
sql = sql.OrderBy("NodeId");
|
|
|
|
|
|
|
|
|
|
//IEnumerable<IUmbracoEntity> result;
|
|
|
|
|
//
|
|
|
|
|
//if (isMedia)
|
|
|
|
|
//{
|
|
|
|
|
// //Treat media differently for now, as an Entity it will be returned with ALL of it's properties in the AdditionalData bag!
|
|
|
|
|
// var pagedResult = UnitOfWork.Database.Page<dynamic>(pageIndex + 1, pageSize, pagedSql);
|
|
|
|
|
|
|
|
|
|
// var ids = pagedResult.Items.Select(x => (int)x.id).InGroupsOf(2000);
|
|
|
|
|
// var entities = pagedResult.Items.Select(BuildEntityFromDynamic).Cast<IUmbracoEntity>().ToList();
|
|
|
|
|
|
|
|
|
|
// //Now we need to merge in the property data since we need paging and we can't do this the way that the big media query was working before
|
|
|
|
|
// foreach (var idGroup in ids)
|
|
|
|
|
// {
|
|
|
|
|
// var propSql = GetPropertySql(Constants.ObjectTypes.Media)
|
|
|
|
|
// .WhereIn<NodeDto>(x => x.NodeId, idGroup)
|
|
|
|
|
// .OrderBy<NodeDto>(x => x.NodeId);
|
|
|
|
|
|
|
|
|
|
// //This does NOT fetch all data into memory in a list, this will read
|
|
|
|
|
// // over the records as a data reader, this is much better for performance and memory,
|
|
|
|
|
// // but it means that during the reading of this data set, nothing else can be read
|
|
|
|
|
// // from SQL server otherwise we'll get an exception.
|
|
|
|
|
// var allPropertyData = UnitOfWork.Database.Query<dynamic>(propSql);
|
|
|
|
|
|
|
|
|
|
// //keep track of the current property data item being enumerated
|
|
|
|
|
// var propertyDataSetEnumerator = allPropertyData.GetEnumerator();
|
|
|
|
|
// var hasCurrent = false; // initially there is no enumerator.Current
|
|
|
|
|
|
|
|
|
|
// try
|
|
|
|
|
// {
|
|
|
|
|
// //This must be sorted by node id (which is done by SQL) because this is how we are sorting the query to lookup property types above,
|
|
|
|
|
// // which allows us to more efficiently iterate over the large data set of property values.
|
|
|
|
|
// foreach (var entity in entities)
|
|
|
|
|
// {
|
|
|
|
|
// // assemble the dtos for this def
|
|
|
|
|
// // use the available enumerator.Current if any else move to next
|
|
|
|
|
// while (hasCurrent || propertyDataSetEnumerator.MoveNext())
|
|
|
|
|
// {
|
|
|
|
|
// if (propertyDataSetEnumerator.Current.nodeId == entity.Id)
|
|
|
|
|
// {
|
|
|
|
|
// hasCurrent = false; // enumerator.Current is not available
|
|
|
|
|
|
|
|
|
|
// //the property data goes into the additional data
|
|
|
|
|
// entity.AdditionalData[propertyDataSetEnumerator.Current.propertyTypeAlias] = new UmbracoEntity.EntityProperty
|
|
|
|
|
// {
|
|
|
|
|
// PropertyEditorAlias = propertyDataSetEnumerator.Current.propertyEditorAlias,
|
|
|
|
|
// Value = StringExtensions.IsNullOrWhiteSpace(propertyDataSetEnumerator.Current.textValue)
|
|
|
|
|
// ? propertyDataSetEnumerator.Current.varcharValue
|
|
|
|
|
// : StringExtensions.ConvertToJsonIfPossible(propertyDataSetEnumerator.Current.textValue)
|
|
|
|
|
// };
|
|
|
|
|
// }
|
|
|
|
|
// else
|
|
|
|
|
// {
|
|
|
|
|
// hasCurrent = true; // enumerator.Current is available for another def
|
|
|
|
|
// break; // no more propertyDataDto for this def
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// finally
|
|
|
|
|
// {
|
|
|
|
|
// propertyDataSetEnumerator.Dispose();
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// result = entities;
|
|
|
|
|
//}
|
|
|
|
|
//else
|
|
|
|
|
//{
|
|
|
|
|
// var pagedResult = UnitOfWork.Database.Page<dynamic>(pageIndex + 1, pageSize, pagedSql);
|
|
|
|
|
// result = pagedResult.Items.Select(BuildEntityFromDynamic).Cast<IUmbracoEntity>().ToList();
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
var page = Database.Page<BaseDto>(pageIndex + 1, pageSize, sql);
|
|
|
|
|
var dtos = page.Items;
|
|
|
|
|
var entities = dtos.Select(x => BuildEntity(isContent, isMedia, x)).ToArray();
|
|
|
|
|
|
|
|
|
|
//TODO: For isContent will we need to build up the variation info?
|
|
|
|
|
|
|
|
|
|
if (isContent)
|
|
|
|
|
BuildVariantInfo(entities);
|
|
|
|
|
|
|
|
|
|
if (isMedia)
|
|
|
|
|
BuildProperties(entities, dtos);
|
|
|
|
|
@@ -158,7 +90,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
ddto => ddto.VariationInfo,
|
|
|
|
|
ddto => ddto.VersionId,
|
|
|
|
|
sql);
|
|
|
|
|
return dtos.Count == 0 ? null : BuildDocumentEntity(dtos[0]);
|
|
|
|
|
|
|
|
|
|
return dtos.Count == 0 ? null : BuildVariantInfo(BuildDocumentEntity(dtos[0]))[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var dto = Database.FirstOrDefault<BaseDto>(sql);
|
|
|
|
|
@@ -220,9 +153,10 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
dto => dto.VariationInfo,
|
|
|
|
|
dto => dto.VersionId,
|
|
|
|
|
sql);
|
|
|
|
|
|
|
|
|
|
return cdtos.Count == 0
|
|
|
|
|
? Enumerable.Empty<IEntitySlim>()
|
|
|
|
|
: cdtos.Select(BuildDocumentEntity).ToArray();
|
|
|
|
|
: BuildVariantInfo(cdtos.Select(BuildDocumentEntity).ToArray()).ToList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var dtos = Database.Fetch<BaseDto>(sql);
|
|
|
|
|
@@ -323,7 +257,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
|
|
|
|
|
private void BuildProperties(EntitySlim[] entities, List<BaseDto> dtos)
|
|
|
|
|
{
|
|
|
|
|
var versionIds = dtos.Select(x => x.VersionId).Distinct().ToArray();
|
|
|
|
|
var versionIds = dtos.Select(x => x.VersionId).Distinct().ToList();
|
|
|
|
|
var pdtos = Database.FetchByGroups<PropertyDataDto, int>(versionIds, 2000, GetPropertyData);
|
|
|
|
|
|
|
|
|
|
var xentity = entities.ToDictionary(x => x.Id, x => x); // nodeId -> entity
|
|
|
|
|
@@ -346,10 +280,54 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
entity.AdditionalData[pdto.PropertyTypeDto.Alias] = new EntitySlim.PropertySlim(pdto.PropertyTypeDto.DataTypeDto.EditorAlias, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void BuildVariantInfo(EntitySlim[] entities)
|
|
|
|
|
{
|
|
|
|
|
BuildVariantInfo((DocumentEntitySlim[])entities);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private DocumentEntitySlim[] BuildVariantInfo(params DocumentEntitySlim[] entities)
|
|
|
|
|
{
|
|
|
|
|
if (entities.Any(x => x.Variations.VariesByCulture()))
|
|
|
|
|
{
|
|
|
|
|
//each EntitySlim at this stage is an DocumentEntitySlim
|
|
|
|
|
|
|
|
|
|
var dtos = Database.FetchByGroups<VariationPublishInfoDto, int>(entities.Select(x => x.Id), 2000, GetVariantPublishedInfo)
|
|
|
|
|
.GroupBy(x => x.NodeId)
|
|
|
|
|
.ToDictionary(x => x.Key, x => (IEnumerable<VariationPublishInfoDto>)x);
|
|
|
|
|
|
|
|
|
|
foreach (var e in entities.OfType<DocumentEntitySlim>().Where(x => x.Variations.VariesByCulture()).OrderBy(x => x.Id))
|
|
|
|
|
{
|
|
|
|
|
//fixme: how do i get this info? Seems that requires another query since that is how I think it's done in the DocumentRepository
|
|
|
|
|
//e.EditedCultures =
|
|
|
|
|
e.PublishedCultures = dtos[e.Id].Where(x => x.VersionPublished).Select(x => x.IsoCode).Distinct().ToList();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return entities;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Sql
|
|
|
|
|
|
|
|
|
|
private Sql<ISqlContext> GetVariantPublishedInfo(IEnumerable<int> ids)
|
|
|
|
|
{
|
|
|
|
|
var sql = Sql();
|
|
|
|
|
sql
|
|
|
|
|
.Select<ContentVersionDto>(x => x.NodeId, x => Alias(x.Id, "versionId"), x => Alias(x.Current, "versionCurrent"))
|
|
|
|
|
.AndSelect<ContentVersionCultureVariationDto>(x => Alias(x.Id, "versionCultureId"))
|
|
|
|
|
.AndSelect<LanguageDto>(x => x.IsoCode)
|
|
|
|
|
.AndSelect<DocumentVersionDto>(x => Alias(x.Published, "versionPublished"))
|
|
|
|
|
.From<NodeDto>()
|
|
|
|
|
.InnerJoin<ContentVersionDto>().On<NodeDto, ContentVersionDto>(x => x.NodeId, x => x.NodeId)
|
|
|
|
|
.InnerJoin<ContentVersionCultureVariationDto>().On<ContentVersionDto, ContentVersionCultureVariationDto>(x => x.Id, x => x.VersionId)
|
|
|
|
|
.InnerJoin<DocumentVersionDto>().On<ContentVersionDto, DocumentVersionDto>(x => x.Id, x => x.Id)
|
|
|
|
|
.InnerJoin<LanguageDto>().On<ContentVersionCultureVariationDto, LanguageDto>(x => x.LanguageId, x => x.Id)
|
|
|
|
|
.Where<NodeDto>(x => x.NodeObjectType == Constants.ObjectTypes.Document)
|
|
|
|
|
.WhereIn<NodeDto>(x => x.NodeId, ids)
|
|
|
|
|
.Where($"{SqlSyntax.GetFieldName<ContentVersionDto>(x => x.Current)} = 1 OR {SqlSyntax.GetFieldName<DocumentVersionDto>(x => x.Published)} = 1");
|
|
|
|
|
return sql;
|
|
|
|
|
}
|
|
|
|
|
// gets the full sql for a given object type and a given unique id
|
|
|
|
|
protected Sql<ISqlContext> GetFullSqlForEntityType(bool isContent, bool isMedia, Guid objectType, Guid uniqueId)
|
|
|
|
|
{
|
|
|
|
|
@@ -371,24 +349,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
return AddGroupBy(isContent, isMedia, sql);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fixme kill this nonsense
|
|
|
|
|
//// gets the SELECT + FROM + WHERE sql
|
|
|
|
|
//// to get all property data for all items of the specified object type
|
|
|
|
|
//private Sql<ISqlContext> GetPropertySql(Guid objectType)
|
|
|
|
|
//{
|
|
|
|
|
// return Sql()
|
|
|
|
|
// .Select<PropertyDataDto>(x => x.VersionId, x => x.TextValue, x => x.VarcharValue)
|
|
|
|
|
// .AndSelect<NodeDto>(x => x.NodeId)
|
|
|
|
|
// .AndSelect<DataTypeDto>(x => x.PropertyEditorAlias)
|
|
|
|
|
// .AndSelect<PropertyTypeDto>(x => Alias(x.Alias, "propertyTypeAlias"))
|
|
|
|
|
// .From<PropertyDataDto>()
|
|
|
|
|
// .InnerJoin<ContentVersionDto>().On<PropertyDataDto, ContentVersionDto>((left, right) => left.VersionId == right.Id)
|
|
|
|
|
// .InnerJoin<NodeDto>().On<ContentVersionDto, NodeDto>((left, right) => left.NodeId == right.NodeId)
|
|
|
|
|
// .InnerJoin<PropertyTypeDto>().On<PropertyDataDto, PropertyTypeDto>(dto => dto.PropertyTypeId, dto => dto.Id)
|
|
|
|
|
// .InnerJoin<DataTypeDto>().On<PropertyTypeDto, DataTypeDto>(dto => dto.DataTypeId, dto => dto.DataTypeId)
|
|
|
|
|
// .Where<NodeDto>(x => x.NodeObjectType == objectType);
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
private Sql<ISqlContext> GetPropertyData(int versionId)
|
|
|
|
|
{
|
|
|
|
|
return Sql()
|
|
|
|
|
@@ -410,89 +370,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
.OrderBy<PropertyDataDto>(x => x.VersionId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fixme - wtf is this?
|
|
|
|
|
//private Sql<ISqlContext> GetFullSqlForMedia(Sql<ISqlContext> entitySql, Action<Sql<ISqlContext>> filter = null)
|
|
|
|
|
//{
|
|
|
|
|
// //this will add any varcharValue property to the output which can be added to the additional properties
|
|
|
|
|
|
|
|
|
|
// var sql = GetPropertySql(Constants.ObjectTypes.Media);
|
|
|
|
|
|
|
|
|
|
// filter?.Invoke(sql);
|
|
|
|
|
|
|
|
|
|
// // We're going to create a query to query against the entity SQL
|
|
|
|
|
// // because we cannot group by nText columns and we have a COUNT in the entitySql we cannot simply left join
|
|
|
|
|
// // the entitySql query, we have to join the wrapped query to get the ntext in the result
|
|
|
|
|
|
|
|
|
|
// var wrappedSql = Sql()
|
|
|
|
|
// .Append("SELECT * FROM (")
|
|
|
|
|
// .Append(entitySql)
|
|
|
|
|
// .Append(") tmpTbl LEFT JOIN (")
|
|
|
|
|
// .Append(sql)
|
|
|
|
|
// .Append(") as property ON id = property.nodeId")
|
|
|
|
|
// .OrderBy("sortOrder, id");
|
|
|
|
|
|
|
|
|
|
// return wrappedSql;
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The DTO used to fetch results for a content item with its variation info
|
|
|
|
|
/// </summary>
|
|
|
|
|
private class ContentEntityDto : BaseDto
|
|
|
|
|
{
|
|
|
|
|
public ContentVariation Variations { get; set; }
|
|
|
|
|
|
|
|
|
|
[ResultColumn, Reference(ReferenceType.Many)]
|
|
|
|
|
public List<ContentEntityVariationInfoDto> VariationInfo { get; set; }
|
|
|
|
|
|
|
|
|
|
public bool Published { get; set; }
|
|
|
|
|
public bool Edited { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The DTO used in the 1:M result for content variation info
|
|
|
|
|
/// </summary>
|
|
|
|
|
private class ContentEntityVariationInfoDto
|
|
|
|
|
{
|
|
|
|
|
[Column("versionCultureId")]
|
|
|
|
|
public int VersionCultureId { get; set; }
|
|
|
|
|
[Column("versionCultureLangId")]
|
|
|
|
|
public int LanguageId { get; set; }
|
|
|
|
|
[Column("versionCultureName")]
|
|
|
|
|
public string Name { get; set; }
|
|
|
|
|
[Column("versionCultureEdited")]
|
|
|
|
|
public bool Edited { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ReSharper disable once ClassNeverInstantiated.Local
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// the DTO corresponding to fields selected by GetBase
|
|
|
|
|
/// </summary>
|
|
|
|
|
private class BaseDto
|
|
|
|
|
{
|
|
|
|
|
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
|
|
|
|
// ReSharper disable UnusedMember.Local
|
|
|
|
|
public int NodeId { get; set; }
|
|
|
|
|
public bool Trashed { get; set; }
|
|
|
|
|
public int ParentId { get; set; }
|
|
|
|
|
public int? UserId { get; set; }
|
|
|
|
|
public int Level { get; set; }
|
|
|
|
|
public string Path { get; set; }
|
|
|
|
|
public int SortOrder { get; set; }
|
|
|
|
|
public Guid UniqueId { get; set; }
|
|
|
|
|
public string Text { get; set; }
|
|
|
|
|
public Guid NodeObjectType { get; set; }
|
|
|
|
|
public DateTime CreateDate { get; set; }
|
|
|
|
|
public int Children { get; set; }
|
|
|
|
|
public int VersionId { get; set; }
|
|
|
|
|
public string Alias { get; set; }
|
|
|
|
|
public string Icon { get; set; }
|
|
|
|
|
public string Thumbnail { get; set; }
|
|
|
|
|
public bool IsContainer { get; set; }
|
|
|
|
|
|
|
|
|
|
// ReSharper restore UnusedAutoPropertyAccessor.Local
|
|
|
|
|
// ReSharper restore UnusedMember.Local
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// gets the base SELECT + FROM [+ filter] sql
|
|
|
|
|
// always from the 'current' content version
|
|
|
|
|
@@ -524,8 +402,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
.AndSelect<ContentVersionCultureVariationDto>(
|
|
|
|
|
x => Alias(x.Id, "versionCultureId"),
|
|
|
|
|
x => Alias(x.LanguageId, "versionCultureLangId"),
|
|
|
|
|
x => Alias(x.Name, "versionCultureName"),
|
|
|
|
|
x => Alias(x.Edited, "versionCultureEdited"));
|
|
|
|
|
x => Alias(x.Name, "versionCultureName"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -537,7 +414,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
sql
|
|
|
|
|
.InnerJoin<ContentVersionDto>().On<NodeDto, ContentVersionDto>((left, right) => left.NodeId == right.NodeId && right.Current)
|
|
|
|
|
.InnerJoin<ContentDto>().On<NodeDto, ContentDto>((left, right) => left.NodeId == right.NodeId)
|
|
|
|
|
.LeftJoin<ContentTypeDto>().On<ContentDto, ContentTypeDto>((left, right) => left.ContentTypeId == right.NodeId);
|
|
|
|
|
.InnerJoin<ContentTypeDto>().On<ContentDto, ContentTypeDto>((left, right) => left.ContentTypeId == right.NodeId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isContent)
|
|
|
|
|
@@ -652,184 +529,73 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
public string TextValue { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fixme kill
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// This is a special relator in that it is not returning a DTO but a real resolved entity and that it accepts
|
|
|
|
|
/// a dynamic instance.
|
|
|
|
|
/// The DTO used to fetch results for a content item with its variation info
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// We're doing this because when we query the db, we want to use dynamic so that it returns all available fields not just the ones
|
|
|
|
|
/// defined on the entity so we can them to additional data
|
|
|
|
|
/// </remarks>
|
|
|
|
|
//internal class UmbracoEntityRelator
|
|
|
|
|
//{
|
|
|
|
|
// internal UmbracoEntity Current;
|
|
|
|
|
private class ContentEntityDto : BaseDto
|
|
|
|
|
{
|
|
|
|
|
public ContentVariation Variations { get; set; }
|
|
|
|
|
|
|
|
|
|
// public IEnumerable<IUmbracoEntity> MapAll(IEnumerable<dynamic> input)
|
|
|
|
|
// {
|
|
|
|
|
// UmbracoEntity entity;
|
|
|
|
|
[ResultColumn, Reference(ReferenceType.Many)]
|
|
|
|
|
public List<ContentEntityVariationInfoDto> VariationInfo { get; set; }
|
|
|
|
|
|
|
|
|
|
// foreach (var x in input)
|
|
|
|
|
// {
|
|
|
|
|
// entity = Map(x);
|
|
|
|
|
// if (entity != null) yield return entity;
|
|
|
|
|
// }
|
|
|
|
|
public bool Published { get; set; }
|
|
|
|
|
public bool Edited { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// entity = Map((dynamic) null);
|
|
|
|
|
// if (entity != null) yield return entity;
|
|
|
|
|
// }
|
|
|
|
|
private class VariationPublishInfoDto
|
|
|
|
|
{
|
|
|
|
|
public int NodeId { get; set; }
|
|
|
|
|
public int VersionId { get; set; }
|
|
|
|
|
public bool VersionCurrent { get; set; }
|
|
|
|
|
public string IsoCode { get; set; }
|
|
|
|
|
public int VersionCultureId { get; set; }
|
|
|
|
|
public bool VersionPublished { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// // must be called one last time with null in order to return the last one!
|
|
|
|
|
// public UmbracoEntity Map(dynamic a)
|
|
|
|
|
// {
|
|
|
|
|
// // Terminating call. Since we can return null from this function
|
|
|
|
|
// // we need to be ready for NPoco to callback later with null
|
|
|
|
|
// // parameters
|
|
|
|
|
// if (a == null)
|
|
|
|
|
// return Current;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The DTO used in the 1:M result for content variation info
|
|
|
|
|
/// </summary>
|
|
|
|
|
private class ContentEntityVariationInfoDto
|
|
|
|
|
{
|
|
|
|
|
[Column("versionCultureId")]
|
|
|
|
|
public int VersionCultureId { get; set; }
|
|
|
|
|
[Column("versionCultureLangId")]
|
|
|
|
|
public int LanguageId { get; set; }
|
|
|
|
|
[Column("versionCultureName")]
|
|
|
|
|
public string Name { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// string pPropertyEditorAlias = a.propertyEditorAlias;
|
|
|
|
|
// var pExists = pPropertyEditorAlias != null;
|
|
|
|
|
// string pPropertyAlias = a.propertyTypeAlias;
|
|
|
|
|
// string pTextValue = a.textValue;
|
|
|
|
|
// string pNVarcharValue = a.varcharValue;
|
|
|
|
|
|
|
|
|
|
// // Is this the same UmbracoEntity as the current one we're processing
|
|
|
|
|
// if (Current != null && Current.Key == a.uniqueID)
|
|
|
|
|
// {
|
|
|
|
|
// if (pExists && pPropertyAlias.IsNullOrWhiteSpace() == false)
|
|
|
|
|
// {
|
|
|
|
|
// // Add this UmbracoProperty to the current additional data
|
|
|
|
|
// Current.AdditionalData[pPropertyAlias] = new UmbracoEntity.EntityProperty
|
|
|
|
|
// {
|
|
|
|
|
// PropertyEditorAlias = pPropertyEditorAlias,
|
|
|
|
|
// Value = pTextValue.IsNullOrWhiteSpace()
|
|
|
|
|
// ? pNVarcharValue
|
|
|
|
|
// : pTextValue.ConvertToJsonIfPossible()
|
|
|
|
|
// };
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// // Return null to indicate we're not done with this UmbracoEntity yet
|
|
|
|
|
// return null;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// // This is a different UmbracoEntity to the current one, or this is the
|
|
|
|
|
// // first time through and we don't have a Tab yet
|
|
|
|
|
|
|
|
|
|
// // Save the current UmbracoEntityDto
|
|
|
|
|
// var prev = Current;
|
|
|
|
|
|
|
|
|
|
// // Setup the new current UmbracoEntity
|
|
|
|
|
|
|
|
|
|
// Current = BuildEntityFromDynamic(a);
|
|
|
|
|
|
|
|
|
|
// if (pExists && pPropertyAlias.IsNullOrWhiteSpace() == false)
|
|
|
|
|
// {
|
|
|
|
|
// //add the property/create the prop list if null
|
|
|
|
|
// Current.AdditionalData[pPropertyAlias] = new UmbracoEntity.EntityProperty
|
|
|
|
|
// {
|
|
|
|
|
// PropertyEditorAlias = pPropertyEditorAlias,
|
|
|
|
|
// Value = pTextValue.IsNullOrWhiteSpace()
|
|
|
|
|
// ? pNVarcharValue
|
|
|
|
|
// : pTextValue.ConvertToJsonIfPossible()
|
|
|
|
|
// };
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// // Return the now populated previous UmbracoEntity (or null if first time through)
|
|
|
|
|
// return prev;
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
// fixme need to review what's below
|
|
|
|
|
// comes from 7.6, similar to what's in VersionableRepositoryBase
|
|
|
|
|
// not sure it really makes sense...
|
|
|
|
|
|
|
|
|
|
//private class EntityDefinitionCollection : KeyedCollection<int, EntityDefinition>
|
|
|
|
|
//{
|
|
|
|
|
// protected override int GetKeyForItem(EntityDefinition item)
|
|
|
|
|
// {
|
|
|
|
|
// return item.Id;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// /// <summary>
|
|
|
|
|
// /// if this key already exists if it does then we need to check
|
|
|
|
|
// /// if the existing item is 'older' than the new item and if that is the case we'll replace the older one
|
|
|
|
|
// /// </summary>
|
|
|
|
|
// /// <param name="item"></param>
|
|
|
|
|
// /// <returns></returns>
|
|
|
|
|
// public bool AddOrUpdate(EntityDefinition item)
|
|
|
|
|
// {
|
|
|
|
|
// if (Dictionary == null)
|
|
|
|
|
// {
|
|
|
|
|
// Add(item);
|
|
|
|
|
// return true;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// var key = GetKeyForItem(item);
|
|
|
|
|
// if (TryGetValue(key, out EntityDefinition found))
|
|
|
|
|
// {
|
|
|
|
|
// //it already exists and it's older so we need to replace it
|
|
|
|
|
// if (item.VersionId > found.VersionId)
|
|
|
|
|
// {
|
|
|
|
|
// var currIndex = Items.IndexOf(found);
|
|
|
|
|
// if (currIndex == -1)
|
|
|
|
|
// throw new IndexOutOfRangeException("Could not find the item in the list: " + found.Id);
|
|
|
|
|
|
|
|
|
|
// //replace the current one with the newer one
|
|
|
|
|
// SetItem(currIndex, item);
|
|
|
|
|
// return true;
|
|
|
|
|
// }
|
|
|
|
|
// //could not add or update
|
|
|
|
|
// return false;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// Add(item);
|
|
|
|
|
// return true;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// private bool TryGetValue(int key, out EntityDefinition val)
|
|
|
|
|
// {
|
|
|
|
|
// if (Dictionary != null) return Dictionary.TryGetValue(key, out val);
|
|
|
|
|
|
|
|
|
|
// val = null;
|
|
|
|
|
// return false;
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
// fixme wtf is this, why dynamics here, this is horrible !!
|
|
|
|
|
//private class EntityDefinition
|
|
|
|
|
//{
|
|
|
|
|
// private readonly dynamic _entity;
|
|
|
|
|
// private readonly bool _isContent;
|
|
|
|
|
// private readonly bool _isMedia;
|
|
|
|
|
|
|
|
|
|
// public EntityDefinition(dynamic entity, bool isContent, bool isMedia)
|
|
|
|
|
// {
|
|
|
|
|
// _entity = entity;
|
|
|
|
|
// _isContent = isContent;
|
|
|
|
|
// _isMedia = isMedia;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// public IUmbracoEntity BuildFromDynamic()
|
|
|
|
|
// {
|
|
|
|
|
// return BuildEntityFromDynamic(_entity);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// public int Id => _entity.id;
|
|
|
|
|
|
|
|
|
|
// public int VersionId
|
|
|
|
|
// {
|
|
|
|
|
// get
|
|
|
|
|
// {
|
|
|
|
|
// if (_isContent || _isMedia)
|
|
|
|
|
// {
|
|
|
|
|
// return _entity.versionId;
|
|
|
|
|
// }
|
|
|
|
|
// return _entity.id;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
// ReSharper disable once ClassNeverInstantiated.Local
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// the DTO corresponding to fields selected by GetBase
|
|
|
|
|
/// </summary>
|
|
|
|
|
private class BaseDto
|
|
|
|
|
{
|
|
|
|
|
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
|
|
|
|
// ReSharper disable UnusedMember.Local
|
|
|
|
|
public int NodeId { get; set; }
|
|
|
|
|
public bool Trashed { get; set; }
|
|
|
|
|
public int ParentId { get; set; }
|
|
|
|
|
public int? UserId { get; set; }
|
|
|
|
|
public int Level { get; set; }
|
|
|
|
|
public string Path { get; set; }
|
|
|
|
|
public int SortOrder { get; set; }
|
|
|
|
|
public Guid UniqueId { get; set; }
|
|
|
|
|
public string Text { get; set; }
|
|
|
|
|
public Guid NodeObjectType { get; set; }
|
|
|
|
|
public DateTime CreateDate { get; set; }
|
|
|
|
|
public int Children { get; set; }
|
|
|
|
|
public int VersionId { get; set; }
|
|
|
|
|
public string Alias { get; set; }
|
|
|
|
|
public string Icon { get; set; }
|
|
|
|
|
public string Thumbnail { get; set; }
|
|
|
|
|
public bool IsContainer { get; set; }
|
|
|
|
|
|
|
|
|
|
// ReSharper restore UnusedAutoPropertyAccessor.Local
|
|
|
|
|
// ReSharper restore UnusedMember.Local
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Factory
|
|
|
|
|
@@ -914,21 +680,15 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
|
|
|
|
|
//fill in the variant info
|
|
|
|
|
if (dto.Variations.VariesByCulture() && dto.VariationInfo != null && dto.VariationInfo.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
//fixme: Currently require making a 2nd query to fill in publish status information for variants
|
|
|
|
|
|
|
|
|
|
var variantInfo = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
|
|
|
|
|
foreach (var info in dto.VariationInfo)
|
|
|
|
|
{
|
|
|
|
|
var isoCode = _langRepository.GetIsoCodeById(info.LanguageId);
|
|
|
|
|
if (isoCode != null)
|
|
|
|
|
variantInfo[isoCode] = info.Name;
|
|
|
|
|
|
|
|
|
|
if (dto.Published)
|
|
|
|
|
{
|
|
|
|
|
publishedCultures.Add(isoCode);
|
|
|
|
|
if (info.Edited)
|
|
|
|
|
{
|
|
|
|
|
editedCultures.Add(isoCode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
entity.CultureNames = variantInfo;
|
|
|
|
|
entity.Variations = dto.Variations;
|
|
|
|
|
|