diff --git a/src/Orchard.Tests.Modules/Indexing/LuceneSearchBuilderTests.cs b/src/Orchard.Tests.Modules/Indexing/LuceneSearchBuilderTests.cs index cd76eef81..7259f6b30 100644 --- a/src/Orchard.Tests.Modules/Indexing/LuceneSearchBuilderTests.cs +++ b/src/Orchard.Tests.Modules/Indexing/LuceneSearchBuilderTests.cs @@ -639,5 +639,24 @@ namespace Orchard.Tests.Modules.Indexing { .WithField("field3", 3).Mandatory().AsFilter() .Count(), Is.EqualTo(1)); } + + [Test] + public void ShouldReturnFacetedResults() { + _provider.CreateIndex("default"); + _provider.Store("default", _provider.New(1).Add("body", "michael is in the kitchen").Analyze()); + _provider.Store("default", _provider.New(2).Add("body", "michael has a cousin named michel").Analyze()); + _provider.Store("default", _provider.New(3).Add("body", "speak inside the mic").Analyze()); + _provider.Store("default", _provider.New(4).Add("body", "a dog is pursuing a cat").Analyze()); + _provider.Store("default", _provider.New(5).Add("body", "michael speaks to elephants").Analyze()); + + var michael = SearchBuilder.WithField("body", "michael").GetBits(); + var speak = SearchBuilder.WithField("body", "speak").GetBits(); + Assert.That(michael.Count(), Is.EqualTo(3)); + Assert.That(speak.Count(), Is.EqualTo(2)); + + Assert.That(speak.And(michael).Count(), Is.EqualTo(1)); + Assert.That(speak.Or(michael).Count(), Is.EqualTo(4)); + Assert.That(speak.Xor(michael).Count(), Is.EqualTo(3)); + } } } diff --git a/src/Orchard.Tests/DisplayManagement/NilTests.cs b/src/Orchard.Tests/DisplayManagement/NilTests.cs index ed12a5362..47a1cd24c 100644 --- a/src/Orchard.Tests/DisplayManagement/NilTests.cs +++ b/src/Orchard.Tests/DisplayManagement/NilTests.cs @@ -37,5 +37,11 @@ namespace Orchard.Tests.DisplayManagement { dynamic nil = Nil.Instance; Assert.That(nil.Foo.Bar.ToString(), Is.EqualTo("")); } + + [Test] + public void ConvertingToStringShouldReturnNullString() { + dynamic nil = Nil.Instance; + Assert.That((string)nil == null, Is.True); + } } } diff --git a/src/Orchard.Web/Core/Shapes/CoreShapes.cs b/src/Orchard.Web/Core/Shapes/CoreShapes.cs index 20627dc96..6fa37a3da 100644 --- a/src/Orchard.Web/Core/Shapes/CoreShapes.cs +++ b/src/Orchard.Web/Core/Shapes/CoreShapes.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; using System.IO; using System.Linq; using System.Web; @@ -28,20 +27,24 @@ namespace Orchard.Core.Shapes { private readonly Work _workContext; private readonly Work _resourceManager; private readonly Work _httpContextAccessor; + private readonly Work _shapeFactory; public CoreShapes( Work workContext, Work resourceManager, - Work httpContextAccessor + Work httpContextAccessor, + Work shapeFactory ) { _workContext = workContext; _resourceManager = resourceManager; _httpContextAccessor = httpContextAccessor; + _shapeFactory = shapeFactory; T = NullLocalizer.Instance; } public Localizer T { get; set; } + public dynamic New { get { return _shapeFactory.Value; } } public void Discover(ShapeTableBuilder builder) { // the root page shape named 'Layout' is wrapped with 'Document' @@ -490,49 +493,49 @@ namespace Orchard.Core.Shapes { routeData.Remove(pageKey); // to keep from having "page=1" in the query string } // first - Shape.Add(Display.Pager_First(Value: firstText, RouteValues: routeData, Pager: Shape)); + Shape.Add(New.Pager_First(Value: firstText, RouteValues: new RouteValueDictionary(routeData), Pager: Shape)); // previous if (currentPage > 2) { // also to keep from having "page=1" in the query string routeData[pageKey] = currentPage - 1; } - Shape.Add(Display.Pager_Previous(Value: previousText, RouteValues: routeData, Pager: Shape)); + Shape.Add(New.Pager_Previous(Value: previousText, RouteValues: new RouteValueDictionary(routeData), Pager: Shape)); } // gap at the beginning of the pager if (firstPage > 1 && numberOfPagesToShow > 0) { - Shape.Add(Display.Pager_Gap(Value: gapText, Pager: Shape)); + Shape.Add(New.Pager_Gap(Value: gapText, Pager: Shape)); } // page numbers - if (numberOfPagesToShow > 0 && firstPage != lastPage) { + if (numberOfPagesToShow > 0) { for (var p = firstPage; p <= lastPage; p++) { if (p == currentPage) { - Shape.Add(Display.Pager_CurrentPage(Value: p, RouteValues: routeData, Pager: Shape)); + Shape.Add(New.Pager_CurrentPage(Value: p, RouteValues: new RouteValueDictionary(routeData), Pager: Shape)); } else { if (p == 1) routeData.Remove(pageKey); else routeData[pageKey] = p; - Shape.Add(Display.Pager_Link(Value: p, RouteValues: routeData, Pager: Shape)); + Shape.Add(New.Pager_Link(Value: p, RouteValues: new RouteValueDictionary(routeData), Pager: Shape)); } } } // gap at the end of the pager if (lastPage < totalPageCount && numberOfPagesToShow > 0) { - Shape.Add(Display.Pager_Gap(Value: gapText, Pager: Shape)); + Shape.Add(New.Pager_Gap(Value: gapText, Pager: Shape)); } // next and last pages if (Page < totalPageCount) { // next routeData[pageKey] = Page + 1; - Shape.Add(Display.Pager_Next(Value: nextText, RouteValues: routeData, Pager: Shape)); + Shape.Add(New.Pager_Next(Value: nextText, RouteValues: new RouteValueDictionary(routeData), Pager: Shape)); // last routeData[pageKey] = totalPageCount; - Shape.Add(Display.Pager_Last(Value: lastText, RouteValues: routeData, Pager: Shape)); + Shape.Add(New.Pager_Last(Value: lastText, RouteValues: new RouteValueDictionary(routeData), Pager: Shape)); } return Display(Shape); @@ -562,7 +565,7 @@ namespace Orchard.Core.Shapes { [Shape] public IHtmlString Pager_CurrentPage(HtmlHelper Html, dynamic Display, object Value) { var tagBuilder = new TagBuilder("span"); - tagBuilder.InnerHtml = Html.Encode(Value is string ? (string)Value : Display(Value)); + tagBuilder.InnerHtml = EncodeOrDisplay(Value, Display, Html).ToString(); return MvcHtmlString.Create(tagBuilder.ToString()); } @@ -583,21 +586,13 @@ namespace Orchard.Core.Shapes { [Shape] public IHtmlString Pager_Link(HtmlHelper Html, dynamic Shape, dynamic Display, object Value) { - var RouteValues = (object)Shape.RouteValues; - RouteValueDictionary rvd; - if (RouteValues == null) { - rvd = new RouteValueDictionary(); - } - else { - rvd = RouteValues is RouteValueDictionary ? (RouteValueDictionary)RouteValues : new RouteValueDictionary(RouteValues); - } - - string value = Html.Encode(Value is string ? (string)Value : Display(Value)); - return @Html.ActionLink(value, (string)rvd["action"], (string)rvd["controller"], rvd, null); + Shape.Metadata.Alternates.Clear(); + Shape.Metadata.Type = "ActionLink"; + return Display(Shape); } [Shape] - public IHtmlString ActionLink(HtmlHelper Html, dynamic Shape, dynamic Display, object Value) { + public IHtmlString ActionLink(HtmlHelper Html, UrlHelper Url, dynamic Shape, dynamic Display, object Value) { var RouteValues = (object)Shape.RouteValues; RouteValueDictionary rvd; if (RouteValues == null) { @@ -606,15 +601,23 @@ namespace Orchard.Core.Shapes { else { rvd = RouteValues is RouteValueDictionary ? (RouteValueDictionary)RouteValues : new RouteValueDictionary(RouteValues); } - - string value = Html.Encode(Value is string ? (string)Value : Display(Value)); - return @Html.ActionLink(value, (string)rvd["action"], (string)rvd["controller"], rvd, null); + + var action = Url.Action((string)rvd["action"], (string)rvd["controller"], rvd); + + IEnumerable classes = Shape.Classes; + IDictionary attributes = Shape.Attributes; + attributes.Add("href", action); + string id = Shape.Id; + var tag = GetTagBuilder("a", id, classes, attributes); + tag.InnerHtml = EncodeOrDisplay(Value, Display, Html).ToString(); + + return Html.Raw(tag.ToString()); } [Shape] public IHtmlString Pager_Gap(HtmlHelper Html, dynamic Display, object Value) { var tagBuilder = new TagBuilder("span"); - tagBuilder.InnerHtml = Html.Encode(Value is string ? (string)Value : Display(Value)); + tagBuilder.InnerHtml = EncodeOrDisplay(Value, Display, Html).ToString(); return MvcHtmlString.Create(tagBuilder.ToString()); } @@ -628,37 +631,88 @@ namespace Orchard.Core.Shapes { string Id, IEnumerable Classes, IDictionary Attributes, + string ItemTag, IEnumerable ItemClasses, IDictionary ItemAttributes) { if (Items == null) return; + + // prevent multiple enumerations + var items = Items.ToList(); - var itemDisplayOutputs = Items.Select(item => Display(item)).Where(output => !string.IsNullOrWhiteSpace(output.ToHtmlString())).ToList(); - var count = itemDisplayOutputs.Count(); + // var itemDisplayOutputs = Items.Select(item => Display(item)).Where(output => !string.IsNullOrWhiteSpace(output.ToHtmlString())).ToList(); + var count = items.Count(); if (count < 1) return; - var listTagName = string.IsNullOrEmpty(Tag) ? "ul" : Tag; - const string itemTagName = "li"; + string listTagName = null; + + if (Tag != "-") { + listTagName = string.IsNullOrEmpty(Tag) ? "ul" : Tag; + } - var listTag = GetTagBuilder(listTagName, Id, Classes, Attributes); - Output.Write(listTag.ToString(TagRenderMode.StartTag)); + var listTag = String.IsNullOrEmpty(listTagName) ? null : GetTagBuilder(listTagName, Id, Classes, Attributes); + string itemTagName = null; + if (ItemTag != "-") { + itemTagName = string.IsNullOrEmpty(ItemTag) ? "li" : ItemTag; + } + + if (listTag != null) { + Output.Write(listTag.ToString(TagRenderMode.StartTag)); + } + + var itemTags = new List(); + var itemOutputs = new List(); + + // give the item shape the possibility to alter its container tag var index = 0; - foreach (var itemDisplayOutput in itemDisplayOutputs) { - var itemTag = GetTagBuilder(itemTagName, null, ItemClasses, ItemAttributes); - if (index == 0) - itemTag.AddCssClass("first"); - if (index == count - 1) - itemTag.AddCssClass("last"); - Output.Write(itemTag.ToString(TagRenderMode.StartTag)); - Output.Write(itemDisplayOutput); - Output.Write(itemTag.ToString(TagRenderMode.EndTag)); + foreach (var item in items) { + + var itemTag = String.IsNullOrEmpty(itemTagName) ? null : GetTagBuilder(itemTagName, null, ItemClasses, ItemAttributes); + + if (item is IShape) { + item.Tag = itemTag; + } + + var itemOutput = Display(item).ToHtmlString(); + + if (!String.IsNullOrWhiteSpace(itemOutput)) { + itemTags.Add(itemTag); + itemOutputs.Add(itemOutput); + } + else { + count--; + } + ++index; } - Output.Write(listTag.ToString(TagRenderMode.EndTag)); + index = 0; + foreach(var itemOutput in itemOutputs) { + var itemTag = itemTags[index]; + + if (itemTag != null) { + if (index == 0) + itemTag.AddCssClass("first"); + if (index == count - 1) + itemTag.AddCssClass("last"); + Output.Write(itemTag.ToString(TagRenderMode.StartTag)); + } + + Output.Write(itemOutput); + + if (itemTag != null) { + Output.Write(itemTag.ToString(TagRenderMode.EndTag)); + } + + ++index; + } + + if (listTag != null) { + Output.Write(listTag.ToString(TagRenderMode.EndTag)); + } } [Shape] @@ -718,5 +772,20 @@ namespace Orchard.Core.Shapes { private string EncodeAlternateElement(string alternateElement) { return alternateElement.Replace("-", "__").Replace(".", "_"); } + + /// + /// Encode a value if it's a string, or render it if it's a Shape + /// + private IHtmlString EncodeOrDisplay(dynamic Value, dynamic Display, HtmlHelper Html) { + if (Value is IHtmlString) { + return Value; + } + + if (Value is IShape) { + return Display(Value).ToString(); + } + + return Html.Raw(Html.Encode(Value.ToString())); + } } } diff --git a/src/Orchard.Web/Modules/Lucene/Lucene.csproj b/src/Orchard.Web/Modules/Lucene/Lucene.csproj index ebd498216..1b8b6bf21 100644 --- a/src/Orchard.Web/Modules/Lucene/Lucene.csproj +++ b/src/Orchard.Web/Modules/Lucene/Lucene.csproj @@ -21,6 +21,10 @@ 4.0 + + + + true @@ -66,6 +70,7 @@ + diff --git a/src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs b/src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs index 482a03152..7634d6101 100644 --- a/src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs +++ b/src/Orchard.Web/Modules/Lucene/Services/LuceneSearchBuilder.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -6,6 +7,7 @@ using Lucene.Models; using Lucene.Net.Index; using Lucene.Net.Search; using Lucene.Net.Store; +using Lucene.Net.Util; using Orchard.Indexing; using Orchard.Logging; using Lucene.Net.Documents; @@ -355,6 +357,30 @@ namespace Lucene.Services { } + public ISearchBits GetBits() { + var query = CreateQuery(); + IndexSearcher searcher; + + try { + searcher = new IndexSearcher(_directory, true); + } + catch { + // index might not exist if it has been rebuilt + Logger.Information("Attempt to read a none existing index"); + return null; + } + + try { + var filter = new QueryWrapperFilter(query); + var bits = filter.GetDocIdSet(searcher.GetIndexReader()); + var disi = new OpenBitSetDISI(bits.Iterator(), searcher.MaxDoc()); + return new SearchBits(disi); + } + finally { + searcher.Close(); + } + } + public ISearchHit Get(int documentId) { var query = new TermQuery(new Term("id", documentId.ToString(CultureInfo.InvariantCulture))); diff --git a/src/Orchard.Web/Modules/Lucene/Services/SearchBits.cs b/src/Orchard.Web/Modules/Lucene/Services/SearchBits.cs new file mode 100644 index 000000000..01adb981b --- /dev/null +++ b/src/Orchard.Web/Modules/Lucene/Services/SearchBits.cs @@ -0,0 +1,43 @@ +using System; +using Lucene.Net.Util; +using Orchard.Indexing; + +namespace Lucene.Services { + public class SearchBits : ISearchBits { + internal readonly OpenBitSet _openBitSet; + + public SearchBits(OpenBitSet openBitSet) { + _openBitSet = openBitSet; + } + + public ISearchBits And(ISearchBits other) { + return Apply(other, (x, y) => x.And(y)); + } + + public ISearchBits Or(ISearchBits other) { + return Apply(other, (x, y) => x.Or(y)); + } + + public ISearchBits Xor(ISearchBits other) { + return Apply(other, (x, y) => x.Xor(y)); + } + + public long Count() { + return _openBitSet.Cardinality(); + } + + private ISearchBits Apply(ISearchBits other, Action operation) { + var bitset = (OpenBitSet)_openBitSet.Clone(); + var otherBitSet = other as SearchBits; + + if (otherBitSet == null) { + throw new InvalidOperationException("The other bitset must be of type OpenBitSet"); + } + + operation(bitset, otherBitSet._openBitSet); + + return new SearchBits(bitset); + + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Views/BlogAdmin/Item.cshtml b/src/Orchard.Web/Modules/Orchard.Blogs/Views/BlogAdmin/Item.cshtml index f56e8dc0c..927636650 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Views/BlogAdmin/Item.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Views/BlogAdmin/Item.cshtml @@ -1,5 +1,5 @@ @{ - Html.AddTitleParts(T("Manage Blog").ToString()); + Layout.Title = T("Manage Blog").ToString(); } @* Model is a Shape, calling Display() so that it is rendered using the most specific template for its Shape type *@ @Display(Model) diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Views/Content-Blog.DetailAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.Blogs/Views/Content-Blog.DetailAdmin.cshtml index 9ad6e4b8a..dba8003a0 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Views/Content-Blog.DetailAdmin.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Views/Content-Blog.DetailAdmin.cshtml @@ -1,7 +1,8 @@ @using Orchard.Blogs.Extensions; @using Orchard.Blogs.Models; +@using Orchard.ContentManagement -@{ Layout.Title = (string)Model.Title; } +@{ Layout.Title = T("Manage {0}", Html.ItemDisplayText((IContent)Model.ContentItem)); } @Display(Model.Header) @Display(Model.Actions) diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Views/Content-Blog.Edit.cshtml b/src/Orchard.Web/Modules/Orchard.Blogs/Views/Content-Blog.Edit.cshtml index dbb1e6cc7..193859209 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Views/Content-Blog.Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Views/Content-Blog.Edit.cshtml @@ -1,6 +1,6 @@ @using Orchard.Mvc.Html; @{ - Html.AddTitleParts((string)Model.Title); + Layout.Title = T("New Blog"); }
diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/Controllers/AdminController.cs index 6e28f4416..b1dc21f31 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Controllers/AdminController.cs @@ -2,13 +2,16 @@ using System.Collections.Generic; using System.Linq; using System.Web.Mvc; +using System.Web.Routing; using Orchard.ContentManagement; using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData.Models; +using Orchard.ContentPicker.Settings; using Orchard.Core.Common.Models; using Orchard.Core.Contents.Settings; using Orchard.Core.Contents.ViewModels; using Orchard.DisplayManagement; +using Orchard.Localization; using Orchard.Mvc; using Orchard.Settings; using Orchard.Themes; @@ -18,23 +21,71 @@ namespace Orchard.ContentPicker.Controllers { public class AdminController : Controller { private readonly ISiteService _siteService; private readonly IContentDefinitionManager _contentDefinitionManager; + private readonly INavigationManager _navigationManager; public AdminController( IOrchardServices orchardServices, ISiteService siteService, - IContentDefinitionManager contentDefinitionManager) { + IContentDefinitionManager contentDefinitionManager, + INavigationManager navigationManager) { _siteService = siteService; _contentDefinitionManager = contentDefinitionManager; + _navigationManager = navigationManager; Services = orchardServices; + + T = NullLocalizer.Instance; } public IOrchardServices Services { get; set; } + public Localizer T { get; set; } [Themed(false)] - public ActionResult Index(ListContentsViewModel model, PagerParameters pagerParameters) { + public ActionResult Index(ListContentsViewModel model, PagerParameters pagerParameters, string part, string field) { + + IEnumerable menuItems = _navigationManager.BuildMenu("content-picker").ToList(); + + var contentPickerMenuItem = menuItems.FirstOrDefault(); + if (contentPickerMenuItem == null) { + return HttpNotFound(); + } + + if (contentPickerMenuItem.Items.All(x => x.Text.ToString() != T("Recent Content").Text)) { + // the default tab should not be displayed, redirect to the next one + + var routeData = new RouteValueDictionary(menuItems.First().RouteValues); + var queryString = Request.QueryString; + foreach (var key in queryString.AllKeys) { + routeData[key] = queryString[key]; + } + + return RedirectToRoute(routeData); + } + + ContentPickerFieldSettings settings = null; + + // if the picker is loaded for a specific field, apply custom settings + if (!String.IsNullOrEmpty(part) && !String.IsNullOrEmpty(field)) { + var definition = _contentDefinitionManager.GetPartDefinition(part).Fields.FirstOrDefault(x => x.Name == field); + if (definition != null) { + settings = definition.Settings.GetModel(); + } + } + + IEnumerable contentTypes; + if (settings != null && !String.IsNullOrEmpty(settings.DisplayedContentTypes)) { + var rawTypes = settings.DisplayedContentTypes.Split(new[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries).ToList(); + contentTypes = _contentDefinitionManager + .ListTypeDefinitions() + .Where(x => x.Parts.Any(p => rawTypes.Contains(p.PartDefinition.Name))) + .ToArray(); + } + else { + contentTypes = GetCreatableTypes(false).ToList(); + } + var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters); - var query = Services.ContentManager.Query(VersionOptions.Latest, GetCreatableTypes(false).Select(ctd => ctd.Name).ToArray()); + var query = Services.ContentManager.Query(VersionOptions.Latest, contentTypes.Select(ctd => ctd.Name).ToArray()); if (!string.IsNullOrEmpty(model.Options.SelectedFilter)) { var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(model.Options.SelectedFilter); @@ -60,7 +111,7 @@ namespace Orchard.ContentPicker.Controllers { break; } - model.Options.FilterOptions = GetCreatableTypes(false) + model.Options.FilterOptions = contentTypes .Select(ctd => new KeyValuePair(ctd.Name, ctd.DisplayName)) .ToList().OrderBy(kvp => kvp.Value); diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Drivers/ContentPickerFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/Drivers/ContentPickerFieldDriver.cs index 212b22300..50ebda63b 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Drivers/ContentPickerFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Drivers/ContentPickerFieldDriver.cs @@ -39,6 +39,7 @@ namespace Orchard.ContentPicker.Drivers { () => { var model = new ContentPickerFieldViewModel { Field = field, + Part = part, ContentItems = _contentManager.GetMany(field.Ids, VersionOptions.Published, QueryHints.Empty).ToList(), }; diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Scripts/ContentPicker.js b/src/Orchard.Web/Modules/Orchard.ContentPicker/Scripts/ContentPicker.js index d2b5edfaa..a87f88496 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Scripts/ContentPicker.js +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Scripts/ContentPicker.js @@ -20,11 +20,14 @@ // remove trailing slash if any if (baseUrl.substr(-1) == '/') baseUrl = baseUrl.substr(0, baseUrl.length - 1); - + var url = baseUrl + "/Admin/Orchard.ContentPicker?" + "callback=" + callbackName - + "&" + (new Date() - 0); + + "&" + (new Date() - 0) + + "&part=" + encodeURIComponent(data.part) + + "&field=" + encodeURIComponent(data.field); + var w = window.open(url, "_blank", data.windowFeatures || "width=685,height=700,status=no,toolbar=no,location=no,menubar=no,resizable=no,scrollbars=yes"); }); }); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Services/ContentPickerNavigationProvider.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/Services/ContentPickerNavigationProvider.cs index 54d89d815..096a4f16e 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Services/ContentPickerNavigationProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Services/ContentPickerNavigationProvider.cs @@ -1,9 +1,20 @@ -using Orchard.Localization; +using System; +using System.Linq; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentPicker.Settings; +using Orchard.Localization; using Orchard.UI.Navigation; namespace Orchard.ContentPicker.Services { public class ContentPickerNavigationProvider : INavigationProvider { - public ContentPickerNavigationProvider() { + private readonly IContentDefinitionManager _contentDefinitionManager; + private readonly IWorkContextAccessor _workContextAccessor; + + public ContentPickerNavigationProvider( + IContentDefinitionManager contentDefinitionManager, + IWorkContextAccessor workContextAccessor) { + _contentDefinitionManager = contentDefinitionManager; + _workContextAccessor = workContextAccessor; T = NullLocalizer.Instance; } @@ -14,9 +25,36 @@ namespace Orchard.ContentPicker.Services { } public void GetNavigation(NavigationBuilder builder) { + var workContext = _workContextAccessor.GetContext(); + var httpContext = workContext.HttpContext; + + if (httpContext == null) { + return; + } + + var queryString = workContext.HttpContext.Request.QueryString; + + string part = queryString["part"]; + string field = queryString["field"]; + + ContentPickerFieldSettings settings = null; + + // if the picker is loaded for a specific field, apply custom settings + if (!String.IsNullOrEmpty(part) && !String.IsNullOrEmpty(field)) { + var definition = _contentDefinitionManager.GetPartDefinition(part).Fields.FirstOrDefault(x => x.Name == field); + if (definition != null) { + settings = definition.Settings.GetModel(); + } + } + + if (settings != null && !settings.ShowContentTab) { + return; + } + builder.Add(T("Content Picker"), menu => menu - .Add(T("Recent Content"), "5", item => item.Action("Index", "Admin", new {area = "Orchard.ContentPicker"}).LocalNav())); + .Add(T("Recent Content"), "5", item => item.Action("Index", "Admin", new { area = "Orchard.ContentPicker" }).LocalNav())); + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Services/ContentPickerShapes.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/Services/ContentPickerShapes.cs index ef20eedff..1fb973f3e 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Services/ContentPickerShapes.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Services/ContentPickerShapes.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using System.Web; using Orchard.ContentManagement; using Orchard.DisplayManagement; diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Settings/ContentPickerFieldEditorEvents.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/Settings/ContentPickerFieldEditorEvents.cs index 16af05345..8db16ed27 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Settings/ContentPickerFieldEditorEvents.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Settings/ContentPickerFieldEditorEvents.cs @@ -26,6 +26,8 @@ namespace Orchard.ContentPicker.Settings { builder.WithSetting("ContentPickerFieldSettings.Hint", model.Hint); builder.WithSetting("ContentPickerFieldSettings.Required", model.Required.ToString(CultureInfo.InvariantCulture)); builder.WithSetting("ContentPickerFieldSettings.Multiple", model.Multiple.ToString(CultureInfo.InvariantCulture)); + builder.WithSetting("ContentPickerFieldSettings.ShowContentTab", model.ShowContentTab.ToString(CultureInfo.InvariantCulture)); + builder.WithSetting("ContentPickerFieldSettings.DisplayedContentTypes", model.DisplayedContentTypes); } yield return DefinitionTemplate(model); diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Settings/ContentPickerFieldSettings.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/Settings/ContentPickerFieldSettings.cs index 3b15a4612..b067dc759 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Settings/ContentPickerFieldSettings.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Settings/ContentPickerFieldSettings.cs @@ -1,7 +1,14 @@ namespace Orchard.ContentPicker.Settings { public class ContentPickerFieldSettings { + public ContentPickerFieldSettings() { + ShowContentTab = true; + } + public string Hint { get; set; } public bool Required { get; set; } public bool Multiple { get; set; } + + public bool ShowContentTab { get; set; } + public string DisplayedContentTypes { get; set; } } } diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/ViewModels/ContentPickerFieldViewModel.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/ViewModels/ContentPickerFieldViewModel.cs index ce0803ece..3b36322e0 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/ViewModels/ContentPickerFieldViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/ViewModels/ContentPickerFieldViewModel.cs @@ -9,5 +9,6 @@ namespace Orchard.ContentPicker.ViewModels { public ICollection ContentItems { get; set; } public string SelectedIds { get; set; } public ContentPickerField Field { get; set; } + public ContentPart Part { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Views/DefinitionTemplates/ContentPickerFieldSettings.cshtml b/src/Orchard.Web/Modules/Orchard.ContentPicker/Views/DefinitionTemplates/ContentPickerFieldSettings.cshtml index fedf07521..968f99d24 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Views/DefinitionTemplates/ContentPickerFieldSettings.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Views/DefinitionTemplates/ContentPickerFieldSettings.cshtml @@ -18,3 +18,16 @@ @T("The help text is written under the field when authors are selecting content items.") @Html.ValidationMessageFor(m => m.Hint) +
+
+ @Html.CheckBoxFor(m => m.ShowContentTab) + @T("Uncheck to hide the Content tab from the picker window.") +
+
+
+
+ + @Html.TextBoxFor(m => m.DisplayedContentTypes) + @T("A comma separated value of all the content types or content parts to display.") +
+
diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Views/EditorTemplates/Fields/ContentPicker.Edit.cshtml b/src/Orchard.Web/Modules/Orchard.ContentPicker/Views/EditorTemplates/Fields/ContentPicker.Edit.cshtml index 7cbfec51b..fe96da9c4 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Views/EditorTemplates/Fields/ContentPicker.Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Views/EditorTemplates/Fields/ContentPicker.Edit.cshtml @@ -87,7 +87,9 @@ refreshIds(); $('#save-message-@Html.FieldIdFor(m => m.Field.Ids)').show(); }, - baseUrl: '@Url.Content("~/")' + baseUrl: '@Url.Content("~/")', + part: '@HttpUtility.JavaScriptStringEncode(Model.Part.PartDefinition.Name)', + field: '@HttpUtility.JavaScriptStringEncode(Model.Field.PartFieldDefinition.Name)' }); }); diff --git a/src/Orchard.Web/Modules/Orchard.Projections/Drivers/ProjectionPartDriver.cs b/src/Orchard.Web/Modules/Orchard.Projections/Drivers/ProjectionPartDriver.cs index 24417239f..9852eb480 100644 --- a/src/Orchard.Web/Modules/Orchard.Projections/Drivers/ProjectionPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Projections/Drivers/ProjectionPartDriver.cs @@ -63,13 +63,14 @@ namespace Orchard.Projections.Drivers { var pageKey = String.IsNullOrWhiteSpace(part.Record.PagerSuffix) ? "page" : "page-" + part.Record.PagerSuffix; var page = 0; - if(queryString.AllKeys.Contains(pageKey)) { + // default page size + int pageSize = part.Record.Items; + + // don't try to page if not necessary + if (part.Record.DisplayPager && queryString.AllKeys.Contains(pageKey)) { Int32.TryParse(queryString[pageKey], out page); } - // default page size - int pageSize = part.Record.Items; - // if 0, then assume "All" if (pageSize == 0) { pageSize = Int32.MaxValue; diff --git a/src/Orchard.Web/Modules/Orchard.Projections/Providers/SortCriteria/ContentFieldsSortCriteria.cs b/src/Orchard.Web/Modules/Orchard.Projections/Providers/SortCriteria/ContentFieldsSortCriteria.cs index b59effa25..fb03aa3eb 100644 --- a/src/Orchard.Web/Modules/Orchard.Projections/Providers/SortCriteria/ContentFieldsSortCriteria.cs +++ b/src/Orchard.Web/Modules/Orchard.Projections/Providers/SortCriteria/ContentFieldsSortCriteria.cs @@ -66,7 +66,7 @@ namespace Orchard.Projections.Providers.SortCriteria { } public void ApplySortCriterion(SortCriterionContext context, IFieldTypeEditor fieldTypeEditor, string storageName, Type storageType, ContentPartDefinition part, ContentPartFieldDefinition field) { - bool ascending = Convert.ToBoolean(context.State.Sort); + bool ascending = (bool)context.State.Sort; var propertyName = String.Join(".", part.Name, field.Name, storageName ?? ""); // use an alias with the join so that two filters on the same Field Type wont collide @@ -87,7 +87,7 @@ namespace Orchard.Projections.Providers.SortCriteria { } public LocalizedString DisplaySortCriterion(SortCriterionContext context, ContentPartDefinition part, ContentPartFieldDefinition fieldDefinition) { - bool ascending = Convert.ToBoolean(context.State.Sort); + bool ascending = (bool)context.State.Sort; return ascending ? T("Ordered by field {0}, ascending", fieldDefinition.Name) diff --git a/src/Orchard.Web/Modules/Orchard.Search/ContentPickerNavigationProvider.cs b/src/Orchard.Web/Modules/Orchard.Search/ContentPickerNavigationProvider.cs index 912eaa339..4e4768548 100644 --- a/src/Orchard.Web/Modules/Orchard.Search/ContentPickerNavigationProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Search/ContentPickerNavigationProvider.cs @@ -1,11 +1,23 @@ -using Orchard.Environment.Extensions; +using System; +using System.Linq; +using Orchard.ContentManagement.MetaData; +using Orchard.Environment.Extensions; using Orchard.Localization; +using Orchard.Search.Settings; using Orchard.UI.Navigation; namespace Orchard.Search { [OrchardFeature("Orchard.Search.ContentPicker")] public class ContentPickerNavigationProvider : INavigationProvider { - public ContentPickerNavigationProvider() { + private readonly IWorkContextAccessor _workContextAccessor; + private readonly IContentDefinitionManager _contentDefinitionManager; + + public ContentPickerNavigationProvider( + IWorkContextAccessor workContextAccessor, + IContentDefinitionManager contentDefinitionManager + ) { + _workContextAccessor = workContextAccessor; + _contentDefinitionManager = contentDefinitionManager; T = NullLocalizer.Instance; } @@ -16,6 +28,33 @@ namespace Orchard.Search { } public void GetNavigation(NavigationBuilder builder) { + + var workContext = _workContextAccessor.GetContext(); + var httpContext = workContext.HttpContext; + + if (httpContext == null) { + return; + } + + var queryString = workContext.HttpContext.Request.QueryString; + + string part = queryString["part"]; + string field = queryString["field"]; + + ContentPickerSearchFieldSettings settings = null; + + // if the picker is loaded for a specific field, apply custom settings + if (!String.IsNullOrEmpty(part) && !String.IsNullOrEmpty(field)) { + var definition = _contentDefinitionManager.GetPartDefinition(part).Fields.FirstOrDefault(x => x.Name == field); + if (definition != null) { + settings = definition.Settings.GetModel(); + } + } + + if (settings != null && !settings.ShowSearchTab) { + return; + } + builder.Add(T("Content Picker"), menu => menu .Add(T("Search Content"), "5", item => item.Action("Index", "ContentPicker", new {area = "Orchard.Search"}).LocalNav())); diff --git a/src/Orchard.Web/Modules/Orchard.Search/Controllers/ContentPickerController.cs b/src/Orchard.Web/Modules/Orchard.Search/Controllers/ContentPickerController.cs index 316741f68..b8415dff3 100644 --- a/src/Orchard.Web/Modules/Orchard.Search/Controllers/ContentPickerController.cs +++ b/src/Orchard.Web/Modules/Orchard.Search/Controllers/ContentPickerController.cs @@ -1,8 +1,8 @@ using System; using System.Linq; using System.Web.Mvc; -using Orchard.Collections; using Orchard.ContentManagement; +using Orchard.ContentManagement.MetaData; using Orchard.DisplayManagement; using Orchard.Environment.Extensions; using Orchard.Indexing; @@ -10,7 +10,7 @@ using Orchard.Localization; using Orchard.Logging; using Orchard.Mvc; using Orchard.Search.Models; -using Orchard.Search.Services; +using Orchard.Search.Settings; using Orchard.Settings; using Orchard.Themes; using Orchard.UI.Admin; @@ -21,15 +21,18 @@ namespace Orchard.Search.Controllers { [Admin] [OrchardFeature("Orchard.Search.ContentPicker")] public class ContentPickerController : Controller { - private readonly ISearchService _searchService; private readonly ISiteService _siteService; + private readonly IContentDefinitionManager _contentDefinitionManager; + private readonly IIndexManager _indexManager; public ContentPickerController( IOrchardServices orchardServices, - ISearchService searchService, - ISiteService siteService) { - _searchService = searchService; + ISiteService siteService, + IContentDefinitionManager contentDefinitionManager, + IIndexManager indexManager) { _siteService = siteService; + _contentDefinitionManager = contentDefinitionManager; + _indexManager = indexManager; Services = orchardServices; T = NullLocalizer.Instance; Logger = NullLogger.Instance; @@ -40,35 +43,68 @@ namespace Orchard.Search.Controllers { public Localizer T { get; set; } [Themed(false)] - public ActionResult Index(PagerParameters pagerParameters, string searchText = "") { + public ActionResult Index(PagerParameters pagerParameters, string part, string field, string searchText = "") { Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters); var searchFields = Services.WorkContext.CurrentSite.As().SearchedFields; - IPageOfItems searchHits = new PageOfItems(new ISearchHit[] { }); - try { + int totalCount = 0; + int[] foundIds = new int[0]; - searchHits = _searchService.Query(searchText, pager.Page, pager.PageSize, - Services.WorkContext.CurrentSite.As().Record.FilterCulture, - searchFields, - searchHit => searchHit); - } - catch (Exception exception) { - Logger.Error(T("Invalid search query: {0}", exception.Message).Text); - Services.Notifier.Error(T("Invalid search query: {0}", exception.Message)); + if (!String.IsNullOrWhiteSpace(searchText)) { + ContentPickerSearchFieldSettings settings = null; + // if the picker is loaded for a specific field, apply custom settings + if (!String.IsNullOrEmpty(part) && !String.IsNullOrEmpty(field)) { + var definition = _contentDefinitionManager.GetPartDefinition(part).Fields.FirstOrDefault(x => x.Name == field); + if (definition != null) { + settings = definition.Settings.GetModel(); + } + } + + if (!_indexManager.HasIndexProvider()) { + return HttpNotFound(); + } + + var builder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder("Search"); + try { + builder.Parse(searchFields, searchText); + + if (settings != null && !String.IsNullOrEmpty(settings.DisplayedContentTypes)) { + var rawTypes = settings.DisplayedContentTypes.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); + var contentTypes = _contentDefinitionManager + .ListTypeDefinitions() + .Where(x => x.Parts.Any(p => rawTypes.Contains(p.PartDefinition.Name))) + .ToArray(); + + + foreach (string type in contentTypes.Select(x => x.Name)) { + builder.WithField("type", type).AsFilter(); + } + } + + totalCount = builder.Count(); + builder = builder.Slice((pager.Page > 0 ? pager.Page - 1 : 0) * pager.PageSize, pager.PageSize); + var searchResults = builder.Search(); + + foundIds = searchResults.Select(searchHit => searchHit.ContentItemId).ToArray(); + } + catch (Exception exception) { + Logger.Error(T("Invalid search query: {0}", exception.Message).Text); + Services.Notifier.Error(T("Invalid search query: {0}", exception.Message)); + } } var list = Services.New.List(); - foreach (var contentItem in Services.ContentManager.GetMany(searchHits.Select(x => x.ContentItemId), VersionOptions.Published, QueryHints.Empty)) { + foreach (var contentItem in Services.ContentManager.GetMany(foundIds, VersionOptions.Published, QueryHints.Empty)) { // ignore search results which content item has been removed or unpublished if (contentItem == null) { - searchHits.TotalItemCount--; + totalCount--; continue; } list.Add(Services.ContentManager.BuildDisplay(contentItem, "SummaryAdmin")); } - var pagerShape = Services.New.Pager(pager).TotalItemCount(searchHits.TotalItemCount); + var pagerShape = Services.New.Pager(pager).TotalItemCount(totalCount); foreach(IShape item in list.Items) { diff --git a/src/Orchard.Web/Modules/Orchard.Search/Orchard.Search.csproj b/src/Orchard.Web/Modules/Orchard.Search/Orchard.Search.csproj index 30e472a56..4bb7f1d58 100644 --- a/src/Orchard.Web/Modules/Orchard.Search/Orchard.Search.csproj +++ b/src/Orchard.Web/Modules/Orchard.Search/Orchard.Search.csproj @@ -21,6 +21,10 @@ 4.0 + + + + true @@ -68,6 +72,8 @@ + + @@ -109,6 +115,9 @@ + + + 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) diff --git a/src/Orchard.Web/Modules/Orchard.Search/Settings/ContentPickerFieldEditorEvents.cs b/src/Orchard.Web/Modules/Orchard.Search/Settings/ContentPickerFieldEditorEvents.cs new file mode 100644 index 000000000..a4409b69d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Search/Settings/ContentPickerFieldEditorEvents.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.Globalization; +using Orchard.ContentManagement; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Builders; +using Orchard.ContentManagement.MetaData.Models; +using Orchard.ContentManagement.ViewModels; +using Orchard.Environment.Extensions; + +namespace Orchard.Search.Settings { + [OrchardFeature("Orchard.Search.ContentPicker")] + public class ContentPickerFieldEditorEvents : ContentDefinitionEditorEventsBase { + + public override IEnumerable PartFieldEditor(ContentPartFieldDefinition definition) { + if (definition.FieldDefinition.Name == "ContentPickerField") { + var model = definition.Settings.GetModel(); + yield return DefinitionTemplate(model); + } + } + + public override IEnumerable PartFieldEditorUpdate(ContentPartFieldDefinitionBuilder builder, IUpdateModel updateModel) { + if (builder.FieldType != "ContentPickerField") { + yield break; + } + + var model = new ContentPickerSearchFieldSettings(); + if (updateModel.TryUpdateModel(model, "ContentPickerSearchFieldSettings", null, null)) { + builder.WithSetting("ContentPickerSearchFieldSettings.ShowSearchTab", model.ShowSearchTab.ToString(CultureInfo.InvariantCulture)); + builder.WithSetting("ContentPickerSearchFieldSettings.DisplayedContentTypes", model.DisplayedContentTypes); + } + + yield return DefinitionTemplate(model); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Search/Settings/ContentPickerFieldSettings.cs b/src/Orchard.Web/Modules/Orchard.Search/Settings/ContentPickerFieldSettings.cs new file mode 100644 index 000000000..5a8c8a41a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Search/Settings/ContentPickerFieldSettings.cs @@ -0,0 +1,10 @@ +namespace Orchard.Search.Settings { + public class ContentPickerSearchFieldSettings { + public ContentPickerSearchFieldSettings() { + ShowSearchTab = true; + } + + public bool ShowSearchTab { get; set; } + public string DisplayedContentTypes { get; set; } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.Search/Views/DefinitionTemplates/ContentPickerSearchFieldSettings.cshtml b/src/Orchard.Web/Modules/Orchard.Search/Views/DefinitionTemplates/ContentPickerSearchFieldSettings.cshtml new file mode 100644 index 000000000..ea1690eb6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Search/Views/DefinitionTemplates/ContentPickerSearchFieldSettings.cshtml @@ -0,0 +1,15 @@ +@model Orchard.Search.Settings.ContentPickerSearchFieldSettings + +
+
+ @Html.CheckBoxFor(m => m.ShowSearchTab) + @T("Uncheck to hide the Search tab from the picker window.") +
+
+
+
+ + @Html.TextBoxFor(m => m.DisplayedContentTypes) + @T("A comma separated value of all the content types or content parts to display.") +
+
diff --git a/src/Orchard.Web/Modules/Orchard.Widgets/Migrations.cs b/src/Orchard.Web/Modules/Orchard.Widgets/Migrations.cs index cc16abf4a..ad8976c34 100644 --- a/src/Orchard.Web/Modules/Orchard.Widgets/Migrations.cs +++ b/src/Orchard.Web/Modules/Orchard.Widgets/Migrations.cs @@ -1,32 +1,8 @@ -using Orchard.ContentManagement; -using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData; using Orchard.Core.Contents.Extensions; using Orchard.Data.Migration; -using Orchard.Widgets.Models; namespace Orchard.Widgets { - public interface IDefaultLayersInitializer : IDependency { - void CreateDefaultLayers(); - } - - public class DefaultLayersInitializer : IDefaultLayersInitializer { - private readonly IContentManager _contentManager; - - public DefaultLayersInitializer(IContentManager contentManager) { - _contentManager = contentManager; - } - - public void CreateDefaultLayers() { - IContent defaultLayer = _contentManager.Create("Layer", t => { t.Record.Name = "Default"; t.Record.LayerRule = "true"; }); - _contentManager.Publish(defaultLayer.ContentItem); - IContent authenticatedLayer = _contentManager.Create("Layer", t => { t.Record.Name = "Authenticated"; t.Record.LayerRule = "authenticated"; }); - _contentManager.Publish(authenticatedLayer.ContentItem); - IContent anonymousLayer = _contentManager.Create("Layer", t => { t.Record.Name = "Anonymous"; t.Record.LayerRule = "not authenticated"; }); - _contentManager.Publish(anonymousLayer.ContentItem); - IContent disabledLayer = _contentManager.Create("Layer", t => { t.Record.Name = "Disabled"; t.Record.LayerRule = "false"; }); - _contentManager.Publish(disabledLayer.ContentItem); - } - } public class WidgetsDataMigration : DataMigrationImpl { public int Create() { diff --git a/src/Orchard.Web/Themes/TheThemeMachine/Views/Content-Actualite.Detail.cshtml b/src/Orchard.Web/Themes/TheThemeMachine/Views/Content-Actualite.Detail.cshtml deleted file mode 100644 index 35770b585..000000000 --- a/src/Orchard.Web/Themes/TheThemeMachine/Views/Content-Actualite.Detail.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -Ceci est une actualite parlant de : - -@Model.ContentItem.Actualite.Sommaire.Value \ No newline at end of file diff --git a/src/Orchard.Web/Themes/TheThemeMachine/Views/Pager.cshtml b/src/Orchard.Web/Themes/TheThemeMachine/Views/Pager.cshtml index dc7baca19..8c40ed044 100644 --- a/src/Orchard.Web/Themes/TheThemeMachine/Views/Pager.cshtml +++ b/src/Orchard.Web/Themes/TheThemeMachine/Views/Pager.cshtml @@ -1,5 +1,7 @@ @{ + // number of page number links to show, 0 means no link, 1 means only the current page, or more accepted. Model.Quantity = 0; + Model.PreviousText = T("Newer"); Model.NextText = T("Older"); Model.Classes.Add("group"); diff --git a/src/Orchard/DisplayManagement/IShapeFactory.cs b/src/Orchard/DisplayManagement/IShapeFactory.cs index e92b43ce3..44e550700 100644 --- a/src/Orchard/DisplayManagement/IShapeFactory.cs +++ b/src/Orchard/DisplayManagement/IShapeFactory.cs @@ -6,14 +6,9 @@ namespace Orchard.DisplayManagement { /// This may be used directly, or through the IShapeHelperFactory. /// public interface IShapeFactory : IDependency { + IShape Create(string shapeType); IShape Create(string shapeType, INamedEnumerable parameters); IShape Create(string shapeType, INamedEnumerable parameters, Func createShape); } - - public static class ShapeFactoryExtensions { - public static IShape Create(this IShapeFactory factory, string shapeType) { - return factory.Create(shapeType, Arguments.Empty()); - } - } } diff --git a/src/Orchard/DisplayManagement/Implementation/DefaultShapeFactory.cs b/src/Orchard/DisplayManagement/Implementation/DefaultShapeFactory.cs index 2d2b18cc7..2f0cec598 100644 --- a/src/Orchard/DisplayManagement/Implementation/DefaultShapeFactory.cs +++ b/src/Orchard/DisplayManagement/Implementation/DefaultShapeFactory.cs @@ -23,6 +23,10 @@ namespace Orchard.DisplayManagement.Implementation { return true; } + public IShape Create(string shapeType) { + return Create(shapeType, Arguments.Empty(), () => new Shape()); + } + public IShape Create(string shapeType, INamedEnumerable parameters) { return Create(shapeType, parameters, () => new Shape()); } diff --git a/src/Orchard/Indexing/ISearchBits.cs b/src/Orchard/Indexing/ISearchBits.cs new file mode 100644 index 000000000..b22765f78 --- /dev/null +++ b/src/Orchard/Indexing/ISearchBits.cs @@ -0,0 +1,8 @@ +namespace Orchard.Indexing { + public interface ISearchBits { + ISearchBits And(ISearchBits other); + ISearchBits Or(ISearchBits other); + ISearchBits Xor(ISearchBits other); + long Count(); + } +} diff --git a/src/Orchard/Indexing/ISearchBuilder.cs b/src/Orchard/Indexing/ISearchBuilder.cs index e2f73280a..de372a7eb 100644 --- a/src/Orchard/Indexing/ISearchBuilder.cs +++ b/src/Orchard/Indexing/ISearchBuilder.cs @@ -57,6 +57,7 @@ namespace Orchard.Indexing { ISearchBuilder Slice(int skip, int count); IEnumerable Search(); ISearchHit Get(int documentId); + ISearchBits GetBits(); int Count(); } diff --git a/src/Orchard/Indexing/NullSearchBuilder.cs b/src/Orchard/Indexing/NullSearchBuilder.cs index 521de9856..003510ad7 100644 --- a/src/Orchard/Indexing/NullSearchBuilder.cs +++ b/src/Orchard/Indexing/NullSearchBuilder.cs @@ -127,6 +127,11 @@ namespace Orchard.Indexing { public ISearchHit Get(int documentId) { return null; } + + public ISearchBits GetBits() { + throw new NotImplementedException(); + } + public int Count() { return 0; } diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index c9a10dc31..6e59cbfec 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -238,6 +238,7 @@ + diff --git a/src/Orchard/UI/Zones/ZoneHoldingBehavior.cs b/src/Orchard/UI/Zones/ZoneHoldingBehavior.cs index d1a6f9a50..14c7b6aca 100644 --- a/src/Orchard/UI/Zones/ZoneHoldingBehavior.cs +++ b/src/Orchard/UI/Zones/ZoneHoldingBehavior.cs @@ -139,7 +139,16 @@ namespace Orchard.UI.Zones { } public override bool TryConvert(System.Dynamic.ConvertBinder binder, out object result) { - result = Nil.Instance; + if (binder.ReturnType == typeof (string)) { + result = null; + } + else if (binder.ReturnType.IsValueType) { + result = Activator.CreateInstance(binder.ReturnType); + } + else { + result = null; + } + return true; }