Partial identity matches can now be considered as full matches, fixing a bug where import files would create duplicate items if imported several times.

This commit is contained in:
Bertrand Le Roy
2014-10-17 13:16:34 -07:00
parent bfc72ba5a0
commit 1540f69a79
7 changed files with 55 additions and 19 deletions

View File

@@ -39,6 +39,30 @@ namespace Orchard.Tests.ContentManagement {
var identity2 = new ContentIdentity(@"/foo=bar/abaz=quux\/fr\\ed=foo/yarg=yiu=foo");
Assert.That(comparer.Equals(identity2, new ContentIdentity(identity2.ToString())));
}
[Test]
public void ContentIdentityCanSeePartialMatchesAreEquivalent() {
var identity1 = new ContentIdentity("/bar=baz/a=b");
var identity2 = new ContentIdentity(@"/foo=bar/bar=baz/glop=glop");
Assert.That(ContentIdentity.ContentIdentityEqualityComparer.AreEquivalent(identity1, identity2));
Assert.That(ContentIdentity.ContentIdentityEqualityComparer.AreEquivalent(identity2, identity1));
}
[Test]
public void ContentIdentityCanSeeFullMatchesAreEquivalent() {
var identity1 = new ContentIdentity(@"/foo=bar/bar=baz/glop=glop");
var identity2 = new ContentIdentity(@"/foo=bar/bar=baz/glop=glop");
Assert.That(ContentIdentity.ContentIdentityEqualityComparer.AreEquivalent(identity1, identity2));
Assert.That(ContentIdentity.ContentIdentityEqualityComparer.AreEquivalent(identity2, identity1));
}
[Test]
public void ContentIdentityCanSeeNonMatchesAreNotEquivalent() {
var identity1 = new ContentIdentity(@"/a=b/foo=baz");
var identity2 = new ContentIdentity(@"/foo=bar/bar=baz/glop=glop");
Assert.IsFalse(ContentIdentity.ContentIdentityEqualityComparer.AreEquivalent(identity1, identity2));
Assert.IsFalse(ContentIdentity.ContentIdentityEqualityComparer.AreEquivalent(identity2, identity1));
}
}
}

View File

@@ -29,12 +29,12 @@ namespace Orchard.Core.Common.Services {
return null;
}
var comparer = new ContentIdentity.ContentIdentityEqualityComparer();
return _contentManager
.Query<IdentityPart, IdentityPartRecord>()
.Where(p => p.Identifier == identifier)
.List<ContentItem>()
.Where(c => comparer.Equals(identity, _contentManager.GetItemMetadata(c).Identity));
.Where(c => ContentIdentity.ContentIdentityEqualityComparer.AreEquivalent(
identity, _contentManager.GetItemMetadata(c).Identity));
}
}
}

View File

