Merge remote-tracking branch 'origin/v10/dev' into v10/feature/nullable-reference-types-in-Umbraco-Core
# Conflicts: # build/build.ps1 # src/Umbraco.Core/Configuration/ConfigConnectionString.cs # src/Umbraco.Core/Configuration/Models/ConnectionStrings.cs # src/Umbraco.Core/Install/InstallSteps/TelemetryIdentifierStep.cs # src/Umbraco.Core/Models/ContentType.cs # src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs # tests/Umbraco.Tests.AcceptanceTest/package.json
This commit is contained in:
@@ -92,8 +92,8 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
|
||||
var sqlClause = Sql()
|
||||
.SelectAll()
|
||||
.From<PropertyTypeGroupDto>()
|
||||
.RightJoin<PropertyTypeDto>()
|
||||
.From<PropertyTypeDto>()
|
||||
.LeftJoin<PropertyTypeGroupDto>()
|
||||
.On<PropertyTypeGroupDto, PropertyTypeDto>(left => left.Id, right => right.PropertyTypeGroupId)
|
||||
.InnerJoin<DataTypeDto>()
|
||||
.On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.NodeId);
|
||||
|
||||
@@ -757,7 +757,7 @@ AND umbracoNode.id <> @id",
|
||||
//now we need to insert names into these 2 tables based on the invariant data
|
||||
|
||||
//insert rows into the versionCultureVariationDto table based on the data from contentVersionDto for the default lang
|
||||
var cols = Sql().Columns<ContentVersionCultureVariationDto>(x => x.VersionId, x => x.Name, x => x.UpdateUserId, x => x.UpdateDate, x => x.LanguageId);
|
||||
var cols = Sql().ColumnsForInsert<ContentVersionCultureVariationDto>(x => x.VersionId, x => x.Name, x => x.UpdateUserId, x => x.UpdateDate, x => x.LanguageId);
|
||||
sqlSelect = Sql().Select<ContentVersionDto>(x => x.Id, x => x.Text, x => x.UserId, x => x.VersionDate)
|
||||
.Append($", {defaultLanguageId}") //default language ID
|
||||
.From<ContentVersionDto>()
|
||||
@@ -768,7 +768,7 @@ AND umbracoNode.id <> @id",
|
||||
Database.Execute(sqlInsert);
|
||||
|
||||
//insert rows into the documentCultureVariation table
|
||||
cols = Sql().Columns<DocumentCultureVariationDto>(x => x.NodeId, x => x.Edited, x => x.Published, x => x.Name, x => x.Available, x => x.LanguageId);
|
||||
cols = Sql().ColumnsForInsert<DocumentCultureVariationDto>(x => x.NodeId, x => x.Edited, x => x.Published, x => x.Name, x => x.Available, x => x.LanguageId);
|
||||
sqlSelect = Sql().Select<DocumentDto>(x => x.NodeId, x => x.Edited, x => x.Published)
|
||||
.AndSelect<NodeDto>(x => x.Text)
|
||||
.Append($", 1, {defaultLanguageId}") //make Available + default language ID
|
||||
@@ -856,7 +856,7 @@ AND umbracoNode.id <> @id",
|
||||
.WhereNull<TagDto>(x => x.Id, "xtags") // ie, not exists
|
||||
.Where<TagDto>(x => x.LanguageId.SqlNullableEquals(sourceLanguageId, -1));
|
||||
|
||||
var cols = Sql().Columns<TagDto>(x => x.Text, x => x.Group, x => x.LanguageId);
|
||||
var cols = Sql().ColumnsForInsert<TagDto>(x => x.Text, x => x.Group, x => x.LanguageId);
|
||||
var sqlInsertTags = Sql($"INSERT INTO {TagDto.TableName} ({cols})").Append(sqlSelectTagsToInsert);
|
||||
|
||||
Database.Execute(sqlInsertTags);
|
||||
@@ -884,7 +884,7 @@ AND umbracoNode.id <> @id",
|
||||
.Where<TagDto>(x => x.LanguageId.SqlNullableEquals(sourceLanguageId, -1))
|
||||
.WhereIn<TagRelationshipDto>(x => x.PropertyTypeId, propertyTypeIds);
|
||||
|
||||
var relationColumnsToInsert = Sql().Columns<TagRelationshipDto>(x => x.NodeId, x => x.PropertyTypeId, x => x.TagId);
|
||||
var relationColumnsToInsert = Sql().ColumnsForInsert<TagRelationshipDto>(x => x.NodeId, x => x.PropertyTypeId, x => x.TagId);
|
||||
var sqlInsertRelations = Sql($"INSERT INTO {TagRelationshipDto.TableName} ({relationColumnsToInsert})").Append(sqlSelectRelationsToInsert);
|
||||
|
||||
Database.Execute(sqlInsertRelations);
|
||||
@@ -972,7 +972,7 @@ AND umbracoNode.id <> @id",
|
||||
|
||||
//now insert all property data into the target language that exists under the source language
|
||||
var targetLanguageIdS = targetLanguageId.HasValue ? targetLanguageId.ToString() : "NULL";
|
||||
var cols = Sql().Columns<PropertyDataDto>(x => x.VersionId, x => x.PropertyTypeId, x => x.Segment, x => x.IntegerValue, x => x.DecimalValue, x => x.DateValue, x => x.VarcharValue, x => x.TextValue, x => x.LanguageId);
|
||||
var cols = Sql().ColumnsForInsert<PropertyDataDto>(x => x.VersionId, x => x.PropertyTypeId, x => x.Segment, x => x.IntegerValue, x => x.DecimalValue, x => x.DateValue, x => x.VarcharValue, x => x.TextValue, x => x.LanguageId);
|
||||
var sqlSelectData = Sql().Select<PropertyDataDto>(x => x.VersionId, x => x.PropertyTypeId, x => x.Segment, x => x.IntegerValue, x => x.DecimalValue, x => x.DateValue, x => x.VarcharValue, x => x.TextValue)
|
||||
.Append(", " + targetLanguageIdS) //default language ID
|
||||
.From<PropertyDataDto>();
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
private readonly IMacroService _macroService;
|
||||
private readonly IContentTypeService _contentTypeService;
|
||||
private readonly string _tempFolderPath;
|
||||
private readonly string _mediaFolderPath;
|
||||
private readonly string _createdPackagesFolderPath;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CreatedPackageSchemaRepository"/> class.
|
||||
@@ -76,9 +76,8 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
_macroService = macroService;
|
||||
_contentTypeService = contentTypeService;
|
||||
_xmlParser = new PackageDefinitionXmlParser();
|
||||
_mediaFolderPath = mediaFolderPath ?? Path.Combine(globalSettings.Value.UmbracoMediaPhysicalRootPath, Constants.SystemDirectories.CreatedPackages);
|
||||
_tempFolderPath =
|
||||
tempFolderPath ?? Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "PackageFiles";
|
||||
_createdPackagesFolderPath = mediaFolderPath ?? Constants.SystemDirectories.CreatedPackages;
|
||||
_tempFolderPath = tempFolderPath ?? Constants.SystemDirectories.TempData + "/PackageFiles";
|
||||
}
|
||||
|
||||
public IEnumerable<PackageDefinition> GetAll()
|
||||
@@ -137,7 +136,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
.Delete<CreatedPackageSchemaDto>()
|
||||
.Where<CreatedPackageSchemaDto>(x => x.Id == id);
|
||||
|
||||
_umbracoDatabase.Delete<CreatedPackageSchemaDto>(query);
|
||||
_umbracoDatabase.Execute(query);
|
||||
}
|
||||
|
||||
public bool SavePackage(PackageDefinition definition)
|
||||
@@ -168,10 +167,8 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
};
|
||||
|
||||
// Set the ids, we have to save in database first to get the Id
|
||||
definition.PackageId = dto.PackageId;
|
||||
var result = _umbracoDatabase.Insert(dto);
|
||||
var decimalResult = result.SafeCast<decimal>();
|
||||
definition.Id = decimal.ToInt32(decimalResult);
|
||||
_umbracoDatabase.Insert(dto);
|
||||
definition.Id = dto.Id;
|
||||
}
|
||||
|
||||
// Save snapshot locally, we do this to the updated packagePath
|
||||
@@ -192,17 +189,12 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
|
||||
public string ExportPackage(PackageDefinition definition)
|
||||
{
|
||||
|
||||
// Ensure it's valid
|
||||
ValidatePackage(definition);
|
||||
|
||||
// Create a folder for building this package
|
||||
var temporaryPath =
|
||||
_hostingEnvironment.MapPathContentRoot(_tempFolderPath.EnsureEndsWith('/') + Guid.NewGuid());
|
||||
if (Directory.Exists(temporaryPath) == false)
|
||||
{
|
||||
Directory.CreateDirectory(temporaryPath);
|
||||
}
|
||||
var temporaryPath = _hostingEnvironment.MapPathContentRoot(Path.Combine(_tempFolderPath, Guid.NewGuid().ToString()));
|
||||
Directory.CreateDirectory(temporaryPath);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -218,8 +210,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
PackageTemplates(definition, root);
|
||||
PackageStylesheets(definition, root);
|
||||
PackageStaticFiles(definition.Scripts, root, "Scripts", "Script", _fileSystems.ScriptsFileSystem);
|
||||
PackageStaticFiles(definition.PartialViews, root, "PartialViews", "View",
|
||||
_fileSystems.PartialViewsFileSystem);
|
||||
PackageStaticFiles(definition.PartialViews, root, "PartialViews", "View", _fileSystems.PartialViewsFileSystem);
|
||||
PackageMacros(definition, root);
|
||||
PackageDictionaryItems(definition, root);
|
||||
PackageLanguages(definition, root);
|
||||
@@ -265,27 +256,25 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
}
|
||||
}
|
||||
|
||||
var directoryName =
|
||||
_hostingEnvironment.MapPathWebRoot(
|
||||
Path.Combine(_mediaFolderPath, definition.Name.Replace(' ', '_')));
|
||||
|
||||
if (Directory.Exists(directoryName) == false)
|
||||
{
|
||||
Directory.CreateDirectory(directoryName);
|
||||
}
|
||||
var directoryName = _hostingEnvironment.MapPathContentRoot(Path.Combine(_createdPackagesFolderPath, definition.Name.Replace(' ', '_')));
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
var finalPackagePath = Path.Combine(directoryName, fileName);
|
||||
|
||||
if (File.Exists(finalPackagePath))
|
||||
// Clean existing files
|
||||
foreach (var packagePath in new[]
|
||||
{
|
||||
File.Delete(finalPackagePath);
|
||||
}
|
||||
|
||||
if (File.Exists(finalPackagePath.Replace("zip", "xml")))
|
||||
{
|
||||
File.Delete(finalPackagePath.Replace("zip", "xml"));
|
||||
definition.PackagePath,
|
||||
finalPackagePath
|
||||
})
|
||||
{
|
||||
if (File.Exists(packagePath))
|
||||
{
|
||||
File.Delete(packagePath);
|
||||
}
|
||||
}
|
||||
|
||||
// Move to final package path
|
||||
File.Move(tempPackagePath, finalPackagePath);
|
||||
|
||||
definition.PackagePath = finalPackagePath;
|
||||
|
||||
@@ -356,7 +356,8 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
.On<NodeDto, DocumentCultureVariationDto, LanguageDto>((node, dcv, lang) => node.NodeId == dcv.NodeId && lang.Id == dcv.LanguageId, aliasRight: "dcv")
|
||||
|
||||
// for selected nodes
|
||||
.WhereIn<NodeDto>(x => x.NodeId, ids);
|
||||
.WhereIn<NodeDto>(x => x.NodeId, ids)
|
||||
.OrderBy<LanguageDto>(x => x.Id);
|
||||
}
|
||||
|
||||
// gets the full sql for a given object type and a given unique id
|
||||
|
||||
@@ -296,7 +296,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
=> forUpdate ? Sql()
|
||||
.Select<ExternalLoginTokenDto>(r => r.Select(x => x.ExternalLoginDto))
|
||||
.From<ExternalLoginTokenDto>()
|
||||
.Append(" WITH (UPDLOCK)") // ensure these table values are locked for updates, the ForUpdate ext method does not work here
|
||||
.AppendForUpdateHint() // ensure these table values are locked for updates, the ForUpdate ext method does not work here
|
||||
.InnerJoin<ExternalLoginDto>()
|
||||
.On<ExternalLoginTokenDto, ExternalLoginDto>(x => x.ExternalLoginId, x => x.Id)
|
||||
: Sql()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NPoco;
|
||||
using Umbraco.Cms.Core;
|
||||
@@ -171,6 +172,11 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
}
|
||||
|
||||
public IEnumerable<IUmbracoEntity> GetPagedParentEntitiesByChildId(int childId, long pageIndex, int pageSize, out long totalRecords, params Guid[] entityTypes)
|
||||
{
|
||||
return GetPagedParentEntitiesByChildId(childId, pageIndex, pageSize, out totalRecords, new int[0], entityTypes);
|
||||
}
|
||||
|
||||
public IEnumerable<IUmbracoEntity> GetPagedParentEntitiesByChildId(int childId, long pageIndex, int pageSize, out long totalRecords, int[] relationTypes, params Guid[] entityTypes)
|
||||
{
|
||||
// var contentObjectTypes = new[] { Constants.ObjectTypes.Document, Constants.ObjectTypes.Media, Constants.ObjectTypes.Member }
|
||||
// we could pass in the contentObjectTypes so that the entity repository sql is configured to do full entity lookups so that we get the full data
|
||||
@@ -184,10 +190,36 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
|
||||
sql.Where<RelationDto>(rel => rel.ChildId == childId);
|
||||
sql.Where<RelationDto, NodeDto>((rel, node) => rel.ParentId == childId || node.NodeId != childId);
|
||||
|
||||
if (relationTypes != null && relationTypes.Any())
|
||||
{
|
||||
sql.WhereIn<RelationDto>(rel => rel.RelationType, relationTypes);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public IEnumerable<IUmbracoEntity> GetPagedParentEntitiesByChildIds(int[] childIds, long pageIndex, int pageSize, out long totalRecords, int[] relationTypes, params Guid[] entityTypes)
|
||||
{
|
||||
return _entityRepository.GetPagedResultsByQuery(Query<IUmbracoEntity>(), entityTypes, pageIndex, pageSize, out totalRecords, null, null, sql =>
|
||||
{
|
||||
SqlJoinRelations(sql);
|
||||
|
||||
sql.WhereIn<RelationDto>(rel => rel.ChildId, childIds);
|
||||
sql.WhereAny(s => s.WhereIn<RelationDto>(rel => rel.ParentId, childIds), s => s.WhereNotIn<NodeDto>(node => node.NodeId, childIds));
|
||||
|
||||
if (relationTypes != null && relationTypes.Any())
|
||||
{
|
||||
sql.WhereIn<RelationDto>(rel => rel.RelationType, relationTypes);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public IEnumerable<IUmbracoEntity> GetPagedChildEntitiesByParentId(int parentId, long pageIndex, int pageSize, out long totalRecords, params Guid[] entityTypes)
|
||||
{
|
||||
return GetPagedChildEntitiesByParentId(parentId, pageIndex, pageSize, out totalRecords, new int[0], entityTypes);
|
||||
}
|
||||
|
||||
public IEnumerable<IUmbracoEntity> GetPagedChildEntitiesByParentId(int parentId, long pageIndex, int pageSize, out long totalRecords, int[] relationTypes, params Guid[] entityTypes)
|
||||
{
|
||||
// var contentObjectTypes = new[] { Constants.ObjectTypes.Document, Constants.ObjectTypes.Media, Constants.ObjectTypes.Member }
|
||||
// we could pass in the contentObjectTypes so that the entity repository sql is configured to do full entity lookups so that we get the full data
|
||||
@@ -201,9 +233,29 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
|
||||
sql.Where<RelationDto>(rel => rel.ParentId == parentId);
|
||||
sql.Where<RelationDto, NodeDto>((rel, node) => rel.ChildId == parentId || node.NodeId != parentId);
|
||||
|
||||
if (relationTypes != null && relationTypes.Any())
|
||||
{
|
||||
sql.WhereIn<RelationDto>(rel => rel.RelationType, relationTypes);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public IEnumerable<IUmbracoEntity> GetPagedEntitiesForItemsInRelation(int[] itemIds, long pageIndex, int pageSize, out long totalRecords, params Guid[] entityTypes)
|
||||
{
|
||||
return _entityRepository.GetPagedResultsByQuery(Query<IUmbracoEntity>(), entityTypes, pageIndex, pageSize, out totalRecords, null, null, sql =>
|
||||
{
|
||||
SqlJoinRelations(sql);
|
||||
|
||||
sql.WhereIn<RelationDto>(rel => rel.ChildId, itemIds);
|
||||
sql.Where<RelationDto, NodeDto>((rel, node) => rel.ChildId == node.NodeId);
|
||||
sql.Where<RelationTypeDto>(type => type.IsDependency);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void Save(IEnumerable<IRelation> relations)
|
||||
{
|
||||
foreach (var hasIdentityGroup in relations.GroupBy(r => r.HasIdentity))
|
||||
@@ -313,8 +365,11 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
|
||||
public void DeleteByParent(int parentId, params string[] relationTypeAliases)
|
||||
{
|
||||
if (Database.DatabaseType.IsSqlCe())
|
||||
// HACK: SQLite - hard to replace this without provider specific repositories/another ORM.
|
||||
if (Database.DatabaseType.IsSqlite())
|
||||
{
|
||||
var query = Sql().Append(@"delete from umbracoRelation");
|
||||
|
||||
var subQuery = Sql().Select<RelationDto>(x => x.Id)
|
||||
.From<RelationDto>()
|
||||
.InnerJoin<RelationTypeDto>().On<RelationDto, RelationTypeDto>(x => x.RelationType, x => x.Id)
|
||||
@@ -325,8 +380,9 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
subQuery.WhereIn<RelationTypeDto>(x => x.Alias, relationTypeAliases);
|
||||
}
|
||||
|
||||
Database.Execute(Sql().Delete<RelationDto>().WhereIn<RelationDto>(x => x.Id, subQuery));
|
||||
var fullQuery = query.WhereIn<RelationDto>(x => x.Id, subQuery);
|
||||
|
||||
Database.Execute(fullQuery);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -399,4 +455,42 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
sql.OrderByDescending(orderBy);
|
||||
}
|
||||
}
|
||||
|
||||
internal class RelationItemDto
|
||||
{
|
||||
[Column(Name = "nodeId")]
|
||||
public int ChildNodeId { get; set; }
|
||||
|
||||
[Column(Name = "nodeKey")]
|
||||
public Guid ChildNodeKey { get; set; }
|
||||
|
||||
[Column(Name = "nodeName")]
|
||||
public string ChildNodeName { get; set; }
|
||||
|
||||
[Column(Name = "nodeObjectType")]
|
||||
public Guid ChildNodeObjectType { get; set; }
|
||||
|
||||
[Column(Name = "contentTypeIcon")]
|
||||
public string ChildContentTypeIcon { get; set; }
|
||||
|
||||
[Column(Name = "contentTypeAlias")]
|
||||
public string ChildContentTypeAlias { get; set; }
|
||||
|
||||
[Column(Name = "contentTypeName")]
|
||||
public string ChildContentTypeName { get; set; }
|
||||
|
||||
|
||||
|
||||
[Column(Name = "relationTypeName")]
|
||||
public string RelationTypeName { get; set; }
|
||||
|
||||
[Column(Name = "relationTypeAlias")]
|
||||
public string RelationTypeAlias { get; set; }
|
||||
|
||||
[Column(Name = "relationTypeIsDependency")]
|
||||
public bool RelationTypeIsDependency { get; set; }
|
||||
|
||||
[Column(Name = "relationTypeIsBidirectional")]
|
||||
public bool RelationTypeIsBidirectional { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -51,7 +51,22 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
}
|
||||
}
|
||||
|
||||
// no suffix - name without suffix does NOT exist, AND name with suffix does NOT exist
|
||||
// no suffix - name without suffix does NOT exist - we can just use the name without suffix.
|
||||
if (!model.Suffix.HasValue && !items.SimpleNameExists(model.Text))
|
||||
{
|
||||
model.Suffix = StructuredName.NO_SUFFIX;
|
||||
|
||||
return model.FullName;
|
||||
}
|
||||
|
||||
// suffix - name with suffix does NOT exist
|
||||
// We can just return the full name as it is as there's no conflict.
|
||||
if (model.Suffix.HasValue && !items.SimpleNameExists(model.FullName))
|
||||
{
|
||||
return model.FullName;
|
||||
}
|
||||
|
||||
// no suffix - name without suffix does NOT exist, AND name with suffix does NOT exist
|
||||
if (!model.Suffix.HasValue && !items.SimpleNameExists(model.Text) && !items.SuffixedNameExists())
|
||||
{
|
||||
model.Suffix = StructuredName.NO_SUFFIX;
|
||||
@@ -163,7 +178,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
internal static readonly uint? NO_SUFFIX = default;
|
||||
|
||||
internal string Text { get; set; }
|
||||
internal uint ? Suffix { get; set; }
|
||||
internal uint? Suffix { get; set; }
|
||||
public string FullName
|
||||
{
|
||||
get
|
||||
|
||||
@@ -210,7 +210,16 @@ WHERE r.tagId IS NULL";
|
||||
sql.Append(" UNION ");
|
||||
}
|
||||
|
||||
sql.Append("SELECT N'");
|
||||
// HACK: SQLite (or rather SQL server setup was a hack)
|
||||
if (SqlContext.DatabaseType.IsSqlServer())
|
||||
{
|
||||
sql.Append("SELECT N'");
|
||||
}
|
||||
else
|
||||
{
|
||||
sql.Append("SELECT '");
|
||||
}
|
||||
|
||||
sql.Append(SqlSyntax.EscapeString(tag.Text));
|
||||
sql.Append("' AS tag, '");
|
||||
sql.Append(SqlSyntax.EscapeString(tag.Group));
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NPoco;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Persistence;
|
||||
using Umbraco.Cms.Core.Persistence.Repositories;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
using Umbraco.Cms.Infrastructure.Scoping;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
{
|
||||
internal class TrackedReferencesRepository : ITrackedReferencesRepository
|
||||
{
|
||||
private readonly IScopeAccessor _scopeAccessor;
|
||||
|
||||
public TrackedReferencesRepository(IScopeAccessor scopeAccessor)
|
||||
{
|
||||
_scopeAccessor = scopeAccessor;
|
||||
}
|
||||
|
||||
public IEnumerable<RelationItem> GetPagedItemsWithRelations(int[] ids, long pageIndex, int pageSize,
|
||||
bool filterMustBeIsDependency, out long totalRecords)
|
||||
{
|
||||
var sql = _scopeAccessor.AmbientScope.Database.SqlContext.Sql().Select(
|
||||
"[pn].[id] as nodeId",
|
||||
"[pn].[uniqueId] as nodeKey",
|
||||
"[pn].[text] as nodeName",
|
||||
"[pn].[nodeObjectType] as nodeObjectType",
|
||||
"[ct].[icon] as contentTypeIcon",
|
||||
"[ct].[alias] as contentTypeAlias",
|
||||
"[ctn].[text] as contentTypeName",
|
||||
"[umbracoRelationType].[alias] as relationTypeAlias",
|
||||
"[umbracoRelationType].[name] as relationTypeName",
|
||||
"[umbracoRelationType].[isDependency] as relationTypeIsDependency",
|
||||
"[umbracoRelationType].[dual] as relationTypeIsBidirectional")
|
||||
.From<RelationDto>("r")
|
||||
.InnerJoin<RelationTypeDto>("umbracoRelationType").On<RelationDto, RelationTypeDto>((left, right) => left.RelationType == right.Id, aliasLeft: "r", aliasRight:"umbracoRelationType")
|
||||
.InnerJoin<NodeDto>("cn").On<RelationDto, NodeDto, RelationTypeDto>((r, cn, rt) => (!rt.Dual && r.ParentId == cn.NodeId) || (rt.Dual && (r.ChildId == cn.NodeId || r.ParentId == cn.NodeId )), aliasLeft: "r", aliasRight:"cn", aliasOther: "umbracoRelationType" )
|
||||
.InnerJoin<NodeDto>("pn").On<RelationDto, NodeDto, NodeDto>((r, pn, cn) => (pn.NodeId == r.ChildId && cn.NodeId == r.ParentId) || (pn.NodeId == r.ParentId && cn.NodeId == r.ChildId), aliasLeft: "r", aliasRight:"pn", aliasOther:"cn" )
|
||||
.LeftJoin<ContentDto>("c").On<NodeDto, ContentDto>((left, right) => left.NodeId == right.NodeId, aliasLeft:"pn", aliasRight:"c")
|
||||
.LeftJoin<ContentTypeDto>("ct").On<ContentDto, ContentTypeDto>((left, right) => left.ContentTypeId == right.NodeId, aliasLeft:"c", aliasRight:"ct")
|
||||
.LeftJoin<NodeDto>("ctn").On<ContentTypeDto, NodeDto>((left, right) => left.NodeId == right.NodeId, aliasLeft:"ct", aliasRight:"ctn");
|
||||
|
||||
if (ids.Any())
|
||||
{
|
||||
sql = sql.Where<NodeDto>(x => ids.Contains(x.NodeId), "pn");
|
||||
}
|
||||
|
||||
if (filterMustBeIsDependency)
|
||||
{
|
||||
sql = sql.Where<RelationTypeDto>(rt => rt.IsDependency, "umbracoRelationType");
|
||||
}
|
||||
|
||||
// Ordering is required for paging
|
||||
sql = sql.OrderBy<RelationTypeDto>(x => x.Alias);
|
||||
|
||||
var pagedResult = _scopeAccessor.AmbientScope.Database.Page<RelationItemDto>(pageIndex + 1, pageSize, sql);
|
||||
totalRecords = Convert.ToInt32(pagedResult.TotalItems);
|
||||
|
||||
return pagedResult.Items.Select(MapDtoToEntity);
|
||||
}
|
||||
|
||||
public IEnumerable<RelationItem> GetPagedDescendantsInReferences(int parentId, long pageIndex, int pageSize, bool filterMustBeIsDependency,
|
||||
out long totalRecords)
|
||||
{
|
||||
var syntax = _scopeAccessor.AmbientScope.Database.SqlContext.SqlSyntax;
|
||||
|
||||
// Gets the path of the parent with ",%" added
|
||||
var subsubQuery = _scopeAccessor.AmbientScope.Database.SqlContext.Sql()
|
||||
.Select(syntax.GetConcat("[node].[path]", "',%'"))
|
||||
.From<NodeDto>("node")
|
||||
.Where<NodeDto>(x => x.NodeId == parentId, "node");
|
||||
|
||||
|
||||
// Gets the descendants of the parent node
|
||||
Sql<ISqlContext> subQuery = _scopeAccessor.AmbientScope.Database.SqlContext.Sql()
|
||||
.Select<NodeDto>(x => x.NodeId)
|
||||
.From<NodeDto>()
|
||||
.WhereLike<NodeDto>(x => x.Path, subsubQuery);
|
||||
|
||||
// Get all relations where parent is in the sub query
|
||||
var sql = _scopeAccessor.AmbientScope.Database.SqlContext.Sql().Select(
|
||||
"[pn].[id] as nodeId",
|
||||
"[pn].[uniqueId] as nodeKey",
|
||||
"[pn].[text] as nodeName",
|
||||
"[pn].[nodeObjectType] as nodeObjectType",
|
||||
"[ct].[icon] as contentTypeIcon",
|
||||
"[ct].[alias] as contentTypeAlias",
|
||||
"[ctn].[text] as contentTypeName",
|
||||
"[umbracoRelationType].[alias] as relationTypeAlias",
|
||||
"[umbracoRelationType].[name] as relationTypeName",
|
||||
"[umbracoRelationType].[isDependency] as relationTypeIsDependency",
|
||||
"[umbracoRelationType].[dual] as relationTypeIsBidirectional")
|
||||
.From<RelationDto>("r")
|
||||
.InnerJoin<RelationTypeDto>("umbracoRelationType").On<RelationDto, RelationTypeDto>((left, right) => left.RelationType == right.Id, aliasLeft: "r", aliasRight:"umbracoRelationType")
|
||||
.InnerJoin<NodeDto>("cn").On<RelationDto, NodeDto, RelationTypeDto>((r, cn, rt) => (!rt.Dual && r.ParentId == cn.NodeId) || (rt.Dual && (r.ChildId == cn.NodeId || r.ParentId == cn.NodeId )), aliasLeft: "r", aliasRight:"cn", aliasOther: "umbracoRelationType" )
|
||||
.InnerJoin<NodeDto>("pn").On<RelationDto, NodeDto, NodeDto>((r, pn, cn) => (pn.NodeId == r.ChildId && cn.NodeId == r.ParentId) || (pn.NodeId == r.ParentId && cn.NodeId == r.ChildId), aliasLeft: "r", aliasRight:"pn", aliasOther:"cn" )
|
||||
.LeftJoin<ContentDto>("c").On<NodeDto, ContentDto>((left, right) => left.NodeId == right.NodeId, aliasLeft:"pn", aliasRight:"c")
|
||||
.LeftJoin<ContentTypeDto>("ct").On<ContentDto, ContentTypeDto>((left, right) => left.ContentTypeId == right.NodeId, aliasLeft:"c", aliasRight:"ct")
|
||||
.LeftJoin<NodeDto>("ctn").On<ContentTypeDto, NodeDto>((left, right) => left.NodeId == right.NodeId, aliasLeft:"ct", aliasRight:"ctn")
|
||||
.WhereIn((System.Linq.Expressions.Expression<Func<NodeDto, object>>)(x => x.NodeId), subQuery, "pn");
|
||||
if (filterMustBeIsDependency)
|
||||
{
|
||||
sql = sql.Where<RelationTypeDto>(rt => rt.IsDependency, "umbracoRelationType");
|
||||
}
|
||||
// Ordering is required for paging
|
||||
sql = sql.OrderBy<RelationTypeDto>(x => x.Alias);
|
||||
|
||||
var pagedResult = _scopeAccessor.AmbientScope.Database.Page<RelationItemDto>(pageIndex + 1, pageSize, sql);
|
||||
totalRecords = Convert.ToInt32(pagedResult.TotalItems);
|
||||
|
||||
return pagedResult.Items.Select(MapDtoToEntity);
|
||||
}
|
||||
|
||||
public IEnumerable<RelationItem> GetPagedRelationsForItems(int[] ids, long pageIndex, int pageSize, bool filterMustBeIsDependency, out long totalRecords)
|
||||
{
|
||||
var sql = _scopeAccessor.AmbientScope.Database.SqlContext.Sql().Select(
|
||||
"[cn].[id] as nodeId",
|
||||
"[cn].[uniqueId] as nodeKey",
|
||||
"[cn].[text] as nodeName",
|
||||
"[cn].[nodeObjectType] as nodeObjectType",
|
||||
"[ct].[icon] as contentTypeIcon",
|
||||
"[ct].[alias] as contentTypeAlias",
|
||||
"[ctn].[text] as contentTypeName",
|
||||
"[umbracoRelationType].[alias] as relationTypeAlias",
|
||||
"[umbracoRelationType].[name] as relationTypeName",
|
||||
"[umbracoRelationType].[isDependency] as relationTypeIsDependency",
|
||||
"[umbracoRelationType].[dual] as relationTypeIsBidirectional")
|
||||
.From<RelationDto>("r")
|
||||
.InnerJoin<RelationTypeDto>("umbracoRelationType").On<RelationDto, RelationTypeDto>((left, right) => left.RelationType == right.Id, aliasLeft: "r", aliasRight:"umbracoRelationType")
|
||||
.InnerJoin<NodeDto>("cn").On<RelationDto, NodeDto, RelationTypeDto>((r, cn, rt) => (!rt.Dual && r.ParentId == cn.NodeId) || (rt.Dual && (r.ChildId == cn.NodeId || r.ParentId == cn.NodeId )), aliasLeft: "r", aliasRight:"cn", aliasOther: "umbracoRelationType" )
|
||||
.InnerJoin<NodeDto>("pn").On<RelationDto, NodeDto, NodeDto>((r, pn, cn) => (pn.NodeId == r.ChildId && cn.NodeId == r.ParentId) || (pn.NodeId == r.ParentId && cn.NodeId == r.ChildId), aliasLeft: "r", aliasRight:"pn", aliasOther:"cn" )
|
||||
.LeftJoin<ContentDto>("c").On<NodeDto, ContentDto>((left, right) => left.NodeId == right.NodeId, aliasLeft:"cn", aliasRight:"c")
|
||||
.LeftJoin<ContentTypeDto>("ct").On<ContentDto, ContentTypeDto>((left, right) => left.ContentTypeId == right.NodeId, aliasLeft:"c", aliasRight:"ct")
|
||||
.LeftJoin<NodeDto>("ctn").On<ContentTypeDto, NodeDto>((left, right) => left.NodeId == right.NodeId, aliasLeft:"ct", aliasRight:"ctn");
|
||||
|
||||
if (ids.Any())
|
||||
{
|
||||
sql = sql.Where<NodeDto>(x => ids.Contains(x.NodeId), "pn");
|
||||
}
|
||||
|
||||
if (filterMustBeIsDependency)
|
||||
{
|
||||
sql = sql.Where<RelationTypeDto>(rt => rt.IsDependency, "umbracoRelationType");
|
||||
}
|
||||
|
||||
// Ordering is required for paging
|
||||
sql = sql.OrderBy<RelationTypeDto>(x => x.Alias);
|
||||
|
||||
var pagedResult = _scopeAccessor.AmbientScope.Database.Page<RelationItemDto>(pageIndex + 1, pageSize, sql);
|
||||
totalRecords = Convert.ToInt32(pagedResult.TotalItems);
|
||||
|
||||
return pagedResult.Items.Select(MapDtoToEntity);
|
||||
}
|
||||
|
||||
private RelationItem MapDtoToEntity(RelationItemDto dto)
|
||||
{
|
||||
var type = ObjectTypes.GetUdiType(dto.ChildNodeObjectType);
|
||||
return new RelationItem()
|
||||
{
|
||||
NodeId = dto.ChildNodeId,
|
||||
NodeKey = dto.ChildNodeKey,
|
||||
NodeType = ObjectTypes.GetUdiType(dto.ChildNodeObjectType),
|
||||
NodeName = dto.ChildNodeName,
|
||||
RelationTypeName = dto.RelationTypeName,
|
||||
RelationTypeIsBidirectional = dto.RelationTypeIsBidirectional,
|
||||
RelationTypeIsDependency = dto.RelationTypeIsDependency,
|
||||
ContentTypeAlias = dto.ChildContentTypeAlias,
|
||||
ContentTypeIcon = dto.ChildContentTypeIcon,
|
||||
ContentTypeName = dto.ChildContentTypeName,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,10 +225,10 @@ SELECT 4 AS [Key], COUNT(id) AS [Value] FROM umbracoUser WHERE userDisabled = 0
|
||||
// that query is going to run a *lot*, make it a template
|
||||
var t = SqlContext.Templates.Get("Umbraco.Core.UserRepository.ValidateLoginSession", s => s
|
||||
.Select<UserLoginDto>()
|
||||
.SelectTop(1)
|
||||
.From<UserLoginDto>()
|
||||
.Where<UserLoginDto>(x => x.SessionId == SqlTemplate.Arg<Guid>("sessionId"))
|
||||
.ForUpdate());
|
||||
.ForUpdate()
|
||||
.SelectTop(1)); // Stick at end, SQL server syntax provider will insert at start of query after "select ", but sqlite will append limit to end.
|
||||
|
||||
var sql = t.Sql(sessionId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user