Merge pull request #1551 from umbraco/temp-U4-9104

U4-9104 Update the UmbracoExamine logic for Media to read the data di…
This commit is contained in:
Sebastiaan Janssen
2016-11-14 15:41:31 +01:00
committed by GitHub
10 changed files with 193 additions and 87 deletions

View File

@@ -38,5 +38,15 @@ namespace Umbraco.Core.Persistence.Repositories
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
IEnumerable<IMedia> GetPagedResultsByQuery(IQuery<IMedia> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "");
/// <summary>
/// Gets paged media descendants as XML by path
/// </summary>
/// <param name="path">Path starts with</param>
/// <param name="pageIndex">Page number</param>
/// <param name="pageSize">Page size</param>
/// <param name="totalRecords">Total records the query would return without paging</param>
/// <returns>A paged enumerable of XML entries of media items</returns>
IEnumerable<XElement> GetPagedXmlEntriesByPath(string path, long pageIndex, int pageSize, out long totalRecords);
}
}

View File

@@ -465,6 +465,30 @@ namespace Umbraco.Core.Persistence.Repositories
}
/// <summary>
/// Gets paged media descendants as XML by path
/// </summary>
/// <param name="path">Path starts with</param>
/// <param name="pageIndex">Page number</param>
/// <param name="pageSize">Page size</param>
/// <param name="totalRecords">Total records the query would return without paging</param>
/// <returns>A paged enumerable of XML entries of media items</returns>
public IEnumerable<XElement> GetPagedXmlEntriesByPath(string path, long pageIndex, int pageSize, out long totalRecords)
{
Sql query;
if (path == "-1")
{
query = new Sql().Select("nodeId, xml").From("cmsContentXml").Where("nodeId IN (SELECT id FROM umbracoNode WHERE nodeObjectType = @0)", Guid.Parse(Constants.ObjectTypes.Media)).OrderBy("nodeId");
}
else
{
query = new Sql().Select("nodeId, xml").From("cmsContentXml").Where("nodeId IN (SELECT id FROM umbracoNode WHERE path LIKE @0)", path.EnsureEndsWith(",%")).OrderBy("nodeId");
}
var pagedResult = Database.Page<ContentXmlDto>(pageIndex+1, pageSize, query);
totalRecords = pagedResult.TotalItems;
return pagedResult.Items.Select(dto => XElement.Parse(dto.Xml));
}
private IEnumerable<IMedia> ProcessQuery(Sql sql)
{
//NOTE: This doesn't allow properties to be part of the query

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
@@ -57,6 +58,19 @@ namespace Umbraco.Core.Services
/// </summary>
public interface IMediaService : IService
{
/// <summary>
/// Gets all XML entries found in the cmsContentXml table based on the given path
/// </summary>
/// <param name="path">Path starts with</param>
/// <param name="pageIndex">Page number</param>
/// <param name="pageSize">Page size</param>
/// <param name="totalRecords">Total records the query would return without paging</param>
/// <returns>A paged enumerable of XML entries of media items</returns>
/// <remarks>
/// If -1 is passed, then this will return all media xml entries, otherwise will return all descendents from the path
/// </remarks>
IEnumerable<XElement> GetPagedXmlEntries(string path, long pageIndex, int pageSize, out long totalRecords);
/// <summary>
/// Rebuilds all xml content in the cmsContentXml table for all media
/// </summary>

View File

@@ -1199,6 +1199,27 @@ namespace Umbraco.Core.Services
return true;
}
/// <summary>
/// Gets paged media descendants as XML by path
/// </summary>
/// <param name="path">Path starts with</param>
/// <param name="pageIndex">Page number</param>
/// <param name="pageSize">Page size</param>
/// <param name="totalRecords">Total records the query would return without paging</param>
/// <returns>A paged enumerable of XML entries of media items</returns>
public IEnumerable<XElement> GetPagedXmlEntries(string path, long pageIndex, int pageSize, out long totalRecords)
{
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
var uow = UowProvider.GetUnitOfWork();
using (var repository = RepositoryFactory.CreateMediaRepository(uow))
{
var contents = repository.GetPagedXmlEntriesByPath(path, pageIndex, pageSize, out totalRecords);
return contents;
}
}
/// <summary>
/// Rebuilds all xml content in the cmsContentXml table for all media
/// </summary>

View File

@@ -13,6 +13,7 @@ using Umbraco.Core.Persistence.Mappers;
namespace Umbraco.Tests.PublishedContent
{
[DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)]
public class LegacyExamineBackedMediaTests : ExamineBaseTest
{
public override void Initialize()

View File

@@ -3,11 +3,13 @@ using System.Linq;
using Examine;
using Lucene.Net.Store;
using NUnit.Framework;
using Umbraco.Tests.TestHelpers;
using UmbracoExamine;
namespace Umbraco.Tests.UmbracoExamine
{
[TestFixture]
[DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)]
[TestFixture]
public class EventsTest : ExamineBaseTest
{
[Test]

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Examine;
using Examine.LuceneEngine.Config;
using Examine.LuceneEngine.Providers;
@@ -7,10 +9,14 @@ using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Store;
using Moq;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Services;
using UmbracoExamine;
using UmbracoExamine.Config;
@@ -34,7 +40,8 @@ namespace Umbraco.Tests.UmbracoExamine
IMediaService mediaService = null,
IDataTypeService dataTypeService = null,
IMemberService memberService = null,
IUserService userService = null)
IUserService userService = null,
IContentTypeService contentTypeService = null)
{
if (dataService == null)
{
@@ -94,7 +101,8 @@ namespace Umbraco.Tests.UmbracoExamine
long longTotalRecs;
int intTotalRecs;
var allRecs = dataService.MediaService.GetLatestMediaByXpath("//node")
var mediaXml = dataService.MediaService.GetLatestMediaByXpath("//node");
var allRecs = mediaXml
.Root
.Elements()
.Select(x => Mock.Of<IMedia>(
@@ -114,20 +122,29 @@ namespace Umbraco.Tests.UmbracoExamine
mt.Id == (int)x.Attribute("nodeType"))))
.ToArray();
// MOCK!
var mediaServiceMock = new Mock<IMediaService>();
mediaServiceMock
.Setup(x => x.GetPagedDescendants(
It.IsAny<int>(), It.IsAny<long>(), It.IsAny<int>(), out longTotalRecs, It.IsAny<string>(), It.IsAny<Direction>(), It.IsAny<bool>(), It.IsAny<string>())
).Returns(() => allRecs);
mediaServiceMock
.Setup(x => x.GetPagedDescendants(
It.IsAny<int>(), It.IsAny<long>(), It.IsAny<int>(), out longTotalRecs, It.IsAny<string>(), It.IsAny<Direction>(), It.IsAny<string>())
).Returns(() => allRecs);
mediaServiceMock
.Setup(x => x.GetPagedDescendants(
It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>(), out intTotalRecs, It.IsAny<string>(), It.IsAny<Direction>(), It.IsAny<string>())
).Returns(() => allRecs);
mediaServiceMock.Setup(service => service.GetPagedXmlEntries(It.IsAny<string>(), It.IsAny<long>(), It.IsAny<int>(), out longTotalRecs))
.Returns(() => allRecs.Select(x => x.ToXml()));
mediaService = mediaServiceMock.Object;
mediaService = Mock.Of<IMediaService>(
x => x.GetPagedDescendants(
It.IsAny<int>(), It.IsAny<long>(), It.IsAny<int>(), out longTotalRecs, It.IsAny<string>(), It.IsAny<Direction>(), It.IsAny<bool>(), It.IsAny<string>())
==
allRecs
&& x.GetPagedDescendants(
It.IsAny<int>(), It.IsAny<long>(), It.IsAny<int>(), out longTotalRecs, It.IsAny<string>(), It.IsAny<Direction>(), It.IsAny<string>())
==
allRecs
&& x.GetPagedDescendants(
It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>(), out intTotalRecs, It.IsAny<string>(), It.IsAny<Direction>(), It.IsAny<string>())
==
allRecs);
}
if (dataTypeService == null)
{
@@ -139,6 +156,18 @@ namespace Umbraco.Tests.UmbracoExamine
memberService = Mock.Of<IMemberService>();
}
if (contentTypeService == null)
{
var contentTypeServiceMock = new Mock<IContentTypeService>();
contentTypeServiceMock.Setup(x => x.GetAllMediaTypes())
.Returns(new List<IMediaType>()
{
new MediaType(-1) {Alias = "Folder", Name = "Folder", Id = 1031, Icon = "icon-folder"},
new MediaType(-1) {Alias = "Image", Name = "Image", Id = 1032, Icon = "icon-picture"}
});
contentTypeService = contentTypeServiceMock.Object;
}
if (analyzer == null)
{
analyzer = new StandardAnalyzer(Version.LUCENE_29);
@@ -154,6 +183,7 @@ namespace Umbraco.Tests.UmbracoExamine
mediaService,
dataTypeService,
userService,
contentTypeService,
analyzer,
false);

View File

@@ -10,15 +10,17 @@ using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Store;
using NUnit.Framework;
using Umbraco.Tests.TestHelpers;
using UmbracoExamine;
namespace Umbraco.Tests.UmbracoExamine
{
/// <summary>
/// Tests the standard indexing capabilities
/// </summary>
[TestFixture, RequiresSTA]
/// <summary>
/// Tests the standard indexing capabilities
/// </summary>
[DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)]
[TestFixture, RequiresSTA]
public class IndexTest : ExamineBaseTest
{
@@ -85,12 +87,11 @@ namespace Umbraco.Tests.UmbracoExamine
//RESET the parent id
existingCriteria = ((IndexCriteria)_indexer.IndexerData);
_indexer.IndexerData = new IndexCriteria(existingCriteria.StandardFields, existingCriteria.UserFields, existingCriteria.IncludeNodeTypes, existingCriteria.ExcludeNodeTypes,
null);
null);
//now ensure it's deleted
var newResults = _searcher.Search(_searcher.CreateSearchCriteria().Id(2112).Compile());
Assert.AreEqual(1, newResults.Count());
}
[Test]

