Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V9: Merge v8 29-10-2021 #11538

Merged
merged 56 commits into from
Oct 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
c5ba23a
Add Constants.Sql.MaxParameterCount
ronaldbarendse Oct 13, 2021
a6b04a9
Replace arbitrary group size with constant
ronaldbarendse Oct 13, 2021
88a20cb
Minor query cleanup
ronaldbarendse Oct 13, 2021
1bc3290
Fix bugs in fetching more than 2000 items (permissions and culture va…
ronaldbarendse Oct 13, 2021
60be71d
Remove duplicated comment
ronaldbarendse Oct 13, 2021
b13f260
11343: Remove blocklist block on cancel
patrickdemooij9 Oct 11, 2021
809671b
Align template picking more towards the other pickers (#11363)
patrickdemooij9 Oct 21, 2021
aa6c5d4
Add fallback text
BatJan Oct 20, 2021
00d7422
V8/feature/app header localized titles (#11429)
prjseal Oct 22, 2021
79e8205
Remove comma
BatJan Oct 22, 2021
c61eaa2
Merge pull request #11369 from umbraco/v8/bugfix/maxparametercount
Oct 22, 2021
76879ca
Prevent github actions spam
Oct 25, 2021
9773726
Merge pull request #11489 from umbraco/v8/bugfix/prevent-github-actio…
Oct 25, 2021
45dec5c
Add missing fallack values
BatJan Oct 23, 2021
cdd4bd1
Merge branch 'v8/dev' into v8/contrib
nul800sebastiaan Oct 26, 2021
123bcee
Localization add tab text dutch (#11346)
erikjanwestendorp Oct 12, 2021
f9ed371
Add missing fallback texts
BatJan Oct 23, 2021
52f5662
Add missing fallback texts
BatJan Oct 23, 2021
bed34b9
Map missing values
BatJan Oct 23, 2021
8b4398c
Remove space
BatJan Oct 23, 2021
1ce05d4
Map missing text values
BatJan Oct 23, 2021
ad17207
Fix localizations
BatJan Oct 23, 2021
034e43d
Add missing text fallback values
BatJan Oct 23, 2021
1bffd97
Update noUiSlider to v15.5.0
bjarnef Oct 24, 2021
85c9d55
Add missing translations
BatJan Oct 23, 2021
2094101
Map missing translations
BatJan Oct 23, 2021
57634d5
Add missing fallback values
BatJan Oct 23, 2021
965ce91
Map missing fallback texts
BatJan Oct 23, 2021
f1998ca
Add missing fallback texts
BatJan Oct 26, 2021
0723749
Add missing fallback texts
BatJan Oct 26, 2021
87a8ea7
Add missing fallback texts
BatJan Oct 26, 2021
0d73d90
Add missing fallback texts
BatJan Oct 26, 2021
0eb0b18
Add missing fallback texts
BatJan Oct 26, 2021
7794d55
Add missing fallback texts
BatJan Oct 26, 2021
1fdfb2c
Add missing fallback texts
BatJan Oct 26, 2021
9777519
Add missing fallback texts
BatJan Oct 26, 2021
090fe7e
Add missing fallback texts
BatJan Oct 26, 2021
713f204
Add missing fallback texts
BatJan Oct 26, 2021
d1005c5
Add missing fallback texts
BatJan Oct 26, 2021
d131df1
Add missing fallback texts
BatJan Oct 26, 2021
cf40b90
update styling in rollback text - removes stray comma, slight change …
nathanwoulfe Oct 26, 2021
80c9c09
Add missing fallback values
BatJan Oct 26, 2021
57637da
Add missing fallback texts
BatJan Oct 26, 2021
35b0dda
Add missing fallback texts
BatJan Oct 26, 2021
e8970c0
Add missing fallback texts
BatJan Oct 26, 2021
5d4e1c6
Add missing fallback texts
BatJan Oct 26, 2021
f6854cd
Remove unused code
BatJan Oct 26, 2021
5f7c00d
Add missing fallback texts
BatJan Oct 26, 2021
612f529
Add new dictionary key
BatJan Oct 26, 2021
3ee289f
Update fallback texts and add an ind so label and input are paired pr…
BatJan Oct 26, 2021
f12c449
Map fallback texts
BatJan Oct 26, 2021
976711e
Publish hotkey doesn't work in RTE
Oct 22, 2021
ed16728
Change event name to `rte.shortcut.saveAndPublish`
Oct 22, 2021
b046098
Accept udt as extension in import document type (#11108)
bjarnef Oct 27, 2021
02bf616
Merge remote-tracking branch 'origin/v8/dev' into v9/feature/merge-v8…
bergmania Oct 29, 2021
bf5f136
Fix build after merge
bergmania Oct 29, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 12 additions & 33 deletions src/Umbraco.Core/Collections/StackQueue.cs
Original file line number Diff line number Diff line change
@@ -1,60 +1,39 @@
using System.Collections.Generic;

namespace Umbraco.Core.Collections
namespace Umbraco.Cms.Core.Collections
{
/// <summary>
/// Collection that can be both a queue and a stack.
/// Collection that can be both a queue and a stack.
/// </summary>
/// <typeparam name="T"></typeparam>
public class StackQueue<T>
{
private readonly LinkedList<T> _linkedList = new LinkedList<T>();
private readonly LinkedList<T> _linkedList = new();

public void Clear()
{
_linkedList.Clear();
}
public int Count => _linkedList.Count;

public void Push(T obj)
{
_linkedList.AddFirst(obj);
}
public void Clear() => _linkedList.Clear();

public void Enqueue(T obj)
{
_linkedList.AddFirst(obj);
}
public void Push(T obj) => _linkedList.AddFirst(obj);

public void Enqueue(T obj) => _linkedList.AddFirst(obj);

public T Pop()
{
var obj = _linkedList.First.Value;
T obj = _linkedList.First.Value;
_linkedList.RemoveFirst();
return obj;
}

public T Dequeue()
{
var obj = _linkedList.Last.Value;
T obj = _linkedList.Last.Value;
_linkedList.RemoveLast();
return obj;
}

public T PeekStack()
{
return _linkedList.First.Value;
}
public T PeekStack() => _linkedList.First.Value;

public T PeekQueue()
{
return _linkedList.Last.Value;
}

public int Count
{
get
{
return _linkedList.Count;
}
}
public T PeekQueue() => _linkedList.Last.Value;
}
}
18 changes: 18 additions & 0 deletions src/Umbraco.Core/Constants-Sql.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Umbraco.Cms.Core
{
public static partial class Constants
{
public static class Sql
{
/// <summary>
/// The maximum amount of parameters that can be used in a query.
/// </summary>
/// <remarks>
/// The actual limit is 2100
/// (https://docs.microsoft.com/en-us/sql/sql-server/maximum-capacity-specifications-for-sql-server),
/// but we want to ensure there's room for additional parameters if this value is used to create groups/batches.
/// </remarks>
public const int MaxParameterCount = 2000;
}
}
}
2 changes: 1 addition & 1 deletion src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ private void Map(IUserGroup source, UserGroupDisplay target, MapperContext conte
// the entity service due to too many Sql parameters.

var list = new List<IEntitySlim>();
foreach (var idGroup in allContentPermissions.Keys.InGroupsOf(2000))
foreach (var idGroup in allContentPermissions.Keys.InGroupsOf(Constants.Sql.MaxParameterCount))
list.AddRange(_entityService.GetAll(UmbracoObjectTypes.Document, idGroup.ToArray()));
contentEntities = list.ToArray();
}
Expand Down
108 changes: 54 additions & 54 deletions src/Umbraco.Core/Umbraco.Core.csproj
Original file line number Diff line number Diff line change
@@ -1,61 +1,61 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>Umbraco.Cms.Core</RootNamespace>
<Product>Umbraco CMS</Product>
<PackageId>Umbraco.Cms.Core</PackageId>
<Title>Umbraco CMS Core</Title>
<Description>Contains the core assembly needed to run Umbraco Cms. This package only contains the assembly, and can be used for package development. Use the template in the Umbraco.Templates package to setup Umbraco</Description>
<Product>Umbraco CMS</Product>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>Umbraco.Cms.Core</RootNamespace>
<Product>Umbraco CMS</Product>
<PackageId>Umbraco.Cms.Core</PackageId>
<Title>Umbraco CMS Core</Title>
<Description>Contains the core assembly needed to run Umbraco Cms. This package only contains the assembly, and can be used for package development. Use the template in the Umbraco.Templates package to setup Umbraco</Description>
<Product>Umbraco CMS</Product>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DocumentationFile>bin\Release\Umbraco.Core.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DocumentationFile>bin\Release\Umbraco.Core.xml</DocumentationFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="5.0.10" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.7.0" />
<PackageReference Include="System.Runtime.Caching" Version="5.0.0" />
<PackageReference Include="Umbraco.Code" Version="1.2.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0"/>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="5.0.10"/>
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0"/>
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0"/>
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0"/>
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0"/>
<PackageReference Include="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0"/>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0"/>
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.7.0"/>
<PackageReference Include="System.Runtime.Caching" Version="5.0.0"/>
<PackageReference Include="Umbraco.Code" Version="1.2.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Umbraco.Tests</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Umbraco.Tests.Common</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Umbraco.Tests.UnitTests</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Umbraco.Tests.Benchmarks</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Umbraco.Tests.Integration</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>DynamicProxyGenAssembly2</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Umbraco.Tests</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Umbraco.Tests.Common</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Umbraco.Tests.UnitTests</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Umbraco.Tests.Benchmarks</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Umbraco.Tests.Integration</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>DynamicProxyGenAssembly2</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="EmbeddedResources\**\*" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="EmbeddedResources\**\*"/>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,64 +1,76 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using NPoco;
using Umbraco.Cms.Core;
using Umbraco.Cms.Infrastructure.Persistence;

namespace Umbraco.Extensions
{
/// <summary>
/// Provides extension methods to NPoco Database class.
/// Provides extension methods to NPoco Database class.
/// </summary>
public static partial class NPocoDatabaseExtensions
{
/// <summary>
/// Configures NPoco's SqlBulkCopyHelper to use the correct SqlConnection and SqlTransaction instances from the underlying RetryDbConnection and ProfiledDbTransaction
/// Configures NPoco's SqlBulkCopyHelper to use the correct SqlConnection and SqlTransaction instances from the
/// underlying RetryDbConnection and ProfiledDbTransaction
/// </summary>
/// <remarks>
/// This is required to use NPoco's own <see cref="Database.InsertBulk{T}(IEnumerable{T})" /> method because we use wrapped DbConnection and DbTransaction instances.
/// NPoco's InsertBulk method only caters for efficient bulk inserting records for Sql Server, it does not cater for bulk inserting of records for
/// any other database type and in which case will just insert records one at a time.
/// NPoco's InsertBulk method also deals with updating the passed in entity's PK/ID once it's inserted whereas our own BulkInsertRecords methods
/// do not handle this scenario.
/// This is required to use NPoco's own <see cref="Database.InsertBulk{T}(IEnumerable{T})" /> method because we use
/// wrapped DbConnection and DbTransaction instances.
/// NPoco's InsertBulk method only caters for efficient bulk inserting records for Sql Server, it does not cater for
/// bulk inserting of records for
/// any other database type and in which case will just insert records one at a time.
/// NPoco's InsertBulk method also deals with updating the passed in entity's PK/ID once it's inserted whereas our own
/// BulkInsertRecords methods
/// do not handle this scenario.
/// </remarks>
public static void ConfigureNPocoBulkExtensions()
{

SqlBulkCopyHelper.SqlConnectionResolver = dbConn => GetTypedConnection<SqlConnection>(dbConn);
SqlBulkCopyHelper.SqlTransactionResolver = dbTran => GetTypedTransaction<SqlTransaction>(dbTran);
}


/// <summary>
/// Creates bulk-insert commands.
/// Creates bulk-insert commands.
/// </summary>
/// <typeparam name="T">The type of the records.</typeparam>
/// <param name="database">The database.</param>
/// <param name="records">The records.</param>
/// <returns>The sql commands to execute.</returns>
internal static IDbCommand[] GenerateBulkInsertCommands<T>(this IUmbracoDatabase database, T[] records)
{
if (database?.Connection == null) throw new ArgumentException("Null database?.connection.", nameof(database));
if (database?.Connection == null)
{
throw new ArgumentException("Null database?.connection.", nameof(database));
}

var pocoData = database.PocoDataFactory.ForType(typeof(T));
PocoData pocoData = database.PocoDataFactory.ForType(typeof(T));

// get columns to include, = number of parameters per row
var columns = pocoData.Columns.Where(c => IncludeColumn(pocoData, c)).ToArray();
KeyValuePair<string, PocoColumn>[] columns =
pocoData.Columns.Where(c => IncludeColumn(pocoData, c)).ToArray();
var paramsPerRecord = columns.Length;

// format columns to sql
var tableName = database.DatabaseType.EscapeTableName(pocoData.TableInfo.TableName);
var columnNames = string.Join(", ", columns.Select(c => tableName + "." + database.DatabaseType.EscapeSqlIdentifier(c.Key)));
var columnNames = string.Join(", ",
columns.Select(c => tableName + "." + database.DatabaseType.EscapeSqlIdentifier(c.Key)));

// example:
// assume 4168 records, each record containing 8 fields, ie 8 command parameters
// max 2100 parameter per command
// Math.Floor(2100 / 8) = 262 record per command
// 4168 / 262 = 15.908... = there will be 16 command in total
// (if we have disabled db parameters, then all records will be included, in only one command)
var recordsPerCommand = paramsPerRecord == 0 ? int.MaxValue : Convert.ToInt32(Math.Floor(2000.00 / paramsPerRecord));
var recordsPerCommand = paramsPerRecord == 0
? int.MaxValue
: Convert.ToInt32(Math.Floor((double)Constants.Sql.MaxParameterCount / paramsPerRecord));
var commandsCount = Convert.ToInt32(Math.Ceiling((double)records.Length / recordsPerCommand));

var commands = new IDbCommand[commandsCount];
Expand All @@ -67,43 +79,42 @@ internal static IDbCommand[] GenerateBulkInsertCommands<T>(this IUmbracoDatabase
var prefix = database.DatabaseType.GetParameterPrefix(database.ConnectionString);
for (var commandIndex = 0; commandIndex < commandsCount; commandIndex++)
{
var command = database.CreateCommand(database.Connection, CommandType.Text, string.Empty);
DbCommand command = database.CreateCommand(database.Connection, CommandType.Text, string.Empty);
var parameterIndex = 0;
var commandRecords = Math.Min(recordsPerCommand, recordsLeftToInsert);
var recordsValues = new string[commandRecords];
for (var commandRecordIndex = 0; commandRecordIndex < commandRecords; commandRecordIndex++, recordsIndex++, recordsLeftToInsert--)
for (var commandRecordIndex = 0;
commandRecordIndex < commandRecords;
commandRecordIndex++, recordsIndex++, recordsLeftToInsert--)
{
var record = records[recordsIndex];
T record = records[recordsIndex];
var recordValues = new string[columns.Length];
for (var columnIndex = 0; columnIndex < columns.Length; columnIndex++)
{
database.AddParameter(command, columns[columnIndex].Value.GetValue(record));
recordValues[columnIndex] = prefix + parameterIndex++;
}

recordsValues[commandRecordIndex] = "(" + string.Join(",", recordValues) + ")";
}

command.CommandText = $"INSERT INTO {tableName} ({columnNames}) VALUES {string.Join(", ", recordsValues)}";
command.CommandText =
$"INSERT INTO {tableName} ({columnNames}) VALUES {string.Join(", ", recordsValues)}";
commands[commandIndex] = command;
}

return commands;
}

/// <summary>
/// Determines whether a column should be part of a bulk-insert.
/// Determines whether a column should be part of a bulk-insert.
/// </summary>
/// <param name="pocoData">The PocoData object corresponding to the record's type.</param>
/// <param name="column">The column.</param>
/// <returns>A value indicating whether the column should be part of the bulk-insert.</returns>
/// <remarks>Columns that are primary keys and auto-incremental, or result columns, are excluded from bulk-inserts.</remarks>
public static bool IncludeColumn(PocoData pocoData, KeyValuePair<string, PocoColumn> column)
{
return column.Value.ResultColumn == false
&& (pocoData.TableInfo.AutoIncrement == false || column.Key != pocoData.TableInfo.PrimaryKey);
}



public static bool IncludeColumn(PocoData pocoData, KeyValuePair<string, PocoColumn> column) =>
column.Value.ResultColumn == false
&& (pocoData.TableInfo.AutoIncrement == false || column.Key != pocoData.TableInfo.PrimaryKey);
}
}
Loading