Compare commits

..

18 Commits

Author SHA1 Message Date
Sebastiaan Janssen af9c40e9ef Bumps version to 7.10.5 and updates CDF 2018-09-20 08:26:15 +02:00
Sebastiaan Janssen 861e5908a7 U4-11253 New Chrome 66 trimStart function is overriding the Umbraco Core trimStart polyfill 2018-04-20 10:35:21 +02:00
Shannon 75fb070825 U4-11246 When user belongs to groups and none of them have browse access and one or more have a custom start node applied a YSOD occurs 2018-04-19 16:20:18 +10:00
Shannon Deminick 8a0f32e980 Merge pull request #2595 from umbraco/temp-U4-11208
U4-11208 Error : "An item with the same key has already been added." into "Umbraco.Core.Services.IdkMap.Populate" method
2018-04-19 15:27:00 +10:00
Robert 15eb40aedb Removed code that populates content tree with duplicate start nodes. 2018-04-18 16:01:01 +02:00
Sebastiaan Janssen cc3e75dc63 U4-11208 Error : "An item with the same key has already been added." into "Umbraco.Core.Services.IdkMap.Populate" method 2018-04-18 15:14:16 +02:00
Sebastiaan Janssen eeaf17c857 Weird revert of a PR that was merged in before
(cherry picked from commit 94ed741dd5)
2018-04-18 12:18:44 +02:00
Dave Woestenborghs 21a8395142 U4-11216 Multiple Content Picker allows only one item when used as macro parameter (#2593)
U4-11216 set min and max number when used as parameter editor

(cherry picked from commit f25233ac2b)
2018-04-18 10:22:09 +02:00
Sebastiaan Janssen 7d171b1e95 Bumps version to 7.10.4 2018-04-17 15:46:39 +02:00
Sebastiaan Janssen d63061fade Merge pull request #2564 from leekelleher/U4-11184
U4-11184 - Nested Content PropertyValueEditor - return converted value, not update reference value
2018-04-17 15:33:14 +02:00
Sebastiaan Janssen 4664266b8d Bumps version to 7.10.3 2018-04-12 16:40:10 +02:00
Sebastiaan Janssen 5003a55aca Cherry picked - Fix scope leaks caused by database messenger [U4-11207] #2580 2018-04-12 16:32:34 +02:00
leekelleher 7225ec29fe Nested Content - enabled support for property-editors:
- Umbraco.CheckBoxList
- Umbraco.DropDownMultiple
- Umbraco.MacroContainer
- Umbraco.RadioButtonList
- Umbraco.MultipleTextstring
2018-04-05 17:17:34 +01:00
leekelleher cf1069e0e1 NestedContentPropertyEditor - code tidy-up
A little tidy-up of these class method. I noticed we were calling `ToString()` twice in places,
and the `ConfigureForDisplay` prevalues are already available as a Dictionary, so there's no need for an additional `ToDictionary` allocation.
2018-04-05 17:16:34 +01:00
leekelleher 99ce88228c U4-11184 - Nested Content PropertyValueEditor - return converted value, not update reference value
ConvertDbToString

We were updating the `property.Value` reference, which was having adverse effects on the editor value.
In the majority of cases this wasn't an issue, but it did mean that any prevalue-ID-based editors (e.g. dropdown list) had problems.

I've removed the call to the base method, we don't need it - here's what it does...
https://github.com/umbraco/Umbraco-CMS/blob/release-7.4.0/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs#L367

It attempts to convert the value to an XML-safe string, which is ultimately `ToString()` (if not null):
https://github.com/umbraco/Umbraco-CMS/blob/release-7.4.0/src/Umbraco.Core/ObjectExtensions.cs#L544

ConvertDbToEditor

Same as ConvertDbToString, we were updating the `property.Value` reference when we shouldn't be.
We should be returning the converted value, not updating the original reference value itself.

I've removed the call to the base method, we don't need it - it attempts to deserialize the JSON string that we've literally just serialized...
https://github.com/umbraco/Umbraco-CMS/blob/release-7.4.0/src/Umbraco.Core/PropertyEditors/PropertyValueEditor.cs#L283

So we can pass the List<object> value back, as this will be handled by Umbraco and handed by Angular.
2018-04-05 17:14:15 +01:00
Warren edb62b740b Merge branch 'patch-v7' into dev-v7 2018-04-05 10:42:41 +01:00
Shannon 11d4189c8d Merge branch 'patch-v7' into dev-v7 2018-04-05 17:28:46 +10:00
Warren ebbd05dc97 Adds in missing $scope dependency for Dynamic Dashboard Controller 2018-04-04 08:30:33 +01:00
28 changed files with 177 additions and 117 deletions
+1 -1
View File
@@ -28,7 +28,7 @@
<dependency id="HtmlAgilityPack" version="[1.4.9.5, 2.0.0)" />
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
<dependency id="MySql.Data" version="[6.9.9, 7.0.0)" />
<dependency id="ClientDependency" version="[1.9.6, 2.0.0)" />
<dependency id="ClientDependency" version="[1.9.7, 2.0.0)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.10.2")]
[assembly: AssemblyInformationalVersion("7.10.2")]
[assembly: AssemblyFileVersion("7.10.5")]
[assembly: AssemblyInformationalVersion("7.10.5")]
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.10.2");
private static readonly Version Version = new Version("7.10.5");
/// <summary>
/// Gets the current version of Umbraco.
+7 -8
View File
@@ -402,7 +402,7 @@ namespace Umbraco.Core.Persistence
}
// Helper to handle named parameters from object properties
static Regex rxParams = new Regex(@"(?<!@)@\w+", RegexOptions.Compiled);
static readonly Regex rxParams = new Regex(@"(?<!@)@\w+", RegexOptions.Compiled);
public static string ProcessParams(string _sql, object[] args_src, List<object> args_dest)
{
return rxParams.Replace(_sql, m =>
@@ -545,7 +545,7 @@ namespace Umbraco.Core.Persistence
}
// Create a command
static Regex rxParamsPrefix = new Regex(@"(?<!@)@\w+", RegexOptions.Compiled);
static readonly Regex rxParamsPrefix = new Regex(@"(?<!@)@\w+", RegexOptions.Compiled);
public IDbCommand CreateCommand(IDbConnection connection, string sql, params object[] args)
{
// Perform named argument replacements
@@ -666,8 +666,8 @@ namespace Umbraco.Core.Persistence
return ExecuteScalar<T>(sql.SQL, sql.Arguments);
}
Regex rxSelect = new Regex(@"\A\s*(SELECT|EXECUTE|CALL)\s", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline);
Regex rxFrom = new Regex(@"\A\s*FROM\s", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline);
static readonly Regex rxSelect = new Regex(@"\A\s*(SELECT|EXECUTE|CALL)\s", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline);
static readonly Regex rxFrom = new Regex(@"\A\s*FROM\s", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline);
string AddSelectClause<T>(string sql)
{
if (sql.StartsWith(";"))
@@ -701,9 +701,9 @@ namespace Umbraco.Core.Persistence
return Fetch<T>(sql.SQL, sql.Arguments);
}
static Regex rxColumns = new Regex(@"\A\s*SELECT\s+((?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|.)*?)(?<!,\s+)\bFROM\b", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
static Regex rxOrderBy = new Regex(@"\bORDER\s+BY\s+(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?(?:\s*,\s*(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?)*", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
static Regex rxDistinct = new Regex(@"\ADISTINCT\s", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
static readonly Regex rxColumns = new Regex(@"\A\s*SELECT\s+((?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|.)*?)(?<!,\s+)\bFROM\b", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
static readonly Regex rxOrderBy = new Regex(@"\bORDER\s+BY\s+(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?(?:\s*,\s*(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?)*", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
static readonly Regex rxDistinct = new Regex(@"\ADISTINCT\s", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
public static bool SplitSqlForPaging(string sql, out string sqlCount, out string sqlSelectRemoved, out string sqlOrderBy)
{
sqlSelectRemoved = null;
@@ -2546,5 +2546,4 @@ namespace Umbraco.Core.Persistence
}
}
}
}
+3
View File
@@ -20,6 +20,7 @@ namespace Umbraco.Core.Scoping
public NoScope(ScopeProvider scopeProvider)
{
_scopeProvider = scopeProvider;
Timestamp = DateTime.Now;
#if DEBUG_SCOPES
_scopeProvider.RegisterScope(this);
#endif
@@ -28,6 +29,8 @@ namespace Umbraco.Core.Scoping
private readonly Guid _instanceId = Guid.NewGuid();
public Guid InstanceId { get { return _instanceId; } }
public DateTime Timestamp { get; }
/// <inheritdoc />
public bool CallContext { get { return false; } }
+1 -1
View File
@@ -374,7 +374,7 @@ namespace Umbraco.Core.Scoping
}
var parent = ParentScope;
_scopeProvider.AmbientScope = parent;
_scopeProvider.AmbientScope = parent; // might be null = this is how scopes are removed from context objects
#if DEBUG_SCOPES
_scopeProvider.Disposed(this);
+51 -6
View File
@@ -2,10 +2,12 @@
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Web;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
#if DEBUG_SCOPES
using System.Linq;
@@ -66,22 +68,38 @@ namespace Umbraco.Core.Scoping
// tests, any other things (see https://msdn.microsoft.com/en-us/library/dn458353(v=vs.110).aspx),
// but we don't want to make all of our objects serializable since they are *not* meant to be
// used in cross-AppDomain scenario anyways.
//
// in addition, whatever goes into the logical call context is serialized back and forth any
// time cross-AppDomain code executes, so if we put an "object" there, we'll can *another*
// "object" instance - and so we cannot use a random object as a key.
// time cross-AppDomain code executes, so if we put an "object" there, we'll get *another*
// "object" instance back - and so we cannot use a random object as a key.
//
// so what we do is: we register a guid in the call context, and we keep a table mapping those
// guids to the actual objects. the guid serializes back and forth without causing any issue,
// and we can retrieve the actual objects from the table.
// only issue: how are we supposed to clear the table? we can't, really. objects should take
// care of de-registering themselves from context.
// everything we use does, except the NoScope scope, which just stays there
//
// during tests, NoScope can to into call context... nothing much we can do about it
// so far, the only objects that go into this table are scopes (using ScopeItemKey) and
// scope contexts (using ContextItemKey).
private static readonly object StaticCallContextObjectsLock = new object();
private static readonly Dictionary<Guid, object> StaticCallContextObjects
= new Dictionary<Guid, object>();
// normal scopes and scope contexts take greate care removing themselves when disposed, so it
// is all safe. OTOH the NoScope *CANNOT* remove itself, this is by design, it *WILL* leak and
// there is little (nothing) we can do about it - NoScope exists for backward compatibility
// reasons and relying on it is greatly discouraged.
//
// however... we can *try* at protecting the app against memory leaks, by collecting NoScope
// instances that are too old. if anything actually *need* to retain a NoScope instance for
// a long time, it will break. but that's probably ok. so: the constants below define how
// long a NoScope instance can stay in the table before being removed, and how often we should
// collect the table - and collecting happens anytime SetCallContextObject is invoked
private static readonly TimeSpan StaticCallContextNoScopeLifeSpan = TimeSpan.FromMinutes(30);
private static readonly TimeSpan StaticCallContextCollectPeriod = TimeSpan.FromMinutes(4);
private static DateTime _staticCallContextLastCollect = DateTime.MinValue;
#if DEBUG_SCOPES
public Dictionary<Guid, object> CallContextObjects
{
@@ -156,6 +174,7 @@ namespace Umbraco.Core.Scoping
//Logging.LogHelper.Debug<ScopeProvider>("At:\r\n" + Head(Environment.StackTrace, 24));
#endif
StaticCallContextObjects.Remove(objectKey);
CollectStaticCallContextObjectsLocked();
}
}
else
@@ -171,11 +190,37 @@ namespace Umbraco.Core.Scoping
//Logging.LogHelper.Debug<ScopeProvider>("At:\r\n" + Head(Environment.StackTrace, 24));
#endif
StaticCallContextObjects.Add(objectKey, value);
CollectStaticCallContextObjectsLocked();
}
CallContext.LogicalSetData(key, objectKey);
}
}
private static void CollectStaticCallContextObjectsLocked()
{
// is it time to collect?
var now = DateTime.Now;
if (now - _staticCallContextLastCollect <= StaticCallContextCollectPeriod)
return;
// disable warning: this method is invoked from within a lock
// ReSharper disable InconsistentlySynchronizedField
var threshold = now.Add(-StaticCallContextNoScopeLifeSpan);
var guids = StaticCallContextObjects
.Where(x => x.Value is NoScope noScope && noScope.Timestamp < threshold)
.Select(x => x.Key)
.ToList();
if (guids.Count > 0)
{
LogHelper.Warn<ScopeProvider>($"Collected {guids.Count} NoScope instances from StaticCallContextObjects.");
foreach (var guid in guids)
StaticCallContextObjects.Remove(guid);
}
// ReSharper restore InconsistentlySynchronizedField
_staticCallContextLastCollect = now;
}
// this is for tests exclusively until we have a proper accessor in v8
internal static Func<IDictionary> HttpContextItemsGetter { get; set; }
+3 -2
View File
@@ -76,8 +76,9 @@ namespace Umbraco.Core.Services
_locker.EnterWriteLock();
foreach (var pair in pairs)
{
_id2Key.Add(pair.id, new TypedId<Guid>(pair.key, umbracoObjectType));
_key2Id.Add(pair.key, new TypedId<int>(pair.id, umbracoObjectType));
_id2Key[pair.id] = new TypedId<Guid>(pair.key, umbracoObjectType);
_key2Id[pair.key] = new TypedId<int>(pair.id, umbracoObjectType);
}
}
finally
+2 -2
View File
@@ -45,8 +45,8 @@
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="ClientDependency" version="1.9.7" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
<package id="ImageProcessor" version="2.5.6" targetFramework="net45" />
<package id="log4net" version="2.0.8" targetFramework="net45" />
@@ -84,27 +84,21 @@
};
}
if (!String.prototype.trimStart) {
/** trims the start of the string*/
String.prototype.trimStart = function (str) {
if (this.startsWith(str)) {
return this.substring(str.length);
}
return this;
};
}
if (!String.prototype.trimEnd) {
/** trims the start of the string*/
String.prototype.trimStart = function (str) {
if (this.startsWith(str)) {
return this.substring(str.length);
}
return this;
};
/** trims the end of the string*/
String.prototype.trimEnd = function (str) {
if (this.endsWith(str)) {
return this.substring(0, this.length - str.length);
}
return this;
};
}
/** trims the end of the string*/
String.prototype.trimEnd = function (str) {
if (this.endsWith(str)) {
return this.substring(0, this.length - str.length);
}
return this;
};
if (!String.prototype.utf8Encode) {
@@ -332,4 +326,4 @@
}
})();
})();
@@ -58,7 +58,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
$scope.renderModel = [];
$scope.dialogEditor = editorState && editorState.current && editorState.current.isDialogEditor === true;
$scope.dialogEditor = editorState && editorState.current && editorState.current.isDialogEditor === true;
//the default pre-values
var defaultConfig = {
@@ -93,7 +93,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
$scope.model.config.showOpenButton = ($scope.model.config.showOpenButton === "1" ? true : false);
$scope.model.config.showEditButton = ($scope.model.config.showEditButton === "1" ? true : false);
$scope.model.config.showPathOnHover = ($scope.model.config.showPathOnHover === "1" ? true : false);
var entityType = $scope.model.config.startNode.type === "member"
? "Member"
: $scope.model.config.startNode.type === "media"
@@ -267,11 +267,6 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
}
var notSupported = [
"Umbraco.CheckBoxList",
"Umbraco.DropDownMultiple",
"Umbraco.MacroContainer",
"Umbraco.RadioButtonList",
"Umbraco.MultipleTextstring",
"Umbraco.Tags",
"Umbraco.UploadField",
"Umbraco.ImageCropper"
@@ -266,7 +266,7 @@ angular.module("umbraco")
editor.on('ObjectResized', function (e) {
var qs = "?width=" + e.width + "&height=" + e.height;
var qs = "?width=" + e.width + "&height=" + e.height + "&mode=max";
var srcAttr = $(e.target).attr("src");
var path = srcAttr.split("?")[0];
$(e.target).attr("data-mce-src", path + qs);
@@ -384,7 +384,7 @@ angular.module("umbraco")
// element might still be there even after the modal has been hidden.
$scope.$on('$destroy', function () {
unsubscribe();
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
tinyMceEditor.destroy()
}
});
+4 -4
View File
@@ -116,8 +116,8 @@
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="ClientDependency.Core.Mvc, Version=1.8.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency-Mvc5.1.8.0.0\lib\net45\ClientDependency.Core.Mvc.dll</HintPath>
@@ -1035,9 +1035,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>7102</DevelopmentServerPort>
<DevelopmentServerPort>7105</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7102</IISUrl>
<IISUrl>http://localhost:7105</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="ClientDependency" version="1.9.7" targetFramework="net45" />
<package id="ClientDependency-Mvc5" version="1.8.0.0" targetFramework="net45" />
<package id="dotless" version="1.5.2" targetFramework="net45" />
<package id="Examine" version="0.1.89" targetFramework="net45" />
@@ -9,6 +9,7 @@ using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Sync;
using Umbraco.Web.Routing;
using Umbraco.Core.Logging;
using Umbraco.Core.Scoping;
using Umbraco.Web.Scheduling;
namespace Umbraco.Web
@@ -21,9 +22,12 @@ namespace Umbraco.Web
/// </remarks>
public class BatchedDatabaseServerMessenger : DatabaseServerMessenger
{
private readonly ApplicationContext _appContext;
public BatchedDatabaseServerMessenger(ApplicationContext appContext, bool enableDistCalls, DatabaseServerMessengerOptions options)
: base(appContext, enableDistCalls, options)
{
_appContext = appContext;
Scheduler.Initializing += Scheduler_Initializing;
}
@@ -42,7 +46,7 @@ namespace Umbraco.Web
//start the background task runner for processing instructions
const int delayMilliseconds = 60000;
var instructionProcessingRunner = new BackgroundTaskRunner<IBackgroundTask>("InstructionProcessing", ApplicationContext.ProfilingLogger.Logger);
var instructionProcessingTask = new InstructionProcessing(instructionProcessingRunner, this, delayMilliseconds, Options.ThrottleSeconds * 1000);
var instructionProcessingTask = new InstructionProcessing(instructionProcessingRunner, this, _appContext.ScopeProvider, delayMilliseconds, Options.ThrottleSeconds * 1000);
instructionProcessingRunner.TryAdd(instructionProcessingTask);
e.Add(instructionProcessingTask);
}
@@ -73,18 +77,31 @@ namespace Umbraco.Web
private class InstructionProcessing : RecurringTaskBase
{
private readonly DatabaseServerMessenger _messenger;
private readonly IScopeProvider _scopeProvider;
public InstructionProcessing(IBackgroundTaskRunner<RecurringTaskBase> runner,
DatabaseServerMessenger messenger,
IScopeProvider scopeProvider,
int delayMilliseconds, int periodMilliseconds)
: base(runner, delayMilliseconds, periodMilliseconds)
{
_messenger = messenger;
_scopeProvider = scopeProvider;
}
public override bool PerformRun()
{
_messenger.Sync();
// beware!
// DatabaseServerMessenger uses _appContext.DatabaseContext.Database without creating
// scopes, and since we are running in a background task, there will be no ambient
// scope (as would be the case within a web request), and so we would end up creating
// (and leaking) a NoScope instance, which is bad - better make sure we have a true
// scope here! - see U4-11207
using (var scope = _scopeProvider.CreateScope())
{
_messenger.Sync();
scope.Complete();
}
//return true to repeat
return true;
}
@@ -121,14 +138,17 @@ namespace Umbraco.Web
batch.Clear();
//Write the instructions but only create JSON blobs with a max instruction count equal to MaxProcessingInstructionCount
foreach (var instructionsBatch in instructions.InGroupsOf(Options.MaxProcessingInstructionCount))
using (var scope = _appContext.ScopeProvider.CreateScope())
{
WriteInstructions(instructionsBatch);
foreach (var instructionsBatch in instructions.InGroupsOf(Options.MaxProcessingInstructionCount))
{
WriteInstructions(scope, instructionsBatch);
}
scope.Complete();
}
}
private void WriteInstructions(IEnumerable<RefreshInstruction> instructions)
private void WriteInstructions(IScope scope, IEnumerable<RefreshInstruction> instructions)
{
var dto = new CacheInstructionDto
{
@@ -137,8 +157,7 @@ namespace Umbraco.Web
OriginIdentity = LocalIdentity,
InstructionCount = instructions.Sum(x => x.JsonIdCount)
};
ApplicationContext.DatabaseContext.Database.Insert(dto);
scope.Database.Insert(dto);
}
protected ICollection<RefreshInstructionEnvelope> GetBatch(bool create)
@@ -179,16 +198,19 @@ namespace Umbraco.Web
if (batch == null)
{
//only write the json blob with a maximum count of the MaxProcessingInstructionCount
foreach (var maxBatch in instructions.InGroupsOf(Options.MaxProcessingInstructionCount))
using (var scope = _appContext.ScopeProvider.CreateScope())
{
WriteInstructions(maxBatch);
foreach (var maxBatch in instructions.InGroupsOf(Options.MaxProcessingInstructionCount))
{
WriteInstructions(scope, maxBatch);
}
scope.Complete();
}
}
else
{
batch.Add(new RefreshInstructionEnvelope(servers, refresher, instructions));
}
}
}
}
}
}
@@ -2,9 +2,7 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core;
@@ -104,10 +102,9 @@ namespace Umbraco.Web.PropertyEditors
{
base.ConfigureForDisplay(preValues);
var asDictionary = preValues.PreValuesAsDictionary.ToDictionary(x => x.Key, x => x.Value.Value);
if (asDictionary.ContainsKey("hideLabel"))
if (preValues.PreValuesAsDictionary.ContainsKey("hideLabel"))
{
var boolAttempt = asDictionary["hideLabel"].TryConvertTo<bool>();
var boolAttempt = preValues.PreValuesAsDictionary["hideLabel"].Value.TryConvertTo<bool>();
if (boolAttempt.Success)
{
HideLabel = boolAttempt.Result;
@@ -120,10 +117,14 @@ namespace Umbraco.Web.PropertyEditors
public override string ConvertDbToString(Property property, PropertyType propertyType, IDataTypeService dataTypeService)
{
// Convert / validate value
if (property.Value == null || string.IsNullOrWhiteSpace(property.Value.ToString()))
if (property.Value == null)
return string.Empty;
var value = JsonConvert.DeserializeObject<List<object>>(property.Value.ToString());
var propertyValue = property.Value.ToString();
if (string.IsNullOrWhiteSpace(propertyValue))
return string.Empty;
var value = JsonConvert.DeserializeObject<List<object>>(propertyValue);
if (value == null)
return string.Empty;
@@ -182,11 +183,8 @@ namespace Umbraco.Web.PropertyEditors
}
}
// Update the value on the property
property.Value = JsonConvert.SerializeObject(value);
// Pass the call down
return base.ConvertDbToString(property, propertyType, dataTypeService);
// Return the serialized value
return JsonConvert.SerializeObject(value);
}
#endregion
@@ -195,10 +193,14 @@ namespace Umbraco.Web.PropertyEditors
public override object ConvertDbToEditor(Property property, PropertyType propertyType, IDataTypeService dataTypeService)
{
if (property.Value == null || string.IsNullOrWhiteSpace(property.Value.ToString()))
if (property.Value == null)
return string.Empty;
var value = JsonConvert.DeserializeObject<List<object>>(property.Value.ToString());
var propertyValue = property.Value.ToString();
if (string.IsNullOrWhiteSpace(propertyValue))
return string.Empty;
var value = JsonConvert.DeserializeObject<List<object>>(propertyValue);
if (value == null)
return string.Empty;
@@ -260,11 +262,8 @@ namespace Umbraco.Web.PropertyEditors
}
}
// Update the value on the property
property.Value = JsonConvert.SerializeObject(value);
// Pass the call down
return base.ConvertDbToEditor(property, propertyType, dataTypeService);
// Return the strongly-typed object, Umbraco will handle the JSON serializing/parsing, then Angular can handle it directly
return value;
}
#endregion
@@ -273,10 +272,14 @@ namespace Umbraco.Web.PropertyEditors
public override object ConvertEditorToDb(ContentPropertyData editorValue, object currentValue)
{
if (editorValue.Value == null || string.IsNullOrWhiteSpace(editorValue.Value.ToString()))
if (editorValue.Value == null)
return null;
var value = JsonConvert.DeserializeObject<List<object>>(editorValue.Value.ToString());
var rawValue = editorValue.Value.ToString();
if (string.IsNullOrWhiteSpace(rawValue))
return null;
var value = JsonConvert.DeserializeObject<List<object>>(rawValue);
if (value == null)
return null;
@@ -9,6 +9,8 @@ namespace Umbraco.Web.PropertyEditors.ParameterEditors
public MultipleContentPickerParameterEditor()
{
Configuration.Add("multiPicker", "1");
Configuration.Add("minNumber",0 );
Configuration.Add("maxNumber", 0);
}
}
}
}
@@ -96,6 +96,12 @@ namespace Umbraco.Web.Trees
return null;
var treeNode = GetSingleTreeNode(e, parentId, queryStrings);
if (treeNode == null)
{
//this means that the user has NO access to this node via permissions! They at least need to have browse permissions to see
//the node so we need to return null;
return null;
}
if (hasPathAccess == false)
{
treeNode.AdditionalData["noAccess"] = true;
@@ -189,8 +195,7 @@ namespace Umbraco.Web.Trees
{
// try to parse id as an integer else use GetEntityFromId
// which will grok Guids, Udis, etc and let use obtain the id
int entityId;
if (int.TryParse(id, out entityId) == false)
if (int.TryParse(id, out var entityId) == false)
{
var entity = GetEntityFromId(id);
if (entity == null)
@@ -198,15 +203,6 @@ namespace Umbraco.Web.Trees
entityId = entity.Id;
}
// if a request is made for the root node but user has no access to
// root node, return start nodes instead
if (entityId == Constants.System.Root && UserStartNodes.Contains(Constants.System.Root) == false)
{
return UserStartNodes.Length > 0
? Services.EntityService.GetAll(UmbracoObjectType, UserStartNodes)
: Enumerable.Empty<IUmbracoEntity>();
}
return Services.EntityService.GetChildren(entityId, UmbracoObjectType).ToArray();
}
+2 -2
View File
@@ -107,8 +107,8 @@
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="dotless.Core, Version=1.5.2.0, Culture=neutral, PublicKeyToken=96b446c9e63eae34, processorArchitecture=MSIL">
<HintPath>..\packages\dotless.1.5.2\lib\dotless.Core.dll</HintPath>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="ClientDependency" version="1.9.7" targetFramework="net45" />
<package id="dotless" version="1.5.2" targetFramework="net45" />
<package id="Examine" version="0.1.89" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="ClientDependency" version="1.9.7" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net45" />
<package id="Tidy.Net" version="1.0.0" targetFramework="net45" />
+2 -2
View File
@@ -106,8 +106,8 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="ClientDependency" version="1.9.7" targetFramework="net45" />
</packages>
+2 -2
View File
@@ -68,8 +68,8 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
+1 -1
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="ClientDependency" version="1.9.7" targetFramework="net45" />
</packages>
@@ -114,8 +114,8 @@
<Project>{651E1350-91B6-44B7-BD60-7207006D7003}</Project>
<Name>Umbraco.Web</Name>
</ProjectReference>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="System">
<Name>System</Name>