Merge branch 'dev-v7.6' into dev-v7

# Conflicts:
#	src/SolutionInfo.cs
#	src/Umbraco.Core/Configuration/UmbracoVersion.cs
#	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
#	src/Umbraco.Web.UI/packages.config
This commit is contained in:
Sebastiaan Janssen
2017-11-14 07:19:08 +01:00
4 changed files with 115 additions and 11 deletions

View File

@@ -2006,6 +2006,96 @@ namespace Umbraco.Core.Services
}
}
return true;
}
/// <summary>
/// Sorts a collection of <see cref="IContent"/> objects by updating the SortOrder according
/// to the ordering of node Ids passed in.
/// </summary>
/// <remarks>
/// Using this method will ensure that the Published-state is maintained upon sorting
/// so the cache is updated accordingly - as needed.
/// </remarks>
/// <param name="ids"></param>
/// <param name="userId"></param>
/// <param name="raiseEvents"></param>
/// <returns>True if sorting succeeded, otherwise False</returns>
public bool Sort(int[] ids, int userId = 0, bool raiseEvents = true)
{
var shouldBePublished = new List<IContent>();
var shouldBeSaved = new List<IContent>();
using (new WriteLock(Locker))
{
var allContent = GetByIds(ids).ToDictionary(x => x.Id, x => x);
var items = ids.Select(x => allContent[x]);
using (var uow = UowProvider.GetUnitOfWork())
{
var asArray = items.ToArray();
var saveEventArgs = new SaveEventArgs<IContent>(asArray);
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs))
{
uow.Commit();
return false;
}
var repository = RepositoryFactory.CreateContentRepository(uow);
var i = 0;
foreach (var content in asArray)
{
//If the current sort order equals that of the content
//we don't need to update it, so just increment the sort order
//and continue.
if (content.SortOrder == i)
{
i++;
continue;
}
content.SortOrder = i;
content.WriterId = userId;
i++;
if (content.Published)
{
//TODO: This should not be an inner operation, but if we do this, it cannot raise events and cannot be cancellable!
var published = _publishingStrategy.Publish(uow, content, userId).Success;
shouldBePublished.Add(content);
}
else
shouldBeSaved.Add(content);
repository.AddOrUpdate(content);
//add or update a preview
repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c));
}
foreach (var content in shouldBePublished)
{
//Create and Save ContentXml DTO
repository.AddOrUpdateContentXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c));
}
if (raiseEvents)
{
saveEventArgs.CanCancel = false;
uow.Events.Dispatch(Saved, this, saveEventArgs);
}
if (shouldBePublished.Any())
{
//TODO: This should not be an inner operation, but if we do this, it cannot raise events and cannot be cancellable!
_publishingStrategy.PublishingFinalized(uow, shouldBePublished, false);
}
Audit(uow, AuditType.Sort, "Sorting content performed by user", userId, 0);
uow.Commit();
}
}
return true;
}

View File

@@ -642,7 +642,21 @@ namespace Umbraco.Core.Services
/// <param name="userId"></param>
/// <param name="raiseEvents"></param>
/// <returns>True if sorting succeeded, otherwise False</returns>
bool Sort(IEnumerable<IContent> items, int userId = 0, bool raiseEvents = true);
bool Sort(IEnumerable<IContent> items, int userId = 0, bool raiseEvents = true);
/// <summary>
/// Sorts a collection of <see cref="IContent"/> objects by updating the SortOrder according
/// to the ordering of node Ids passed in.
/// </summary>
/// <remarks>
/// Using this method will ensure that the Published-state is maintained upon sorting
/// so the cache is updated accordingly - as needed.
/// </remarks>
/// <param name="ids"></param>
/// <param name="userId"></param>
/// <param name="raiseEvents"></param>
/// <returns>True if sorting succeeded, otherwise False</returns>
bool Sort(int[] ids, int userId = 0, bool raiseEvents = true);
/// <summary>
/// Gets the parent of the current content as an <see cref="IContent"/> item.

View File

@@ -792,11 +792,8 @@ namespace Umbraco.Web.Editors
{
var contentService = Services.ContentService;
// content service GetByIds does order the content items based on the order of Ids passed in
var content = contentService.GetByIds(sorted.IdSortOrder);
// Save content with new sort order and update content xml in db accordingly
if (contentService.Sort(content) == false)
if (contentService.Sort(sorted.IdSortOrder) == false)
{
LogHelper.Warn<ContentController>("Content sorting failed, this was probably caused by an event being cancelled");
return Request.CreateValidationErrorResponse("Content sorting failed, this was probably caused by an event being cancelled");

View File

@@ -175,13 +175,16 @@ namespace umbraco.presentation.webservices
{
var contentService = ApplicationContext.Services.ContentService;
try
{
var intIds = ids.Select(int.Parse).ToArray();
var allContent = contentService.GetByIds(intIds).ToDictionary(x => x.Id, x => x);
var sortedContent = intIds.Select(x => allContent[x]);
{
// Save content with new sort order and update db+cache accordingly
var sorted = contentService.Sort(sortedContent);
var intIds = new List<int>();
foreach (var stringId in ids)
{
int intId;
if (int.TryParse(stringId, out intId))
intIds.Add(intId);
}
var sorted = contentService.Sort(intIds.ToArray());
// refresh sort order on cached xml
// but no... this is not distributed - solely relying on content service & events should be enough