mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Incremental work on diffgram.
This commit is contained in:
@@ -69,9 +69,14 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="System.Configuration" />
|
<Reference Include="System.Configuration" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="xmldiffpatch, Version=1.0.8.28, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>Lib\XmlDiffPatch\xmldiffpatch.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Placement.info" />
|
<None Include="Placement.info" />
|
||||||
|
<Content Include="Lib\XmlDiffPatch\xmldiffpatch.dll" />
|
||||||
<Content Include="Recipes\audit-trail.recipe.xml" />
|
<Content Include="Recipes\audit-trail.recipe.xml" />
|
||||||
<Content Include="Scripts\audit-trail-admin.js" />
|
<Content Include="Scripts\audit-trail-admin.js" />
|
||||||
<Content Include="Styles\admin.css" />
|
<Content Include="Styles\admin.css" />
|
||||||
@@ -141,6 +146,10 @@
|
|||||||
<Compile Include="ImportExport\AuditTrailImportHandler.cs" />
|
<Compile Include="ImportExport\AuditTrailImportHandler.cs" />
|
||||||
<Compile Include="Models\AuditTrailEventRecordResult.cs" />
|
<Compile Include="Models\AuditTrailEventRecordResult.cs" />
|
||||||
<Compile Include="Providers\Content\ContentAuditTrailEventShapes.cs" />
|
<Compile Include="Providers\Content\ContentAuditTrailEventShapes.cs" />
|
||||||
|
<Compile Include="Providers\Content\DiffGramAnalyzer.cs" />
|
||||||
|
<Compile Include="Providers\Content\DiffNode.cs" />
|
||||||
|
<Compile Include="Providers\Content\DiffType.cs" />
|
||||||
|
<Compile Include="Providers\Content\IDiffGramAnalyzer.cs" />
|
||||||
<Compile Include="ViewModels\AuditTrailCategorySettingsViewModel.cs" />
|
<Compile Include="ViewModels\AuditTrailCategorySettingsViewModel.cs" />
|
||||||
<Compile Include="ViewModels\AuditTrailEventSettingsViewModel.cs" />
|
<Compile Include="ViewModels\AuditTrailEventSettingsViewModel.cs" />
|
||||||
<Compile Include="ViewModels\AuditTrailSiteSettingsViewModel.cs" />
|
<Compile Include="ViewModels\AuditTrailSiteSettingsViewModel.cs" />
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Orchard.AuditTrail.Helpers;
|
using Orchard.AuditTrail.Helpers;
|
||||||
using Orchard.AuditTrail.Models;
|
using Orchard.AuditTrail.Models;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
@@ -8,8 +9,11 @@ using Orchard.Environment;
|
|||||||
namespace Orchard.AuditTrail.Providers.Content {
|
namespace Orchard.AuditTrail.Providers.Content {
|
||||||
public class ContentAuditTrailEventShapes : IShapeTableProvider {
|
public class ContentAuditTrailEventShapes : IShapeTableProvider {
|
||||||
private readonly Work<IContentManager> _contentManager;
|
private readonly Work<IContentManager> _contentManager;
|
||||||
public ContentAuditTrailEventShapes(Work<IContentManager> contentManager) {
|
private readonly IDiffGramAnalyzer _analyzer;
|
||||||
|
|
||||||
|
public ContentAuditTrailEventShapes(Work<IContentManager> contentManager, IDiffGramAnalyzer analyzer) {
|
||||||
_contentManager = contentManager;
|
_contentManager = contentManager;
|
||||||
|
_analyzer = analyzer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Discover(ShapeTableBuilder builder) {
|
public void Discover(ShapeTableBuilder builder) {
|
||||||
@@ -25,6 +29,14 @@ namespace Orchard.AuditTrail.Providers.Content {
|
|||||||
var contentItem = _contentManager.Value.Get(contentItemId);
|
var contentItem = _contentManager.Value.Get(contentItemId);
|
||||||
var previousVersion = previousContentItemVersionId > 0 ? _contentManager.Value.Get(contentItemId, VersionOptions.VersionRecord(previousContentItemVersionId)) : default(ContentItem);
|
var previousVersion = previousContentItemVersionId > 0 ? _contentManager.Value.Get(contentItemId, VersionOptions.VersionRecord(previousContentItemVersionId)) : default(ContentItem);
|
||||||
|
|
||||||
|
if (previousVersion != null) {
|
||||||
|
var previousVersionXml = _contentManager.Value.Export(previousVersion);
|
||||||
|
var currentVersionXml = _contentManager.Value.Export(contentItem);
|
||||||
|
var diffGram = _analyzer.GenerateDiffGram(previousVersionXml, currentVersionXml);
|
||||||
|
var diffNodes = _analyzer.Analyze(previousVersionXml, diffGram).ToArray();
|
||||||
|
context.Shape.DiffNodes = diffNodes;
|
||||||
|
}
|
||||||
|
|
||||||
context.Shape.ContentItem = contentItem;
|
context.Shape.ContentItem = contentItem;
|
||||||
context.Shape.PreviousVersion = previousVersion;
|
context.Shape.PreviousVersion = previousVersion;
|
||||||
});
|
});
|
||||||
|
@@ -0,0 +1,98 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using Microsoft.XmlDiffPatch;
|
||||||
|
|
||||||
|
namespace Orchard.AuditTrail.Providers.Content {
|
||||||
|
public class DiffGramAnalyzer : IDiffGramAnalyzer {
|
||||||
|
public XElement GenerateDiffGram(XElement element1, XElement element2) {
|
||||||
|
using(var node1Reader = element1.CreateReader())
|
||||||
|
using (var node2Reader = element2.CreateReader()) {
|
||||||
|
var result = new XDocument();
|
||||||
|
using (var writer = result.CreateWriter()) {
|
||||||
|
var diff =
|
||||||
|
new XmlDiff(XmlDiffOptions.IgnoreChildOrder | XmlDiffOptions.IgnoreWhitespace |
|
||||||
|
XmlDiffOptions.IgnoreComments | XmlDiffOptions.IgnoreXmlDecl);
|
||||||
|
diff.Compare(node1Reader, node2Reader, writer);
|
||||||
|
writer.Flush();
|
||||||
|
writer.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.Root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<DiffNode> Analyze(XElement original, XElement diffGram) {
|
||||||
|
var stack = new Stack<XElement>();
|
||||||
|
|
||||||
|
stack.Push(new XElement("original", original));
|
||||||
|
|
||||||
|
using (var reader = diffGram.CreateReader()) {
|
||||||
|
while (!reader.EOF) {
|
||||||
|
var doRead = true;
|
||||||
|
if (reader.LocalName == "xmldiff")
|
||||||
|
reader.Read();
|
||||||
|
switch (reader.NodeType) {
|
||||||
|
case XmlNodeType.Element:
|
||||||
|
var match = reader.GetAttribute("match");
|
||||||
|
var isAttributeChange = match != null && match.StartsWith("@");
|
||||||
|
var index = match == null || isAttributeChange ? default(int?) : Int32.Parse(match) - 1;
|
||||||
|
var diffType = reader.LocalName;
|
||||||
|
var currentElement = stack.Peek();
|
||||||
|
|
||||||
|
if (currentElement.HasElements && index != null) {
|
||||||
|
var sourceElement = currentElement.Elements().ElementAt(index.Value);
|
||||||
|
stack.Push(sourceElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diffType != "node") {
|
||||||
|
switch (diffType) {
|
||||||
|
case "change":
|
||||||
|
if (isAttributeChange) {
|
||||||
|
var attributeName = match.Substring(1);
|
||||||
|
var originalValue = currentElement.Attribute(attributeName).Value;
|
||||||
|
var currentValue = reader.ReadElementContentAsString();
|
||||||
|
doRead = false;
|
||||||
|
yield return
|
||||||
|
new DiffNode {
|
||||||
|
Type = DiffType.Change,
|
||||||
|
ElementName = attributeName,
|
||||||
|
Previous = originalValue,
|
||||||
|
Current = currentValue
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var originalContent = currentElement.Value;
|
||||||
|
var currentContent = reader.ReadElementContentAsString();
|
||||||
|
stack.Pop();
|
||||||
|
doRead = false;
|
||||||
|
yield return
|
||||||
|
new DiffNode {
|
||||||
|
Type = DiffType.Change,
|
||||||
|
ElementName = currentElement.Name.ToString(),
|
||||||
|
Previous = originalContent,
|
||||||
|
Current = currentContent
|
||||||
|
};
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "add":
|
||||||
|
reader.Read();
|
||||||
|
var addedElementContent = reader.ReadElementContentAsString();
|
||||||
|
yield return new DiffNode { Type = DiffType.Addition, ElementName = reader.Name, Current = addedElementContent };
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case XmlNodeType.EndElement:
|
||||||
|
stack.Pop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (doRead)
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Orchard.AuditTrail.Providers.Content {
|
||||||
|
public class DiffNode {
|
||||||
|
public DiffType Type { get; set; }
|
||||||
|
public string ElementName { get; set; }
|
||||||
|
public string Previous { get; set; }
|
||||||
|
public string Current { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Orchard.AuditTrail.Providers.Content {
|
||||||
|
public enum DiffType {
|
||||||
|
Change,
|
||||||
|
Addition
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,9 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace Orchard.AuditTrail.Providers.Content {
|
||||||
|
public interface IDiffGramAnalyzer : IDependency {
|
||||||
|
XElement GenerateDiffGram(XElement element1, XElement element2);
|
||||||
|
IEnumerable<DiffNode> Analyze(XElement original, XElement diffGram);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user