View File

@@ -8,9 +8,11 @@ using Examine.LuceneEngine.Providers;
using Lucene.Net.Store;
using NUnit.Framework;
using Examine.LuceneEngine.SearchCriteria;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.UmbracoExamine
{
[DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)]
[TestFixture]
public class SearchTests : ExamineBaseTest
{

View File

@@ -1,20 +1,12 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
using System.Web;
using System.Xml.Linq;
using Examine;
using Examine.Config;
using Examine.Providers;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Umbraco.Core;
using umbraco.cms.businesslogic;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Services;
@@ -22,12 +14,9 @@ using UmbracoExamine.DataServices;
using Examine.LuceneEngine;
using Examine.LuceneEngine.Config;
using UmbracoExamine.Config;
using Examine.LuceneEngine.Providers;
using Lucene.Net.Analysis;
using umbraco.BasePages;
using Umbraco.Core.Persistence.Querying;
using IContentService = Umbraco.Core.Services.IContentService;
using UmbracoExamine.LocalStorage;
using IMediaService = Umbraco.Core.Services.IMediaService;
@@ -42,6 +31,7 @@ namespace UmbracoExamine
private readonly IMediaService _mediaService;
private readonly IDataTypeService _dataTypeService;
private readonly IUserService _userService;
private readonly IContentTypeService _contentTypeService;
#region Constructors
@@ -55,6 +45,7 @@ namespace UmbracoExamine
_mediaService = ApplicationContext.Current.Services.MediaService;
_dataTypeService = ApplicationContext.Current.Services.DataTypeService;
_userService = ApplicationContext.Current.Services.UserService;
_contentTypeService = ApplicationContext.Current.Services.ContentTypeService;
}
/// <summary>
@@ -73,6 +64,7 @@ namespace UmbracoExamine
_mediaService = ApplicationContext.Current.Services.MediaService;
_dataTypeService = ApplicationContext.Current.Services.DataTypeService;
_userService = ApplicationContext.Current.Services.UserService;
_contentTypeService = ApplicationContext.Current.Services.ContentTypeService;
}
/// <summary>
@@ -91,6 +83,7 @@ namespace UmbracoExamine
_mediaService = ApplicationContext.Current.Services.MediaService;
_dataTypeService = ApplicationContext.Current.Services.DataTypeService;
_userService = ApplicationContext.Current.Services.UserService;
_contentTypeService = ApplicationContext.Current.Services.ContentTypeService;
}
/// <summary>
@@ -105,6 +98,7 @@ namespace UmbracoExamine
/// <param name="userService"></param>
/// <param name="analyzer"></param>
/// <param name="async"></param>
[Obsolete("Use the overload that specifies the Umbraco services")]
public UmbracoContentIndexer(IIndexCriteria indexerData, Lucene.Net.Store.Directory luceneDirectory, IDataService dataService,
IContentService contentService,
IMediaService mediaService,
@@ -117,13 +111,43 @@ namespace UmbracoExamine
_mediaService = mediaService;
_dataTypeService = dataTypeService;
_userService = userService;
_contentTypeService = ApplicationContext.Current.Services.ContentTypeService;
}
/// <summary>
/// Constructor to allow for creating an indexer at runtime
/// </summary>
/// <param name="indexerData"></param>
/// <param name="luceneDirectory"></param>
/// <param name="dataService"></param>
/// <param name="contentService"></param>
/// <param name="mediaService"></param>
/// <param name="dataTypeService"></param>
/// <param name="userService"></param>
/// <param name="contentTypeService"></param>
/// <param name="analyzer"></param>
/// <param name="async"></param>
public UmbracoContentIndexer(IIndexCriteria indexerData, Lucene.Net.Store.Directory luceneDirectory, IDataService dataService,
IContentService contentService,
IMediaService mediaService,
IDataTypeService dataTypeService,
IUserService userService,
IContentTypeService contentTypeService,
Analyzer analyzer, bool async)
: base(indexerData, luceneDirectory, dataService, analyzer, async)
{
_contentService = contentService;
_mediaService = mediaService;
_dataTypeService = dataTypeService;
_userService = userService;
_contentTypeService = contentTypeService;
}
#endregion
#region Constants & Fields
/// <summary>
/// Used to store the path of a content object
@@ -206,13 +230,8 @@ namespace UmbracoExamine
SupportProtectedContent = supportProtected;
else
SupportProtectedContent = false;
base.Initialize(name, config);
}
#endregion
@@ -285,10 +304,7 @@ namespace UmbracoExamine
#endregion
#region Public methods
/// <summary>
/// Overridden for logging
/// </summary>
@@ -308,7 +324,6 @@ namespace UmbracoExamine
{
DataService.LogService.AddErrorLog(-1, string.Format("ReIndexNode cannot proceed, the format of the XElement is invalid, the xml has no 'id' attribute. {0}", node));
}
}
/// <summary>
@@ -355,8 +370,6 @@ namespace UmbracoExamine
switch (type)
{
case IndexTypes.Content:
var contentParentId = -1;
if (IndexerData.ParentNodeId.HasValue && IndexerData.ParentNodeId.Value > 0)
{
@@ -391,69 +404,62 @@ namespace UmbracoExamine
{
content = descendants.ToArray();
}
AddNodesToIndex(GetSerializedContent(content), type);
pageIndex++;
} while (content.Length == pageSize);
break;
case IndexTypes.Media:
var mediaParentId = -1;
if (IndexerData.ParentNodeId.HasValue && IndexerData.ParentNodeId.Value > 0)
{
mediaParentId = IndexerData.ParentNodeId.Value;
}
IMedia[] media;
XElement[] mediaXElements;
var mediaTypes = _contentTypeService.GetAllMediaTypes().ToArray();
var icons = mediaTypes.ToDictionary(x => x.Id, y => y.Icon);
do
{
long total;
var descendants = _mediaService.GetPagedDescendants(mediaParentId, pageIndex, pageSize, out total);
if (mediaParentId == -1)
{
mediaXElements = _mediaService.GetPagedXmlEntries("-1", pageIndex, pageSize, out total).ToArray();
}
else
{
//Get the parent
var parent = _mediaService.GetById(mediaParentId);
if (parent == null)
mediaXElements = new XElement[0];
else
mediaXElements = _mediaService.GetPagedXmlEntries(parent.Path, pageIndex, pageSize, out total).ToArray();
}
//if specific types are declared we need to post filter them
//TODO: Update the service layer to join the cmsContentType table so we can query by content type too
if (IndexerData.IncludeNodeTypes.Any())
{
media = descendants.Where(x => IndexerData.IncludeNodeTypes.Contains(x.ContentType.Alias)).ToArray();
}
else
{
media = descendants.ToArray();
var includeNodeTypeIds = mediaTypes.Where(x => IndexerData.IncludeNodeTypes.Contains(x.Alias)).Select(x => x.Id);
mediaXElements = mediaXElements.Where(elm => includeNodeTypeIds.Contains(elm.AttributeValue<int>("nodeType"))).ToArray();
}
AddNodesToIndex(GetSerializedMedia(media), type);
foreach (var element in mediaXElements)
{
element.Add(new XAttribute("icon", icons[element.AttributeValue<int>("nodeType")]));
}
AddNodesToIndex(mediaXElements, type);
pageIndex++;
} while (media.Length == pageSize);
} while (mediaXElements.Length == pageSize);
break;
}
}
private IEnumerable<XElement> GetSerializedMedia(IEnumerable<IMedia> media)
{
var serializer = new EntityXmlSerializer();
foreach (var m in media)
{
var xml = serializer.Serialize(
_mediaService,
_dataTypeService,
_userService,
m);
//add a custom 'icon' attribute
if (m.ContentType.Icon.IsNullOrWhiteSpace() == false)
{
xml.Add(new XAttribute("icon", m.ContentType.Icon));
}
yield return xml;
}
}
private IEnumerable<XElement> GetSerializedContent(IEnumerable<IContent> content)
{
var serializer = new EntityXmlSerializer();
@@ -510,7 +516,6 @@ namespace UmbracoExamine
protected override void OnGatheringNodeData(IndexingNodeDataEventArgs e)
{
//strip html of all users fields if we detect it has HTML in it.
//if that is the case, we'll create a duplicate 'raw' copy of it so that we can return
//the value of the field 'as-is'.
@@ -546,7 +551,6 @@ namespace UmbracoExamine
var icon = (string)e.Node.Attribute("icon");
if (!e.Fields.ContainsKey(IconFieldName))
e.Fields.Add(IconFieldName, icon);
}
/// <summary>
@@ -584,7 +588,6 @@ namespace UmbracoExamine
}
return fields;
}
/// <summary>
@@ -605,7 +608,6 @@ namespace UmbracoExamine
{
return base.GetIndexerData(indexSet);
}
}
/// <summary>
@@ -635,10 +637,9 @@ namespace UmbracoExamine
{
return false;
}
return base.ValidateDocument(node);
}
#endregion
}
}
}