mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Merge
--HG-- branch : dev
This commit is contained in:
306
src/Orchard.Tests.Modules/Indexing/IndexingTaskExecutorTests.cs
Normal file
306
src/Orchard.Tests.Modules/Indexing/IndexingTaskExecutorTests.cs
Normal file
@@ -0,0 +1,306 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using Lucene.Services;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ContentManagement.MetaData.Builders;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Core.Common.Handlers;
|
||||
using Orchard.Core.Common.Models;
|
||||
using Orchard.Data;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.FileSystems.AppData;
|
||||
using Orchard.Indexing;
|
||||
using Orchard.Indexing.Handlers;
|
||||
using Orchard.Indexing.Models;
|
||||
using Orchard.Indexing.Services;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Security;
|
||||
using Orchard.Tasks.Indexing;
|
||||
using Orchard.Tests.FileSystems.AppData;
|
||||
using Orchard.Tests.Stubs;
|
||||
|
||||
namespace Orchard.Tests.Modules.Indexing {
|
||||
public class IndexingTaskExecutorTests : DatabaseEnabledTestsBase {
|
||||
private IIndexProvider _provider;
|
||||
private IAppDataFolder _appDataFolder;
|
||||
private ShellSettings _shellSettings;
|
||||
private IIndexNotifierHandler _indexNotifier;
|
||||
private IContentManager _contentManager;
|
||||
private Mock<IContentDefinitionManager> _contentDefinitionManager;
|
||||
private StubLogger _logger;
|
||||
private const string IndexName = "Search";
|
||||
|
||||
private readonly string _basePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
|
||||
[TestFixtureTearDown]
|
||||
public void Clean() {
|
||||
if (Directory.Exists(_basePath)) {
|
||||
Directory.Delete(_basePath, true);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register(ContainerBuilder builder) {
|
||||
if (Directory.Exists(_basePath)) {
|
||||
Directory.Delete(_basePath, true);
|
||||
}
|
||||
Directory.CreateDirectory(_basePath);
|
||||
_contentDefinitionManager = new Mock<IContentDefinitionManager>();
|
||||
_appDataFolder = AppDataFolderTests.CreateAppDataFolder(_basePath);
|
||||
|
||||
builder.RegisterType<LuceneIndexProvider>().As<IIndexProvider>();
|
||||
builder.RegisterInstance(_appDataFolder).As<IAppDataFolder>();
|
||||
builder.RegisterType<IndexingTaskExecutor>().As<IIndexNotifierHandler>();
|
||||
builder.RegisterType<DefaultIndexManager>().As<IIndexManager>();
|
||||
builder.RegisterType<IndexingTaskManager>().As<IIndexingTaskManager>();
|
||||
builder.RegisterType<IndexSynLock>().As<IIndexSynLock>();
|
||||
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
|
||||
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
|
||||
builder.RegisterInstance(_contentDefinitionManager.Object);
|
||||
builder.RegisterInstance(new Mock<IContentDisplay>().Object);
|
||||
|
||||
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
|
||||
builder.RegisterInstance(new Mock<ITransactionManager>().Object);
|
||||
builder.RegisterInstance(new Mock<IAuthorizer>().Object);
|
||||
builder.RegisterType<OrchardServices>().As<IOrchardServices>();
|
||||
|
||||
builder.RegisterType<ThingHandler>().As<IContentHandler>();
|
||||
builder.RegisterType<CreateIndexingTaskHandler>().As<IContentHandler>();
|
||||
|
||||
builder.RegisterType<DefaultContentQuery>().As<IContentQuery>();
|
||||
builder.RegisterType<BodyPartHandler>().As<IContentHandler>();
|
||||
builder.RegisterType<StubExtensionManager>().As<IExtensionManager>();
|
||||
|
||||
// setting up a ShellSettings instance
|
||||
_shellSettings = new ShellSettings { Name = "My Site" };
|
||||
builder.RegisterInstance(_shellSettings).As<ShellSettings>();
|
||||
}
|
||||
|
||||
protected override IEnumerable<Type> DatabaseTypes {
|
||||
get {
|
||||
return new[] { typeof(IndexingTaskRecord),
|
||||
typeof(ContentTypeRecord),
|
||||
typeof(ContentItemRecord),
|
||||
typeof(ContentItemVersionRecord),
|
||||
typeof(BodyPartRecord),
|
||||
typeof(CommonPartRecord),
|
||||
typeof(CommonPartVersionRecord),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public override void Init() {
|
||||
base.Init();
|
||||
|
||||
_provider = _container.Resolve<IIndexProvider>();
|
||||
_indexNotifier = _container.Resolve<IIndexNotifierHandler>();
|
||||
_contentManager = _container.Resolve<IContentManager>();
|
||||
((IndexingTaskExecutor)_indexNotifier).Logger = _logger = new StubLogger();
|
||||
|
||||
var thingType = new ContentTypeDefinitionBuilder()
|
||||
.Named(ThingDriver.ContentTypeName)
|
||||
.WithSetting("TypeIndexing.Included", "true")
|
||||
.Build();
|
||||
|
||||
_contentDefinitionManager
|
||||
.Setup(x => x.GetTypeDefinition(ThingDriver.ContentTypeName))
|
||||
.Returns(thingType);
|
||||
}
|
||||
|
||||
private string[] Indexes() {
|
||||
return new DirectoryInfo(Path.Combine(_basePath, "Sites", "My Site", "Indexes")).GetDirectories().Select(d => d.Name).ToArray();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IndexShouldBeEmptyWhenThereIsNoContent() {
|
||||
_indexNotifier.UpdateIndex(IndexName);
|
||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(0));
|
||||
Assert.That(_logger.LogEntries.Count(), Is.EqualTo(2));
|
||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Rebuild index started"));
|
||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Index update requested, nothing to do"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldIngoreNonIndexableContentWhenRebuildingTheIndex() {
|
||||
var alphaType = new ContentTypeDefinitionBuilder()
|
||||
.Named("alpha")
|
||||
.Build();
|
||||
|
||||
_contentDefinitionManager
|
||||
.Setup(x => x.GetTypeDefinition("alpha"))
|
||||
.Returns(alphaType);
|
||||
|
||||
_contentManager.Create("alpha");
|
||||
|
||||
_indexNotifier.UpdateIndex(IndexName);
|
||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(0));
|
||||
Assert.That(_logger.LogEntries.Count(), Is.EqualTo(2));
|
||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Rebuild index started"));
|
||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Index update requested, nothing to do"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldNotIndexContentIfIndexDocumentIsEmpty() {
|
||||
var alphaType = new ContentTypeDefinitionBuilder()
|
||||
.Named("alpha")
|
||||
.WithSetting("TypeIndexing.Included", "true") // the content types should be indexed, but there is no content at all
|
||||
.Build();
|
||||
|
||||
_contentDefinitionManager
|
||||
.Setup(x => x.GetTypeDefinition("alpha"))
|
||||
.Returns(alphaType);
|
||||
|
||||
_contentManager.Create("alpha");
|
||||
|
||||
_indexNotifier.UpdateIndex(IndexName);
|
||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(0));
|
||||
Assert.That(_logger.LogEntries.Count(), Is.EqualTo(2));
|
||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Rebuild index started"));
|
||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Index update requested, nothing to do"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldIndexContentIfSettingsIsSetAndHandlerIsProvided() {
|
||||
var content = _contentManager.Create<Thing>(ThingDriver.ContentTypeName);
|
||||
content.Text = "Lorem ipsum";
|
||||
|
||||
_indexNotifier.UpdateIndex(IndexName);
|
||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
||||
Assert.That(_logger.LogEntries.Count(), Is.EqualTo(3));
|
||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Rebuild index started"));
|
||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Processing {0} indexing tasks"));
|
||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Added content items to index: {0}"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldUpdateTheIndexWhenContentIsPublished() {
|
||||
_contentManager.Create<Thing>(ThingDriver.ContentTypeName).Text = "Lorem ipsum";
|
||||
_indexNotifier.UpdateIndex(IndexName);
|
||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Rebuild index started"));
|
||||
_logger.Clear();
|
||||
|
||||
_contentManager.Create<Thing>(ThingDriver.ContentTypeName).Text = "Lorem ipsum";
|
||||
_indexNotifier.UpdateIndex(IndexName);
|
||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(2));
|
||||
Assert.That(_logger.LogEntries, Has.None.Matches<LogEntry>(entry => entry.LogFormat == "Rebuild index started"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldUpdateTheIndexWhenContentIsUnPublished() {
|
||||
_contentManager.Create<Thing>(ThingDriver.ContentTypeName).Text = "Lorem ipsum";
|
||||
_clock.Advance(TimeSpan.FromSeconds(1));
|
||||
|
||||
_indexNotifier.UpdateIndex(IndexName);
|
||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Rebuild index started"));
|
||||
_logger.Clear();
|
||||
|
||||
var content = _contentManager.Create<Thing>(ThingDriver.ContentTypeName);
|
||||
content.Text = "Lorem ipsum";
|
||||
_clock.Advance(TimeSpan.FromSeconds(1));
|
||||
|
||||
_indexNotifier.UpdateIndex(IndexName);
|
||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(2));
|
||||
Assert.That(_logger.LogEntries, Has.None.Matches<LogEntry>(entry => entry.LogFormat == "Rebuild index started"));
|
||||
_clock.Advance(TimeSpan.FromSeconds(1));
|
||||
|
||||
_contentManager.Unpublish(content.ContentItem);
|
||||
_clock.Advance(TimeSpan.FromSeconds(1));
|
||||
|
||||
_indexNotifier.UpdateIndex(IndexName);
|
||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
||||
Assert.That(_logger.LogEntries, Has.None.Matches<LogEntry>(entry => entry.LogFormat == "Rebuild index started"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldRemoveFromIndexEvenIfPublishedAndUnpublishedInTheSameSecond() {
|
||||
// This test is to ensure that when a task is created, all previous tasks for the same content item
|
||||
// are also removed, and thus that multiple tasks don't conflict while updating the index
|
||||
|
||||
_contentManager.Create<Thing>(ThingDriver.ContentTypeName).Text = "Lorem ipsum";
|
||||
_clock.Advance(TimeSpan.FromSeconds(1));
|
||||
|
||||
_indexNotifier.UpdateIndex(IndexName);
|
||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
||||
Assert.That(_logger.LogEntries, Has.Some.Matches<LogEntry>(entry => entry.LogFormat == "Rebuild index started"));
|
||||
_logger.Clear();
|
||||
|
||||
var content = _contentManager.Create<Thing>(ThingDriver.ContentTypeName);
|
||||
content.Text = "Lorem ipsum";
|
||||
|
||||
_indexNotifier.UpdateIndex(IndexName);
|
||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(2));
|
||||
Assert.That(_logger.LogEntries, Has.None.Matches<LogEntry>(entry => entry.LogFormat == "Rebuild index started"));
|
||||
|
||||
_contentManager.Unpublish(content.ContentItem);
|
||||
|
||||
_indexNotifier.UpdateIndex(IndexName);
|
||||
Assert.That(_provider.NumDocs(IndexName), Is.EqualTo(1));
|
||||
Assert.That(_logger.LogEntries, Has.None.Matches<LogEntry>(entry => entry.LogFormat == "Rebuild index started"));
|
||||
}
|
||||
|
||||
#region Stubs
|
||||
public class ThingHandler : ContentHandler {
|
||||
public ThingHandler() {
|
||||
Filters.Add(new ActivatingFilter<Thing>(ThingDriver.ContentTypeName));
|
||||
Filters.Add(new ActivatingFilter<ContentPart<CommonPartVersionRecord>>(ThingDriver.ContentTypeName));
|
||||
Filters.Add(new ActivatingFilter<CommonPart>(ThingDriver.ContentTypeName));
|
||||
Filters.Add(new ActivatingFilter<BodyPart>(ThingDriver.ContentTypeName));
|
||||
}
|
||||
}
|
||||
|
||||
public class Thing : ContentPart {
|
||||
public string Text {
|
||||
get { return this.As<BodyPart>().Text; }
|
||||
set { this.As<BodyPart>().Text = value; }
|
||||
}
|
||||
}
|
||||
|
||||
public class ThingDriver : ContentPartDriver<Thing> {
|
||||
public static readonly string ContentTypeName = "thing";
|
||||
}
|
||||
|
||||
public class LogEntry {
|
||||
public Exception LogException { get; set; }
|
||||
public string LogFormat { get; set; }
|
||||
public object[] LogArgs { get; set; }
|
||||
public LogLevel LogLevel { get; set; }
|
||||
}
|
||||
|
||||
public class StubLogger : ILogger {
|
||||
public List<LogEntry> LogEntries { get; set; }
|
||||
|
||||
public StubLogger() {
|
||||
LogEntries = new List<LogEntry>();
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
LogEntries.Clear();
|
||||
}
|
||||
|
||||
public bool IsEnabled(LogLevel level) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Log(LogLevel level, Exception exception, string format, params object[] args) {
|
||||
LogEntries.Add(new LogEntry() {
|
||||
LogArgs = args,
|
||||
LogException = exception,
|
||||
LogFormat = format,
|
||||
LogLevel = level
|
||||
});
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -140,6 +140,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="CodeGeneration\Commands\CodeGenerationCommandsTests.cs" />
|
||||
<Compile Include="Comments\Services\CommentServiceTests.cs" />
|
||||
<Compile Include="Indexing\IndexingTaskExecutorTests.cs" />
|
||||
<Compile Include="Indexing\LuceneIndexProviderTests.cs" />
|
||||
<Compile Include="Indexing\LuceneSearchBuilderTests.cs" />
|
||||
<Compile Include="Media\Services\MediaServiceTests.cs" />
|
||||
|
@@ -20,7 +20,7 @@
|
||||
|
||||
for (i = 0; i < classes.length; i++) {
|
||||
if (classes[i].indexOf("zone-") === 0) {
|
||||
$(this).append('<div class="zone-name">' + classes[i].substr(classes[i].indexOf("-")+1) + '</div>');
|
||||
$(this).append('<div class="zone-name">' + classes[i].substr(classes[i].indexOf("-") + 1) + '</div>');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,5 +39,43 @@
|
||||
_this.prev().show("fast", function () { _this.addClass(open).html("«"); });
|
||||
}
|
||||
});
|
||||
|
||||
$("div.shape-tracing.wrapper").click(function (e) {
|
||||
var _this = $(this);
|
||||
var classes = $(this).attr("class").split(' ');
|
||||
e.stopPropagation();
|
||||
for (i = 0; i < classes.length; i++) {
|
||||
if (classes[i].indexOf("shapeId-") === 0) {
|
||||
var shapeId = classes[i].substr(classes[i].indexOf("-") + 1);
|
||||
$("div.shape-tracing.wrapper").toggleClass('selected', false);
|
||||
_this.toggleClass('selected', true);
|
||||
$("div.shape-tracing.meta").toggle(false);
|
||||
$("div.shape-tracing.meta.shapeId-" + shapeId).toggle(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* tabs */
|
||||
function bindTab(selector) {
|
||||
$('li' + selector).click(function () {
|
||||
var _this = $(this);
|
||||
|
||||
// toggle the selected class on the tab li
|
||||
_this.parent().children('li').toggleClass('selected', false);
|
||||
_this.toggleClass('selected', true);
|
||||
|
||||
// hide all tabs and display the selected one
|
||||
var wrapper = _this.parent().parent().first();
|
||||
wrapper.children('.content').children().toggle(false);
|
||||
wrapper.children('.content').children('div' + selector).toggle(true);
|
||||
});
|
||||
}
|
||||
|
||||
bindTab('.shape');
|
||||
bindTab('.model');
|
||||
bindTab('.placement');
|
||||
bindTab('.templates');
|
||||
bindTab('.source');
|
||||
bindTab('.html');
|
||||
});
|
||||
})(jQuery);
|
||||
|
@@ -12,9 +12,6 @@
|
||||
position:fixed;
|
||||
top:0;
|
||||
}
|
||||
#debug-control :hover {
|
||||
color:yellow;
|
||||
}
|
||||
#debug-control .debug-active {
|
||||
color:Lime;
|
||||
}
|
||||
@@ -48,30 +45,27 @@
|
||||
min-width:20px;
|
||||
min-height:20px;
|
||||
}
|
||||
.debug-shapes body
|
||||
{
|
||||
|
||||
.debug-shapes body {
|
||||
margin-top:25px;
|
||||
}
|
||||
|
||||
.debug-shapes .shape-tracing .wrapper :hover {
|
||||
background:#E0E9EE;
|
||||
}
|
||||
|
||||
.shape-tracing .meta {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.debug-shapes .shape-tracing .meta {
|
||||
.debug-shapes div.shape-tracing.meta {
|
||||
clear:both;
|
||||
display:block;
|
||||
background:#cfc;
|
||||
background:#ccc;
|
||||
font-size:9pt;
|
||||
font-family:Segoe;
|
||||
color:black;
|
||||
margin-top:5px;
|
||||
position:fixed;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
width:100%;
|
||||
z-index:999;
|
||||
}
|
||||
|
||||
.debug-zones .Zone {
|
||||
.debug-zones .shapeType-Zone {
|
||||
border:1px dashed grey;
|
||||
margin:5px;
|
||||
position: relative;
|
||||
@@ -84,10 +78,6 @@
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.debug-shapes .Zone :hover {
|
||||
background:#E0E9EE;
|
||||
}
|
||||
|
||||
.meta .shape {
|
||||
color:black;
|
||||
}
|
||||
@@ -98,4 +88,53 @@
|
||||
|
||||
.meta .wrappers {
|
||||
color:green;
|
||||
}
|
||||
}
|
||||
|
||||
.debug-shapes div.wrapper.selected {
|
||||
background-color:#BAFFC3;
|
||||
}
|
||||
|
||||
/* tabs */
|
||||
|
||||
ul.debuggerMenu { margin:8px 0 -8px 0; }
|
||||
|
||||
.debuggerMenu li {
|
||||
color:#4053DE;
|
||||
display: inline;
|
||||
font-size:15px;
|
||||
line-height:32px;
|
||||
}
|
||||
.debuggerMenu li {
|
||||
margin:0 2px;
|
||||
padding: 8px 18px 7px 18px;
|
||||
}
|
||||
.debuggerMenu li.middle, .debuggerMenu li.first, .debuggerMenu li.last {
|
||||
border:1px solid #E4E5E6;
|
||||
border-bottom:none;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
.debuggerMenu li.first {
|
||||
margin-left:16px;
|
||||
}
|
||||
.debuggerMenu li.selected {
|
||||
background-color: #fff;
|
||||
}
|
||||
.debuggerMenu li.selected, .debuggerMenu li:hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
.debuggerMenu li.selected a {
|
||||
color: #3A822E;
|
||||
}
|
||||
|
||||
.debug-shapes div.shape-tracing.meta .content {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
margin:8px 0 0 0;
|
||||
border: 1px solid #e4e5e6;
|
||||
height:10em;
|
||||
overflow:scroll;
|
||||
/*CSS3 properties*/
|
||||
border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
}
|
||||
|
@@ -4,8 +4,7 @@
|
||||
@using System.Xml;
|
||||
|
||||
@{
|
||||
Script.Require("jQuery");
|
||||
Script.Include("tooltip.min.js");
|
||||
Script.Require("jQueryUI_Tabs");
|
||||
Script.Include("orchard-designertools-shapetracing.js");
|
||||
Style.Include("orchard-designertools-shapetracing.css");
|
||||
|
||||
@@ -13,6 +12,7 @@
|
||||
var shapeTable = workContext.Resolve<IShapeTableManager>().GetShapeTable(workContext.CurrentTheme.Id);
|
||||
var descriptor = shapeTable.Descriptors[Model.Metadata.Type];
|
||||
}
|
||||
|
||||
@functions {
|
||||
string FormatShapeFilename(string type, string themeId) {
|
||||
return "~/Themes/" + themeId + "/Views/" + type.Replace("__", "-").Replace("_", ".") + ".cshtml";
|
||||
@@ -28,34 +28,66 @@
|
||||
}
|
||||
}
|
||||
|
||||
<div class="shape-tracing wrapper @Model.Metadata.Type">
|
||||
@Display(Model.Metadata.ChildContent)
|
||||
<div class="shape-tracing wrapper shapeType-@Model.Metadata.Type shapeId-@Model.GetHashCode() " title="@Model.Metadata.Type">
|
||||
@Display(Model.Metadata.ChildContent)
|
||||
|
||||
<div class="shape-tracing meta">
|
||||
<div class="shape">
|
||||
Shape: @Model.Metadata.Type <br />
|
||||
Definition: @descriptor.BindingSource <br />
|
||||
Display Type: @(Model.Metadata.DisplayType ?? "n/a")<br />
|
||||
Position: @(Model.Metadata.Position ?? "n/a") <br />
|
||||
Placement Source: @(Model.Metadata.PlacementSource ?? "n/a") <br />
|
||||
</div>
|
||||
<div class="shape-tracing meta shapeId-@Model.GetHashCode()" style="display:none">
|
||||
<ul class="debuggerMenu">
|
||||
<li class="shape selected first"><a href="#">Shape</a></li>
|
||||
<li class="model middle"><a href="#">Model</a></li>
|
||||
<li class="placement middle"><a href="#">Placement</a></li>
|
||||
<li class="templates middle"><a href="#">Templates</a></li>
|
||||
<li class="source middle"><a href="#">Source</a></li>
|
||||
<li class="html last"><a href="#">HTML</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="alternates">
|
||||
@foreach(var alternate in Model.Metadata.Alternates) {
|
||||
var formatted = @FormatShapeFilename(alternate, workContext.CurrentTheme.Id);
|
||||
<div>@formatted</div>
|
||||
}
|
||||
</div>
|
||||
<div class="wrappers">
|
||||
@foreach(var wrapper in Model.Metadata.Wrappers) {
|
||||
if(wrapper != "ShapeTracing_Wrapper") {
|
||||
var formatted = @FormatShapeFilename(wrapper, workContext.CurrentTheme.Id);
|
||||
<div>@formatted</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<div class="dump" style="display:none">
|
||||
<pre>@DumpObject((object)Model)</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="shape">
|
||||
Shape: @Model.Metadata.Type <br />
|
||||
Definition: @descriptor.BindingSource <br />
|
||||
Display Type: @(Model.Metadata.DisplayType ?? "n/a")<br />
|
||||
Position: @(Model.Metadata.Position ?? "n/a") <br />
|
||||
Placement Source: @(Model.Metadata.PlacementSource ?? "n/a") <br />
|
||||
</div>
|
||||
|
||||
<div class="model" style="display:none">
|
||||
<pre>@DumpObject((object)Model)</pre>
|
||||
</div>
|
||||
|
||||
<div class="placement" style="display:none">
|
||||
@if(Model.Metadata.PlacementSource != null) {
|
||||
// System.IO.File.ReadAllText(VirtualPathUtility.GetFileName(Model.Metadata.PlacementSource))
|
||||
}
|
||||
else {
|
||||
<div>n/a</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="templates" style="display:none">
|
||||
<div class="alternates">
|
||||
<span>Alternates</span>
|
||||
@foreach(var alternate in Model.Metadata.Alternates) {
|
||||
var formatted = @FormatShapeFilename(alternate, workContext.CurrentTheme.Id);
|
||||
<div>@formatted</div>
|
||||
}
|
||||
</div>
|
||||
<div class="wrappers">
|
||||
<span >Wrappers</span>
|
||||
@foreach(var wrapper in Model.Metadata.Wrappers) {
|
||||
if(wrapper != "ShapeTracing_Wrapper") {
|
||||
var formatted = @FormatShapeFilename(wrapper, workContext.CurrentTheme.Id);
|
||||
<div>@formatted</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="source" style="display:none">
|
||||
</div>
|
||||
|
||||
<div class="html" style="display:none">
|
||||
<pre>@HttpUtility.HtmlEncode(Display(Model.Metadata.ChildContent))</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -23,7 +23,6 @@ namespace Orchard.Indexing.Services {
|
||||
private readonly IIndexingTaskManager _indexingTaskManager;
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly IIndexSynLock _indexSynLock;
|
||||
private const string SearchIndexName = "Search";
|
||||
|
||||
public IndexingTaskExecutor(
|
||||
IClock clock,
|
||||
@@ -44,7 +43,7 @@ namespace Orchard.Indexing.Services {
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public void UpdateIndex(string indexName) {
|
||||
var synLock = _indexSynLock.GetSynLock(SearchIndexName);
|
||||
var synLock = _indexSynLock.GetSynLock(indexName);
|
||||
|
||||
if (!System.Threading.Monitor.TryEnter(synLock)) {
|
||||
Logger.Information("Index was requested but was already running");
|
||||
@@ -63,7 +62,7 @@ namespace Orchard.Indexing.Services {
|
||||
DateTime? lastIndexUtc;
|
||||
|
||||
// Do we need to rebuild the full index (first time module is used, or rebuild index requested) ?
|
||||
if (_indexProvider.IsEmpty(SearchIndexName)) {
|
||||
if (_indexProvider.IsEmpty(indexName)) {
|
||||
Logger.Information("Rebuild index started");
|
||||
|
||||
// mark current last task, as we should process older ones (in case of rebuild index only)
|
||||
@@ -93,10 +92,10 @@ namespace Orchard.Indexing.Services {
|
||||
}
|
||||
else {
|
||||
// retrieve last processed index time
|
||||
lastIndexUtc = _indexProvider.GetLastIndexUtc(SearchIndexName);
|
||||
lastIndexUtc = _indexProvider.GetLastIndexUtc(indexName);
|
||||
}
|
||||
|
||||
_indexProvider.SetLastIndexUtc(SearchIndexName, _clock.UtcNow);
|
||||
_indexProvider.SetLastIndexUtc(indexName, _clock.UtcNow);
|
||||
|
||||
// retrieve not yet processed tasks
|
||||
var taskRecords = lastIndexUtc == null
|
||||
@@ -111,15 +110,15 @@ namespace Orchard.Indexing.Services {
|
||||
|
||||
Logger.Information("Processing {0} indexing tasks", taskRecords.Length);
|
||||
|
||||
if (!_indexProvider.Exists(SearchIndexName)) {
|
||||
_indexProvider.CreateIndex(SearchIndexName);
|
||||
if (!_indexProvider.Exists(indexName)) {
|
||||
_indexProvider.CreateIndex(indexName);
|
||||
}
|
||||
|
||||
// process Delete tasks
|
||||
try {
|
||||
var deleteIds = taskRecords.Where(t => t.Action == IndexingTaskRecord.Delete).Select(t => t.ContentItemRecord.Id).ToArray();
|
||||
if (deleteIds.Length > 0) {
|
||||
_indexProvider.Delete(SearchIndexName, deleteIds);
|
||||
_indexProvider.Delete(indexName, deleteIds);
|
||||
Logger.Information("Deleted content items from index: {0}", String.Join(", ", deleteIds));
|
||||
}
|
||||
}
|
||||
@@ -151,7 +150,7 @@ namespace Orchard.Indexing.Services {
|
||||
|
||||
if (updateIndexDocuments.Count > 0) {
|
||||
try {
|
||||
_indexProvider.Store(SearchIndexName, updateIndexDocuments);
|
||||
_indexProvider.Store(indexName, updateIndexDocuments);
|
||||
Logger.Information("Added content items to index: {0}", String.Join(", ", addedContentItemIds));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
|
@@ -68,6 +68,8 @@ namespace Orchard.Indexing.Services {
|
||||
foreach (var task in tasks) {
|
||||
_repository.Delete(task);
|
||||
}
|
||||
|
||||
_repository.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -40,8 +40,7 @@ namespace Orchard.Indexing.Settings {
|
||||
/// </summary>
|
||||
private void CreateIndexingTasks()
|
||||
{
|
||||
if (!_tasksCreated)
|
||||
{
|
||||
if (!_tasksCreated) {
|
||||
CreateTasksForType(_contentTypeName);
|
||||
_tasksCreated = true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user