@@ -37,7 +37,7 @@ namespace Orchard.Recipes.RecipeHandlers {
//Populate import session with all identities to be imported
foreach (var identity in elementDictionary.Keys) {
importContentSession.Set(identity.ToString(), elementDictionary[identity].Name.LocalName);
importContentSession.Set(identity, elementDictionary[identity].Name.LocalName);
}
//Determine if the import is to be batched in multiple transactions
@@ -45,16 +45,17 @@ namespace Orchard.Recipes.RecipeHandlers {
int batchSize = GetBatchSizeForDataStep(recipeContext.RecipeStep.Step);
//Run the import
ContentIdentity nextIdentity = null;
try {
while (startIndex < elementDictionary.Count) {
importContentSession.InitializeBatch(startIndex, batchSize);
//the session determines which items are included in the current batch
//so that dependencies can be managed within the same transaction
nextIdentity = importContentSession.GetNextInBatch();
var nextIdentity = importContentSession.GetNextInBatch();
while (nextIdentity != null) {
_orchardServices.ContentManager.Import(elementDictionary[nextIdentity], importContentSession);
_orchardServices.ContentManager.Import(
elementDictionary[nextIdentity.ToString()],
importContentSession);
nextIdentity = importContentSession.GetNextInBatch();
}
@@ -75,13 +76,14 @@ namespace Orchard.Recipes.RecipeHandlers {
recipeContext.Executed = true;
}
private Dictionary<ContentIdentity, XElement> CreateElementDictionary(XElement step) {
var elementDictionary = new Dictionary<ContentIdentity, XElement>(new ContentIdentity.ContentIdentityEqualityComparer());
private Dictionary<string, XElement> CreateElementDictionary(XElement step) {
var elementDictionary = new Dictionary<string, XElement>();
foreach (var element in step.Elements()) {
if (element.Attribute("Id") == null || string.IsNullOrEmpty(element.Attribute("Id").Value))
if (element.Attribute("Id") == null
|| string.IsNullOrEmpty(element.Attribute("Id").Value))
continue;
var identity = new ContentIdentity(element.Attribute("Id").Value);
var identity = new ContentIdentity(element.Attribute("Id").Value).ToString();
elementDictionary[identity] = element;
}
return elementDictionary;

View File

@@ -29,12 +29,12 @@ namespace Orchard.Users.Services {
return null;
}
var comparer = new ContentIdentity.ContentIdentityEqualityComparer();
return _contentManager
.Query<UserPart, UserPartRecord>()
.Where(p => p.UserName == identifier)
.List<ContentItem>()
.Where(c => comparer.Equals(identity, _contentManager.GetItemMetadata(c).Identity));
.Where(c => ContentIdentity.ContentIdentityEqualityComparer.AreEquivalent(
identity, _contentManager.GetItemMetadata(c).Identity));
}
}
}

View File

@@ -29,12 +29,12 @@ namespace Orchard.Widgets.Services {
return null;
}
var comparer = new ContentIdentity.ContentIdentityEqualityComparer();
return _contentManager
.Query<LayerPart, LayerPartRecord>()
.Where(p => p.Name == identifier)
.List<ContentItem>()
.Where(c => comparer.Equals(identity, _contentManager.GetItemMetadata(c).Identity));
.Where(c => ContentIdentity.ContentIdentityEqualityComparer.AreEquivalent(
identity, _contentManager.GetItemMetadata(c).Identity));
}
}
}

View File

@@ -144,6 +144,17 @@ namespace Orchard.ContentManagement {
public class ContentIdentityEqualityComparer : IEqualityComparer<ContentIdentity> {
public static bool AreEquivalent(ContentIdentity contentIdentity1, ContentIdentity contentIdentity2) {
if (contentIdentity1 == null) return contentIdentity2 == null;
if (contentIdentity2 == null) return false;
return contentIdentity1._dictionary.Keys
.Any(k => {
var other = contentIdentity2.Get(k);
if (other == null) return false;
return contentIdentity1._dictionary[k] == other;
});
}
public bool Equals(ContentIdentity contentIdentity1, ContentIdentity contentIdentity2) {
if (contentIdentity1._dictionary.Keys.Count != contentIdentity2._dictionary.Keys.Count)
return false;

View File

@@ -6,7 +6,6 @@ namespace Orchard.ContentManagement {
// Maps content identities to content items on the importer.
public class ImportContentSession {
private readonly IContentManager _contentManager;
private readonly ContentIdentity.ContentIdentityEqualityComparer _identityComparer;
private readonly Dictionary<ContentIdentity, int> _identities;
private readonly Dictionary<ContentIdentity, string> _contentTypes;
@@ -21,15 +20,15 @@ namespace Orchard.ContentManagement {
private int _currentIndex;
public ImportContentSession(IContentManager contentManager) {
_identityComparer = new ContentIdentity.ContentIdentityEqualityComparer();
var identityComparer = new ContentIdentity.ContentIdentityEqualityComparer();
_contentManager = contentManager;
_identities = new Dictionary<ContentIdentity, int>(_identityComparer);
_contentTypes = new Dictionary<ContentIdentity, string>(_identityComparer);
_identities = new Dictionary<ContentIdentity, int>(identityComparer);
_contentTypes = new Dictionary<ContentIdentity, string>(identityComparer);
_draftVersionRecordIds = new Dictionary<int, int>();
_allIdentitiesForImport = new List<ContentIdentity>();
_allIdentitiesForImportStatus = new Dictionary<ContentIdentity, bool>(_identityComparer);
_allIdentitiesForImportStatus = new Dictionary<ContentIdentity, bool>(identityComparer);
_dependencyIdentities = new Queue<ContentIdentity>();
}