U4-9104 Update the UmbracoExamine logic for Media to read the data directly from the umbracoXml table.

updated some tests to use the testbehavior attribute so they dont rely on being run in a specific order.
This commit is contained in:
Claus
2016-10-27 10:47:32 +02:00
parent 7495d89a79
commit 221354a7d8
10 changed files with 193 additions and 86 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.GetAllContentTypes())
.Returns(new List<IContentType>()
{
new ContentType(-1) {Alias = "Folder", Name = "Folder", Id = 1031, Icon = "icon-folder"},
new ContentType(-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,63 @@ 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 nodeTypes = _contentTypeService.GetAllContentTypes().ToArray();
var icons = nodeTypes.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();
var includeNodeTypeIds = nodeTypes.Where(x => IndexerData.IncludeNodeTypes.Contains(x.Alias)).Select(x => x.Id);
mediaXElements = mediaXElements.Where(elm => includeNodeTypeIds.Contains(elm.AttributeValue<int>("nodeType"))).ToArray();
}
else
// ReSharper disable once ForCanBeConvertedToForeach
for (var i = 0; i < mediaXElements.Length; i++)
{
media = descendants.ToArray();
mediaXElements[i].Add(new XAttribute("icon", icons[mediaXElements[i].AttributeValue<int>("nodeType")]));
}
AddNodesToIndex(GetSerializedMedia(media), type);
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 +517,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 +552,6 @@ namespace UmbracoExamine
var icon = (string)e.Node.Attribute("icon");
if (!e.Fields.ContainsKey(IconFieldName))
e.Fields.Add(IconFieldName, icon);
}
/// <summary>
@@ -584,7 +589,6 @@ namespace UmbracoExamine
}
return fields;
}
/// <summary>
@@ -605,7 +609,6 @@ namespace UmbracoExamine
{
return base.GetIndexerData(indexSet);
}
}
/// <summary>
@@ -635,10 +638,9 @@ namespace UmbracoExamine
{
return false;
}
return base.ValidateDocument(node);
}
#endregion
}
}
}