Merge branch 'AndyButland-u4-5365' into 7.2.0
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
@@ -21,5 +24,18 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <param name="xml"></param>
|
||||
void AddOrUpdatePreviewXml(IMedia content, Func<IMedia, XElement> xml);
|
||||
|
||||
/// <summary>
|
||||
/// Gets paged media results
|
||||
/// </summary>
|
||||
/// <param name="query">Query to excute</param>
|
||||
/// <param name="pageNumber">Page number</param>
|
||||
/// <param name="pageSize">Page size</param>
|
||||
/// <param name="totalRecords">Total records query would return without paging</param>
|
||||
/// <param name="orderBy">Field to order by</param>
|
||||
/// <param name="orderDirection">Direction to order by</param>
|
||||
/// <param name="filter">Search text filter</param>
|
||||
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
|
||||
IEnumerable<IMedia> GetPagedResultsByQuery(IQuery<IMedia> query, int pageNumber, int pageSize, out int totalRecords,
|
||||
string orderBy, Direction orderDirection, string filter = "");
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,13 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Dynamics;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
@@ -397,6 +399,109 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets paged media results
|
||||
/// </summary>
|
||||
/// <param name="query">Query to excute</param>
|
||||
/// <param name="pageNumber">Page number</param>
|
||||
/// <param name="pageSize">Page size</param>
|
||||
/// <param name="totalRecords">Total records query would return without paging</param>
|
||||
/// <param name="orderBy">Field to order by</param>
|
||||
/// <param name="orderDirection">Direction to order by</param>
|
||||
/// <param name="filter">Search text filter</param>
|
||||
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
|
||||
public IEnumerable<IMedia> GetPagedResultsByQuery(IQuery<IMedia> query, int pageNumber, int pageSize, out int totalRecords,
|
||||
string orderBy, Direction orderDirection, string filter = "")
|
||||
{
|
||||
// Get base query
|
||||
var sqlClause = GetBaseQuery(false);
|
||||
var translator = new SqlTranslator<IMedia>(sqlClause, query);
|
||||
var sql = translator.Translate();
|
||||
|
||||
// Apply filter
|
||||
if (!string.IsNullOrEmpty(filter))
|
||||
{
|
||||
sql = sql.Where("umbracoNode.text LIKE @0", "%" + filter + "%");
|
||||
}
|
||||
|
||||
// Apply order according to parameters
|
||||
if (!string.IsNullOrEmpty(orderBy))
|
||||
{
|
||||
var orderByParams = new[] { GetDatabaseFieldNameForOrderBy(orderBy) };
|
||||
if (orderDirection == Direction.Ascending)
|
||||
{
|
||||
sql = sql.OrderBy(orderByParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
sql = sql.OrderByDescending(orderByParams);
|
||||
}
|
||||
}
|
||||
|
||||
// Note we can't do multi-page for several DTOs like we can multi-fetch and are doing in PerformGetByQuery,
|
||||
// but actually given we are doing a Get on each one (again as in PerformGetByQuery), we only need the node Id.
|
||||
// So we'll modify the SQL.
|
||||
var modifiedSQL = sql.SQL.Replace("SELECT *", "SELECT cmsContentVersion.contentId");
|
||||
|
||||
// Get page of results and total count
|
||||
IEnumerable<IMedia> result;
|
||||
var pagedResult = Database.Page<ContentVersionDto>(pageNumber, pageSize, modifiedSQL, sql.Arguments);
|
||||
totalRecords = Convert.ToInt32(pagedResult.TotalItems);
|
||||
if (totalRecords > 0)
|
||||
{
|
||||
// Parse out node Ids and load media (we need the cast here in order to be able to call the IQueryable extension
|
||||
// methods OrderBy or OrderByDescending)
|
||||
var media = GetAll(pagedResult.Items
|
||||
.DistinctBy(x => x.NodeId)
|
||||
.Select(x => x.NodeId).ToArray())
|
||||
.Cast<Umbraco.Core.Models.Media>()
|
||||
.AsQueryable();
|
||||
|
||||
// Now we need to ensure this result is also ordered by the same order by clause
|
||||
var orderByProperty = GetIMediaPropertyNameForOrderBy(orderBy);
|
||||
if (orderDirection == Direction.Ascending)
|
||||
{
|
||||
result = media.OrderBy(orderByProperty);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = media.OrderByDescending(orderByProperty);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Enumerable.Empty<IMedia>();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private string GetDatabaseFieldNameForOrderBy(string orderBy)
|
||||
{
|
||||
// Translate the passed order by field (which were originally defined for in-memory object sorting
|
||||
// of ContentItemBasic instances) to the database field names.
|
||||
switch (orderBy)
|
||||
{
|
||||
case "Name":
|
||||
return "umbracoNode.text";
|
||||
default:
|
||||
return "umbracoNode.sortOrder";
|
||||
}
|
||||
}
|
||||
|
||||
private string GetIMediaPropertyNameForOrderBy(string orderBy)
|
||||
{
|
||||
// Translate the passed order by field (which were originally defined for in-memory object sorting
|
||||
// of ContentItemBasic instances) to the IMedia property names.
|
||||
switch (orderBy)
|
||||
{
|
||||
case "Name":
|
||||
return "Name";
|
||||
default:
|
||||
return "SortOrder";
|
||||
}
|
||||
}
|
||||
|
||||
private string EnsureUniqueNodeName(int parentId, string nodeName, int id = 0)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
@@ -61,6 +62,20 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
|
||||
IEnumerable<IMedia> GetChildren(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of <see cref="IMedia"/> objects by Parent Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the Parent to retrieve Children from</param>
|
||||
/// <param name="pageNumber">Page number</param>
|
||||
/// <param name="pageSize">Page size</param>
|
||||
/// <param name="totalRecords">Total records query would return without paging</param>
|
||||
/// <param name="orderBy">Field to order by</param>
|
||||
/// <param name="orderDirections">Direction to order by</param>
|
||||
/// <param name="filter">Search text filter</param>
|
||||
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
|
||||
IEnumerable<IMedia> GetPagedChildren(int id, int pageNumber, int pageSize, out int totalChildren,
|
||||
string orderBy, Direction orderDirection, string filter = "");
|
||||
|
||||
/// <summary>
|
||||
/// Gets descendants of a <see cref="IMedia"/> object by its Id
|
||||
/// </summary>
|
||||
|
||||
@@ -10,6 +10,7 @@ using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
@@ -394,6 +395,31 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of <see cref="IMedia"/> objects by Parent Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the Parent to retrieve Children from</param>
|
||||
/// <param name="pageNumber">Page number</param>
|
||||
/// <param name="pageSize">Page size</param>
|
||||
/// <param name="totalRecords">Total records query would return without paging</param>
|
||||
/// <param name="orderBy">Field to order by</param>
|
||||
/// <param name="orderDirections">Direction to order by</param>
|
||||
/// <param name="filter">Search text filter</param>
|
||||
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
|
||||
public IEnumerable<IMedia> GetPagedChildren(int id, int pageNumber, int pageSize, out int totalChildren,
|
||||
string orderBy, Direction orderDirection, string filter = "")
|
||||
{
|
||||
Mandate.ParameterCondition(pageNumber > 0, "pageSize");
|
||||
Mandate.ParameterCondition(pageSize > 0, "pageSize");
|
||||
using (var repository = _repositoryFactory.CreateMediaRepository(_uowProvider.GetUnitOfWork()))
|
||||
{
|
||||
var query = Query<IMedia>.Builder.Where(x => x.ParentId == id);
|
||||
var medias = repository.GetPagedResultsByQuery(query, pageNumber, pageSize, out totalChildren, orderBy, orderDirection, filter);
|
||||
|
||||
return medias;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets descendants of a <see cref="IMedia"/> object by its Id
|
||||
/// </summary>
|
||||
|
||||
@@ -14,6 +14,7 @@ using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
using umbraco.editorControls.tinyMCE3;
|
||||
using umbraco.interfaces;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
|
||||
namespace Umbraco.Tests.Persistence.Repositories
|
||||
{
|
||||
@@ -240,7 +241,6 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
MediaTypeRepository mediaTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository))
|
||||
{
|
||||
|
||||
// Act
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
|
||||
var result = repository.GetByQuery(query);
|
||||
@@ -250,6 +250,153 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_GetPagedResultsByQuery_ForFirstPage_On_MediaRepository()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
MediaTypeRepository mediaTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository))
|
||||
{
|
||||
// Act
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
|
||||
int totalRecords;
|
||||
var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "SortOrder", Direction.Ascending);
|
||||
|
||||
// Assert
|
||||
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
|
||||
Assert.That(result.Count(), Is.EqualTo(1));
|
||||
Assert.That(result.First().Name, Is.EqualTo("Test Image"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_GetPagedResultsByQuery_ForSecondPage_On_MediaRepository()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
MediaTypeRepository mediaTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository))
|
||||
{
|
||||
// Act
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
|
||||
int totalRecords;
|
||||
var result = repository.GetPagedResultsByQuery(query, 2, 1, out totalRecords, "SortOrder", Direction.Ascending);
|
||||
|
||||
// Assert
|
||||
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
|
||||
Assert.That(result.Count(), Is.EqualTo(1));
|
||||
Assert.That(result.First().Name, Is.EqualTo("Test File"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_GetPagedResultsByQuery_WithSinglePage_On_MediaRepository()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
MediaTypeRepository mediaTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository))
|
||||
{
|
||||
// Act
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
|
||||
int totalRecords;
|
||||
var result = repository.GetPagedResultsByQuery(query, 1, 2, out totalRecords, "SortOrder", Direction.Ascending);
|
||||
|
||||
// Assert
|
||||
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
|
||||
Assert.That(result.Count(), Is.EqualTo(2));
|
||||
Assert.That(result.First().Name, Is.EqualTo("Test Image"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_GetPagedResultsByQuery_WithDescendingOrder_On_MediaRepository()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
MediaTypeRepository mediaTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository))
|
||||
{
|
||||
// Act
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
|
||||
int totalRecords;
|
||||
var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "SortOrder", Direction.Descending);
|
||||
|
||||
// Assert
|
||||
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
|
||||
Assert.That(result.Count(), Is.EqualTo(1));
|
||||
Assert.That(result.First().Name, Is.EqualTo("Test File"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_GetPagedResultsByQuery_WitAlternateOrder_On_MediaRepository()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
MediaTypeRepository mediaTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository))
|
||||
{
|
||||
// Act
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
|
||||
int totalRecords;
|
||||
var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "Name", Direction.Ascending);
|
||||
|
||||
// Assert
|
||||
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
|
||||
Assert.That(result.Count(), Is.EqualTo(1));
|
||||
Assert.That(result.First().Name, Is.EqualTo("Test File"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_GetPagedResultsByQuery_WithFilterMatchingSome_On_MediaRepository()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
MediaTypeRepository mediaTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository))
|
||||
{
|
||||
// Act
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
|
||||
int totalRecords;
|
||||
var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "SortOrder", Direction.Ascending, "File");
|
||||
|
||||
// Assert
|
||||
Assert.That(totalRecords, Is.EqualTo(1));
|
||||
Assert.That(result.Count(), Is.EqualTo(1));
|
||||
Assert.That(result.First().Name, Is.EqualTo("Test File"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_GetPagedResultsByQuery_WithFilterMatchingAll_On_MediaRepository()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider();
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
MediaTypeRepository mediaTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository))
|
||||
{
|
||||
// Act
|
||||
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
|
||||
int totalRecords;
|
||||
var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "SortOrder", Direction.Ascending, "Test");
|
||||
|
||||
// Assert
|
||||
Assert.That(totalRecords, Is.EqualTo(2));
|
||||
Assert.That(result.Count(), Is.EqualTo(1));
|
||||
Assert.That(result.First().Name, Is.EqualTo("Test Image"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_GetAll_By_Param_Ids_On_MediaRepository()
|
||||
{
|
||||
|
||||
@@ -138,48 +138,28 @@ namespace Umbraco.Web.Editors
|
||||
Direction orderDirection = Direction.Ascending,
|
||||
string filter = "")
|
||||
{
|
||||
//TODO: This will be horribly inefficient for paging! This is because our datasource/repository
|
||||
// doesn't support paging at the SQL level... and it'll be pretty interesting to try to make that work.
|
||||
|
||||
var children = Services.MediaService.GetChildren(id).ToArray();
|
||||
var totalChildren = children.Length;
|
||||
|
||||
if (totalChildren == 0)
|
||||
return new PagedResult<ContentItemBasic<ContentPropertyBasic, IMedia>>(0, 0, 0);
|
||||
|
||||
var result = children
|
||||
.Select(Mapper.Map<IMedia, ContentItemBasic<ContentPropertyBasic, IMedia>>)
|
||||
.AsQueryable();
|
||||
|
||||
//TODO: This is a rudimentry filter - should use the logic found in the EntityService filter (dynamic linq) instead
|
||||
if (!string.IsNullOrEmpty(filter))
|
||||
{
|
||||
filter = filter.ToLower();
|
||||
result = result.Where(x => x.Name.InvariantContains(filter));
|
||||
}
|
||||
|
||||
var orderedResult = orderDirection == Direction.Ascending
|
||||
? result.OrderBy(orderBy)
|
||||
: result.OrderByDescending(orderBy);
|
||||
|
||||
var pagedResult = new PagedResult<ContentItemBasic<ContentPropertyBasic, IMedia>>(
|
||||
totalChildren,
|
||||
pageNumber,
|
||||
pageSize);
|
||||
|
||||
int totalChildren;
|
||||
IMedia[] children;
|
||||
if (pageNumber > 0 && pageSize > 0)
|
||||
{
|
||||
pagedResult.Items = orderedResult
|
||||
.Skip(pagedResult.SkipSize)
|
||||
.Take(pageSize);
|
||||
children = Services.MediaService.GetPagedChildren(id, pageNumber, pageSize, out totalChildren, orderBy, orderDirection, filter).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
pagedResult.Items = orderedResult;
|
||||
children = Services.MediaService.GetChildren(id).ToArray();
|
||||
totalChildren = children.Length;
|
||||
}
|
||||
|
||||
return pagedResult;
|
||||
if (totalChildren == 0)
|
||||
{
|
||||
return new PagedResult<ContentItemBasic<ContentPropertyBasic, IMedia>>(0, 0, 0);
|
||||
}
|
||||
|
||||
var pagedResult = new PagedResult<ContentItemBasic<ContentPropertyBasic, IMedia>>(totalChildren, pageNumber, pageSize);
|
||||
pagedResult.Items = children
|
||||
.Select(Mapper.Map<IMedia, ContentItemBasic<ContentPropertyBasic, IMedia>>);
|
||||
|
||||
return pagedResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user