From a49227d4bd5cd7866797004829a75572f6f73ae1 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 30 Jan 2013 17:43:45 -0800 Subject: [PATCH] Removing external modules --HG-- branch : 1.x extra : rebase_source : af3ea126c618c5ef86a2fa5e741d49f0d9fbe597 --- .../Modules/Contrib.Cache/AdminMenu.cs | 19 - .../Contrib.Cache/Contrib.Cache.csproj | 162 ----- .../Controllers/AdminController.cs | 128 ---- .../Controllers/StatisticsController.cs | 74 -- .../Filters/OutputCacheFilter.cs | 649 ------------------ .../Handlers/CacheSettingsPartHandler.cs | 40 -- .../Handlers/DisplayedContentItemHandler.cs | 26 - .../Modules/Contrib.Cache/Migrations.cs | 74 -- .../Modules/Contrib.Cache/Models/CacheItem.cs | 18 - .../Models/CacheParameterRecord.cs | 11 - .../Contrib.Cache/Models/CacheSettingsPart.cs | 32 - .../Models/CacheSettingsPartRecord.cs | 14 - .../Modules/Contrib.Cache/Module.txt | 11 - .../Contrib.Cache/Properties/AssemblyInfo.cs | 34 - .../Modules/Contrib.Cache/Scripts/Web.config | 21 - .../Contrib.Cache/Services/CacheService.cs | 121 ---- .../Services/DefaultCacheStorageProvider.cs | 66 -- .../Contrib.Cache/Services/DefaultTagCache.cs | 24 - .../Contrib.Cache/Services/ICacheService.cs | 39 -- .../Services/IDisplayedContentItemHandler.cs | 9 - .../Services/IOutputCacheStorageProvider.cs | 22 - .../Contrib.Cache/Services/ITagCache.cs | 9 - .../Modules/Contrib.Cache/Styles/Web.config | 21 - .../ViewModels/IndexViewModel.cs | 15 - .../ViewModels/RouteConfiguration.cs | 10 - .../ViewModels/StatisticsViewModel.cs | 9 - .../Contrib.Cache/Views/Admin/Index.cshtml | 72 -- .../Views/Statistics/Index.cshtml | 35 - .../Modules/Contrib.Cache/Views/Web.config | 41 -- .../Modules/Contrib.Cache/Web.config | 41 -- .../Modules/Contrib.Taxonomies/AdminMenu.cs | 16 - .../Contrib.Taxonomies.csproj | 242 ------- .../Controllers/AdminController.cs | 210 ------ .../Controllers/HomeController.cs | 106 --- .../Controllers/TermAdminController.cs | 228 ------ .../Drivers/TaxonomyFieldDriver.cs | 121 ---- .../Drivers/TaxonomyMenuItemPartDriver.cs | 53 -- .../Drivers/TaxonomyMenuPartDriver.cs | 195 ------ .../Drivers/TaxonomyPartDriver.cs | 37 - .../Drivers/TermPartDriver.cs | 95 --- .../Drivers/TermWidgetPartDriver.cs | 168 ----- .../Drivers/TermsPartDriver.cs | 7 - .../Fields/TaxonomyField.cs | 22 - .../Handlers/TaxonomyMenuItemPartHandler.cs | 14 - .../Handlers/TaxonomyMenuPartHandler.cs | 11 - .../Handlers/TaxonomyPartHandler.cs | 32 - .../Handlers/TermPartHandler.cs | 40 -- .../Handlers/TermWidgetPartHandler.cs | 11 - .../Handlers/TermsPartHandler.cs | 76 -- .../Helpers/PathExtensions.cs | 29 - .../Helpers/PredicateBuilder.cs | 34 - .../Modules/Contrib.Taxonomies/Migrations.cs | 99 --- .../Models/TaxonomyMenuItemPart.cs | 24 - .../Models/TaxonomyMenuItemPartRecord.cs | 9 - .../Models/TaxonomyMenuPart.cs | 64 -- .../Models/TaxonomyMenuPartRecord.cs | 15 - .../Contrib.Taxonomies/Models/TaxonomyPart.cs | 22 - .../Models/TaxonomyPartRecord.cs | 7 - .../Models/TermContentItem.cs | 16 - .../Contrib.Taxonomies/Models/TermPart.cs | 72 -- .../Models/TermPartRecord.cs | 15 - .../Models/TermWidgetPart.cs | 41 -- .../Models/TermWidgetPartRecord.cs | 18 - .../Contrib.Taxonomies/Models/TermsPart.cs | 13 - .../Models/TermsPartRecord.cs | 14 - .../Modules/Contrib.Taxonomies/Module.txt | 18 - .../Modules/Contrib.Taxonomies/Permissions.cs | 48 -- .../Modules/Contrib.Taxonomies/Placement.info | 29 - .../Projections/TermsFilter.cs | 72 -- .../Projections/TermsFilterForms.cs | 57 -- .../Properties/AssemblyInfo.cs | 33 - .../Modules/Contrib.Taxonomies/Routes.cs | 63 -- .../Routing/ITaxonomySlugConstraint.cs | 12 - .../Routing/ITermPathConstraint.cs | 12 - .../Routing/TaxonomySlugConstraint.cs | 70 -- .../Routing/TaxonomySlugConstraintUpdator.cs | 30 - .../Routing/TermPathConstraint.cs | 70 -- .../Routing/TermPathConstraintUpdator.cs | 30 - .../Contrib.Taxonomies/Scripts/Web.config | 21 - .../Scripts/admin-taxonomy-expando.js | 3 - .../Services/ITaxonomyService.cs | 42 -- .../Services/TaxonomyNavigationProvider.cs | 39 -- .../Services/TaxonomyService.cs | 329 --------- .../Settings/TaxonomyFieldEditorEvents.cs | 48 -- .../Settings/TaxonomyFieldSettings.cs | 36 - .../Modules/Contrib.Taxonomies/Shapes.cs | 129 ---- .../StandardQueries/TermFeedQuery.cs | 84 --- .../Contrib.Taxonomies/Styles/Web.config | 18 - .../Styles/admin-taxonomy.css | 21 - .../ViewModels/ImportViewModel.cs | 8 - .../ViewModels/MoveTermViewModel.cs | 10 - .../ViewModels/SelectTermViewModel.cs | 9 - .../ViewModels/TaxonomyAdminIndexViewModel.cs | 19 - .../ViewModels/TaxonomyFieldViewModel.cs | 11 - .../ViewModels/TaxonomyMenuViewModel.cs | 18 - .../ViewModels/TermAdminIndexViewModel.cs | 28 - .../ViewModels/TermWidgetViewModel.cs | 26 - .../Views/Admin/Create.cshtml | 8 - .../Views/Admin/Edit.cshtml | 8 - .../Views/Admin/Import.cshtml | 71 -- .../Views/Admin/Index.cshtml | 56 -- .../TaxonomyFieldSettings.cshtml | 27 - .../Fields/Contrib.TaxonomyField.cshtml | 38 - .../Parts/Taxonomies.Menu.cshtml | 64 -- .../Parts/Taxonomies.TaxonomyMenuItem.cshtml | 13 - .../Parts/Taxonomies.Term.Fields.cshtml | 13 - .../Parts/Taxonomies.TermWidget.cshtml | 76 -- .../Views/Fields/Contrib.TaxonomyField.cshtml | 14 - .../Contrib.Taxonomies/Views/Home/List.cshtml | 1 - .../Views/Items/Content-Term.Edit.cshtml | 7 - .../Views/Items/Taxonomies.Term.cshtml | 5 - .../Views/Items/Taxonomy.List.cshtml | 15 - .../Views/Parts/Taxonomies.Menu.cshtml | 38 - .../Views/Parts/TermWidget.List.cshtml | 15 - .../Taxonomies.TermContentItems.List.cshtml | 9 - .../Views/TermAdmin/Create.cshtml | 8 - .../Views/TermAdmin/Edit.cshtml | 8 - .../Views/TermAdmin/Index.cshtml | 54 -- .../Views/TermAdmin/MoveTerm.cshtml | 21 - .../Views/TermAdmin/RenderTermSelect.cshtml | 6 - .../Views/TermAdmin/SelectTerm.cshtml | 20 - .../Contrib.Taxonomies/Views/Web.config | 42 -- .../Modules/Contrib.Taxonomies/web.config | 40 -- src/Orchard.Web/Modules/Orchard.Workflows.zip | Bin 82712 -> 0 bytes src/Orchard.sln | 46 -- 125 files changed, 6189 deletions(-) delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/AdminMenu.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Contrib.Cache.csproj delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Controllers/AdminController.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Controllers/StatisticsController.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Filters/OutputCacheFilter.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Handlers/CacheSettingsPartHandler.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Handlers/DisplayedContentItemHandler.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Migrations.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Models/CacheItem.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Models/CacheParameterRecord.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Models/CacheSettingsPart.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Models/CacheSettingsPartRecord.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Module.txt delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Properties/AssemblyInfo.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Scripts/Web.config delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Services/CacheService.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Services/DefaultCacheStorageProvider.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Services/DefaultTagCache.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Services/ICacheService.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Services/IDisplayedContentItemHandler.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Services/IOutputCacheStorageProvider.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Services/ITagCache.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Styles/Web.config delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/ViewModels/IndexViewModel.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/ViewModels/RouteConfiguration.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/ViewModels/StatisticsViewModel.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Views/Admin/Index.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Views/Statistics/Index.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Views/Web.config delete mode 100644 src/Orchard.Web/Modules/Contrib.Cache/Web.config delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/AdminMenu.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Contrib.Taxonomies.csproj delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Controllers/AdminController.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Controllers/HomeController.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Controllers/TermAdminController.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyFieldDriver.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyMenuItemPartDriver.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyMenuPartDriver.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyPartDriver.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TermPartDriver.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TermWidgetPartDriver.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TermsPartDriver.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Fields/TaxonomyField.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TaxonomyMenuItemPartHandler.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TaxonomyMenuPartHandler.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TaxonomyPartHandler.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TermPartHandler.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TermWidgetPartHandler.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TermsPartHandler.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Helpers/PathExtensions.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Helpers/PredicateBuilder.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Migrations.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuItemPart.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuItemPartRecord.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuPart.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuPartRecord.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyPart.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyPartRecord.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermContentItem.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermPart.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermPartRecord.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermWidgetPart.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermWidgetPartRecord.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermsPart.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermsPartRecord.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Module.txt delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Permissions.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Placement.info delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Projections/TermsFilter.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Projections/TermsFilterForms.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Properties/AssemblyInfo.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Routes.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/ITaxonomySlugConstraint.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/ITermPathConstraint.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TaxonomySlugConstraint.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TaxonomySlugConstraintUpdator.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TermPathConstraint.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TermPathConstraintUpdator.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Scripts/Web.config delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Scripts/admin-taxonomy-expando.js delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Services/ITaxonomyService.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Services/TaxonomyNavigationProvider.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Services/TaxonomyService.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Settings/TaxonomyFieldEditorEvents.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Settings/TaxonomyFieldSettings.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Shapes.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/StandardQueries/TermFeedQuery.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Styles/Web.config delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Styles/admin-taxonomy.css delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/ImportViewModel.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/MoveTermViewModel.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/SelectTermViewModel.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TaxonomyAdminIndexViewModel.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TaxonomyFieldViewModel.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TaxonomyMenuViewModel.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TermAdminIndexViewModel.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TermWidgetViewModel.cs delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Create.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Edit.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Import.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Index.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/DefinitionTemplates/TaxonomyFieldSettings.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Fields/Contrib.TaxonomyField.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.Menu.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.TaxonomyMenuItem.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.Term.Fields.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.TermWidget.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Fields/Contrib.TaxonomyField.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Home/List.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Items/Content-Term.Edit.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Items/Taxonomies.Term.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Items/Taxonomy.List.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Parts/Taxonomies.Menu.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Parts/TermWidget.List.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Taxonomies.TermContentItems.List.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/Create.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/Edit.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/Index.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/MoveTerm.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/RenderTermSelect.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/SelectTerm.cshtml delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Web.config delete mode 100644 src/Orchard.Web/Modules/Contrib.Taxonomies/web.config delete mode 100644 src/Orchard.Web/Modules/Orchard.Workflows.zip diff --git a/src/Orchard.Web/Modules/Contrib.Cache/AdminMenu.cs b/src/Orchard.Web/Modules/Contrib.Cache/AdminMenu.cs deleted file mode 100644 index c79b148b4..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/AdminMenu.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Orchard.Localization; -using Orchard.Security; -using Orchard.UI.Navigation; - -namespace Contrib.Cache { - public class AdminMenu : INavigationProvider { - public Localizer T { get; set; } - public string MenuName { get { return "admin"; } } - - public void GetNavigation(NavigationBuilder builder) { - builder - .Add(T("Settings"), menu => menu - .Add(T("Cache"), "10.0", subMenu => subMenu.Action("Index", "Admin", new { area = "Contrib.Cache" }).Permission(StandardPermissions.SiteOwner) - .Add(T("Settings"), "10.0", item => item.Action("Index", "Admin", new { area = "Contrib.Cache" }).Permission(StandardPermissions.SiteOwner).LocalNav()) - .Add(T("Statistics"), "10.0", item => item.Action("Index", "Statistics", new { area = "Contrib.Cache" }).Permission(StandardPermissions.SiteOwner).LocalNav()) - )); - } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Contrib.Cache.csproj b/src/Orchard.Web/Modules/Contrib.Cache/Contrib.Cache.csproj deleted file mode 100644 index 1c7d98627..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Contrib.Cache.csproj +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {6E444FF1-A47C-4CF6-BB3F-507C8EBD776D} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Contrib.Cache - Contrib.Cache - v4.0 - false - - - 4.0 - - - - false - - - - - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - bin\ - TRACE - prompt - 4 - AllRules.ruleset - - - - False - ..\..\..\..\lib\autofac\Autofac.dll - - - - - - 3.5 - - - - False - ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll - - - - - - - - - - - - - - - - - - - {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} - Orchard.Framework - - - {9916839C-39FC-4CEB-A5AF-89CA7E87119F} - Orchard.Core - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - - - - $(ProjectDir)\..\Manifests - - - - - - - - - - - - False - True - 45979 - / - - - False - True - http://orchard.codeplex.com - False - - - - - \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Contrib.Cache/Controllers/AdminController.cs deleted file mode 100644 index c61a95a5f..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Controllers/AdminController.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Web.Mvc; -using System.Web.Routing; -using Autofac.Features.Metadata; -using Contrib.Cache.Models; -using Contrib.Cache.Services; -using Contrib.Cache.ViewModels; -using Orchard; -using Orchard.Caching; -using Orchard.ContentManagement; -using Orchard.Localization; -using Orchard.Mvc.Routes; -using Orchard.Security; -using Orchard.UI.Admin; -using Orchard.UI.Notify; - -namespace Contrib.Cache.Controllers { - [Admin] - public class AdminController : Controller { - private readonly IEnumerable> _routeProviders; - private readonly ISignals _signals; - private readonly ICacheService _cacheService; - - public AdminController( - IOrchardServices services, - IEnumerable> routeProviders, - ISignals signals, - ICacheService cacheService) { - _routeProviders = routeProviders; - _signals = signals; - _cacheService = cacheService; - Services = services; - } - - public IOrchardServices Services { get; set; } - public Localizer T { get; set; } - - public ActionResult Index() { - if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not allowed to manage cache"))) - return new HttpUnauthorizedResult(); - - var routeConfigurations = new List(); - var settings = Services.WorkContext.CurrentSite.As(); - - - foreach (var routeProvider in _routeProviders) { - // right now, ignore generic routes - if (routeProvider.Value is StandardExtensionRouteProvider) continue; - - var routeCollection = routeProvider.Value.GetRoutes(); - var feature = routeProvider.Metadata["Feature"] as Orchard.Environment.Extensions.Models.Feature; - - // if there is no feature, skip route - if (feature == null) continue; - - foreach (var routeDescriptor in routeCollection) { - var route = routeDescriptor.Route as Route; - - if(route == null) { - continue; - } - - // ignore admin routes - if (route.Url.StartsWith("Admin/") || route.Url == "Admin") continue; - - var cacheParameterKey = _cacheService.GetRouteDescriptorKey(HttpContext, route); - var cacheParameter = _cacheService.GetCacheParameterByKey(cacheParameterKey); - var duration = cacheParameter == null ? default(int?) : cacheParameter.Duration; - - routeConfigurations.Add(new RouteConfiguration { - RouteKey = cacheParameterKey, - Url = route.Url, - Priority = routeDescriptor.Priority, - Duration = duration, - FeatureName = - String.IsNullOrWhiteSpace(feature.Descriptor.Name) - ? feature.Descriptor.Id - : feature.Descriptor.Name - }); - } - } - - var model = new IndexViewModel { - DefaultCacheDuration = settings.DefaultCacheDuration, - DefaultMaxAge = settings.DefaultMaxAge, - IgnoredUrls = settings.IgnoredUrls, - DebugMode = settings.DebugMode, - ApplyCulture = settings.ApplyCulture, - RouteConfigurations = routeConfigurations - }; - - return View(model); - } - - [HttpPost, ActionName("Index")] - public ActionResult IndexPost() { - if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not allowed to manage cache"))) - return new HttpUnauthorizedResult(); - - var model = new IndexViewModel { - RouteConfigurations = new List() - }; - - if(TryUpdateModel(model)) { - var settings = Services.WorkContext.CurrentSite.As(); - settings.DefaultCacheDuration = model.DefaultCacheDuration; - settings.DefaultMaxAge = model.DefaultMaxAge; - settings.IgnoredUrls = model.IgnoredUrls; - settings.DebugMode = model.DebugMode; - settings.ApplyCulture = model.ApplyCulture; - - // invalidates the settings cache - _signals.Trigger(CacheSettingsPart.CacheKey); - - _cacheService.SaveCacheConfigurations(model.RouteConfigurations); - - Services.Notifier.Information(T("Cache Settings saved successfully.")); - } - else { - Services.Notifier.Error(T("Could not save Cache Settings.")); - } - - return RedirectToAction("Index"); - } - - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Controllers/StatisticsController.cs b/src/Orchard.Web/Modules/Contrib.Cache/Controllers/StatisticsController.cs deleted file mode 100644 index d244050f7..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Controllers/StatisticsController.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Linq; -using System.Web.Mvc; -using Contrib.Cache.Services; -using Contrib.Cache.ViewModels; -using Orchard; -using Orchard.Environment.Configuration; -using Orchard.Localization; -using Orchard.Security; -using Orchard.Settings; -using Orchard.UI.Admin; -using Orchard.UI.Navigation; - -namespace Contrib.Cache.Controllers { - [Admin] - public class StatisticsController : Controller { - private readonly ICacheService _cacheService; - private readonly IOutputCacheStorageProvider _cacheStorageProvider; - private readonly ShellSettings _shellSettings; - private readonly ISiteService _siteService; - - public StatisticsController( - IOrchardServices services, - ICacheService cacheService, - IOutputCacheStorageProvider cacheStorageProvider, - ShellSettings shellSettings, - ISiteService siteService) { - _cacheService = cacheService; - _cacheStorageProvider = cacheStorageProvider; - _shellSettings = shellSettings; - _siteService = siteService; - Services = services; - } - - public IOrchardServices Services { get; set; } - public Localizer T { get; set; } - - public ActionResult Index(PagerParameters pagerParameters) { - if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not allowed to manage cache"))) - return new HttpUnauthorizedResult(); - - var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters); - var pagerShape = Services.New.Pager(pager).TotalItemCount(_cacheStorageProvider.GetCacheItemsCount()); - - var model = new StatisticsViewModel { - CacheItems = _cacheStorageProvider - .GetCacheItems(pager.GetStartIndex(), pager.PageSize) - .ToList(), - Pager = pagerShape - }; - - return View(model); - } - - public ActionResult Evict(string cacheKey) { - if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not allowed to manage cache"))) - return new HttpUnauthorizedResult(); - - _cacheStorageProvider.Remove(cacheKey); - - return RedirectToAction("Index"); - } - - [HttpPost] - public ActionResult EvictAll() { - if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not allowed to manage cache"))) - return new HttpUnauthorizedResult(); - - _cacheStorageProvider.RemoveAll(); - - return RedirectToAction("Index"); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Filters/OutputCacheFilter.cs b/src/Orchard.Web/Modules/Contrib.Cache/Filters/OutputCacheFilter.cs deleted file mode 100644 index daeefd1bd..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Filters/OutputCacheFilter.cs +++ /dev/null @@ -1,649 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Text; -using System.Web; -using System.Web.Mvc; -using System.Web.Routing; -using Contrib.Cache.Models; -using Contrib.Cache.Services; -using Orchard; -using Orchard.Caching; -using Orchard.ContentManagement; -using Orchard.Environment.Configuration; -using Orchard.Logging; -using Orchard.Mvc.Filters; -using Orchard.Services; -using Orchard.Themes; -using Orchard.UI.Admin; -using Orchard.Utility.Extensions; - -namespace Contrib.Cache.Filters -{ - public class OutputCacheFilter : FilterProvider, IActionFilter, IResultFilter - { - - private readonly ICacheManager _cacheManager; - private readonly IOutputCacheStorageProvider _cacheStorageProvider; - private readonly ITagCache _tagCache; - private readonly IDisplayedContentItemHandler _displayedContentItemHandler; - private readonly IWorkContextAccessor _workContextAccessor; - private readonly IThemeManager _themeManager; - private readonly IClock _clock; - private readonly ICacheService _cacheService; - private readonly ISignals _signals; - private readonly ShellSettings _shellSettings; - - private const string AntiforgeryBeacon = ""; - private const string AntiforgeryTag = "().FirstOrDefault() ; - - if(outputCacheAttribute != null) { - if (outputCacheAttribute.Duration <= 0 || outputCacheAttribute.NoStore) { - Logger.Debug("Request ignored based on OutputCache attribute"); - return; - } - } - - // saving the current datetime - _now = _clock.UtcNow; - - // before executing an action, we check if a valid cached result is already - // existing for this context (url, theme, culture, tenant) - - Logger.Debug("Request on: " + filterContext.RequestContext.HttpContext.Request.RawUrl); - - // don't cache POST requests - if(filterContext.HttpContext.Request.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) ) { - Logger.Debug("Request ignored on POST"); - return; - } - - // don't cache the admin - if (AdminFilter.IsApplied(new RequestContext(filterContext.HttpContext, new RouteData()))) { - Logger.Debug("Request ignored on Admin section"); - return; - } - - // ignore child actions, e.g. HomeController is using RenderAction() - if (filterContext.IsChildAction){ - Logger.Debug("Request ignored on Child actions"); - return; - } - - _workContext = _workContextAccessor.GetContext(); - - // don't return any cached content, or cache any content, if the user is authenticated - if (_workContext.CurrentUser != null) { - Logger.Debug("Request ignored on Authenticated user"); - return; - } - - // caches the default cache duration to prevent a query to the settings - _cacheDuration = _cacheManager.Get("CacheSettingsPart.Duration", - context => { - context.Monitor(_signals.When(CacheSettingsPart.CacheKey)); - return _workContext.CurrentSite.As().DefaultCacheDuration; - } - ); - - // caches the default max age duration to prevent a query to the settings - _maxAge = _cacheManager.Get("CacheSettingsPart.MaxAge", - context => { - context.Monitor(_signals.When(CacheSettingsPart.CacheKey)); - return _workContext.CurrentSite.As().DefaultMaxAge; - } - ); - - // caches the ignored urls to prevent a query to the settings - _ignoredUrls = _cacheManager.Get("CacheSettingsPart.IgnoredUrls", - context => { - context.Monitor(_signals.When(CacheSettingsPart.CacheKey)); - return _workContext.CurrentSite.As().IgnoredUrls; - } - ); - - // caches the culture setting - _applyCulture = _cacheManager.Get("CacheSettingsPart.ApplyCulture", - context => { - context.Monitor(_signals.When(CacheSettingsPart.CacheKey)); - return _workContext.CurrentSite.As().ApplyCulture; - } - ); - - // caches the ignored urls to prevent a query to the settings - _debugMode = _cacheManager.Get("CacheSettingsPart.DebugMode", - context => { - context.Monitor(_signals.When(CacheSettingsPart.CacheKey)); - return _workContext.CurrentSite.As().DebugMode; - } - ); - - CacheItem cacheItem = null; - - var queryString = filterContext.RequestContext.HttpContext.Request.QueryString; - var parameters = new Dictionary(filterContext.ActionParameters); - - foreach(var key in queryString.AllKeys) { - parameters[key] = queryString[key]; - } - - // compute the cache key - _cacheKey = ComputeCacheKey(filterContext, parameters); - - // create a tag which doesn't care about querystring - _invariantCacheKey = ComputeCacheKey(filterContext, null); - - // don't retrieve cache content if refused - // in this case the result of the action will update the current cached version - if (filterContext.RequestContext.HttpContext.Request.Headers["Cache-Control"] != "no-cache") { - - // fetch cached data - cacheItem = _cacheStorageProvider.GetCacheItem(_cacheKey); - - if(cacheItem == null) { - Logger.Debug("Cached version not found"); - } - } - else { - Logger.Debug("Cache-Control = no-cache requested"); - } - - var response = filterContext.HttpContext.Response; - - // render cached content - if (cacheItem != null) - { - Logger.Debug("Cache item found, expires on " + cacheItem.ValidUntilUtc); - - var output = cacheItem.Output; - - /* - * - * There is no need to replace the AntiForgeryToken as it is not used for unauthenticated requests - * and at this point, the request can't be authenticated - * - * - - // replace any anti forgery token with a fresh value - if (output.Contains(AntiforgeryBeacon)) - { - var viewContext = new ViewContext - { - HttpContext = filterContext.HttpContext, - Controller = filterContext.Controller - }; - - var htmlHelper = new HtmlHelper(viewContext, new ViewDataContainer()); - var siteSalt = _workContext.CurrentSite.SiteSalt; - var token = htmlHelper.AntiForgeryToken(siteSalt); - output = output.Replace(AntiforgeryBeacon, token.ToString()); - } - - */ - - // adds some caching information to the output if requested - if (_debugMode) - { - output += "\r\n"; - response.AddHeader("X-Cached-On", cacheItem.CachedOnUtc.ToString("r")); - response.AddHeader("X-Cached-Until", cacheItem.ValidUntilUtc.ToString("r")); - } - - filterContext.Result = new ContentResult - { - Content = output, - ContentType = cacheItem.ContentType - }; - - response.StatusCode = cacheItem.StatusCode; - - ApplyCacheControl(cacheItem, response, output); - - return; - } - - // no cache content available, intercept the execution results for caching - response.Filter = _filter = new CapturingResponseFilter(response.Filter); - } - - public void OnActionExecuted(ActionExecutedContext filterContext) { - - // ignore error results from cache - if (filterContext.HttpContext.Response.StatusCode != (int)HttpStatusCode.OK) { - _filter = null; - return; - } - - // if the result of a POST is a Redirect, remove any Cache Item for this url - // so that the redirected client gets a fresh result - // also add a random token to the query string so that public cachers (IIS, proxies, ...) don't return cached content - // i.e., Comment creation - - // ignore in admin - if (AdminFilter.IsApplied(new RequestContext(filterContext.HttpContext, new RouteData()))) { - return; - } - - _workContext = _workContextAccessor.GetContext(); - - // ignore authenticated requests - if (_workContext.CurrentUser != null) { - return; - } - - if (filterContext.HttpContext.Request.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) - && filterContext.Result is RedirectResult) { - - Logger.Debug("Redirect on POST"); - var redirectUrl = ((RedirectResult)filterContext.Result).Url; - - if (!VirtualPathUtility.IsAbsolute(redirectUrl)) { - var applicationRoot = filterContext.HttpContext.Request.ToRootUrlString(); - if (redirectUrl.StartsWith(applicationRoot, StringComparison.OrdinalIgnoreCase)) { - redirectUrl = redirectUrl.Substring(applicationRoot.Length); - } - } - - // querystring invariant key - var invariantCacheKey = ComputeCacheKey( - _shellSettings.Name, - redirectUrl, - () => _workContext.CurrentCulture, - _themeManager.GetRequestTheme(filterContext.RequestContext).Id, - null - ); - - _cacheService.RemoveByTag(invariantCacheKey); - - // adding a refresh key so that the next request will not be cached - var epIndex = redirectUrl.IndexOf('?'); - var qs = new NameValueCollection(); - if (epIndex > 0) { - qs = HttpUtility.ParseQueryString(redirectUrl.Substring(epIndex)); - } - - var refresh = _now.Ticks; - qs.Remove(RefreshKey); - - qs.Add(RefreshKey, refresh.ToString("x")); - var querystring = "?" + string.Join("&", Array.ConvertAll(qs.AllKeys, k => string.Format("{0}={1}", HttpUtility.UrlEncode(k), HttpUtility.UrlEncode(qs[k])))); - - if (epIndex > 0) { - redirectUrl = redirectUrl.Substring(0, epIndex) + querystring; - } - else { - redirectUrl = redirectUrl + querystring; - } - - filterContext.Result = new RedirectResult(redirectUrl, ((RedirectResult)filterContext.Result).Permanent); - filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache); - } - } - - public void OnResultExecuted(ResultExecutedContext filterContext) - { - var response = filterContext.HttpContext.Response; - - // save the result only if the content can be intercepted - if (_filter == null) return; - - // only for ViewResult right now, as we don't want to handle redirects, HttpNotFound, ... - if (filterContext.Result as ViewResultBase == null) { - Logger.Debug("Ignoring none ViewResult response"); - return; - } - - // check if there is a specific rule not to cache the whole route - var configurations = _cacheService.GetRouteConfigurations(); - var route = filterContext.Controller.ControllerContext.RouteData.Route; - var key = _cacheService.GetRouteDescriptorKey(filterContext.HttpContext, route); - var configuration = configurations.FirstOrDefault(c => c.RouteKey == key); - - // do not cache ? - if (configuration != null && configuration.Duration == 0) - { - return; - } - - // ignored url ? - if (IsIgnoredUrl(filterContext.RequestContext.HttpContext.Request.AppRelativeCurrentExecutionFilePath, _ignoredUrls)) - { - return; - } - - // get contents - - response.Flush(); - var output = _filter.GetContents(response.ContentEncoding); - - if (String.IsNullOrWhiteSpace(output)) - { - return; - } - - var tokenIndex = output.IndexOf(AntiforgeryTag, StringComparison.Ordinal); - - // substitute antiforgery token by a beacon - if (tokenIndex != -1) - { - var tokenEnd = output.IndexOf(">", tokenIndex, StringComparison.Ordinal); - var sb = new StringBuilder(); - sb.Append(output.Substring(0, tokenIndex)); - sb.Append(AntiforgeryBeacon); - sb.Append(output.Substring(tokenEnd + 1)); - - output = sb.ToString(); - } - - // default duration of specific one ? - var cacheDuration = configuration != null && configuration.Duration.HasValue ? configuration.Duration.Value : _cacheDuration; - - // include each of the content item ids as tags for the cache entry - var contentItemIds = _displayedContentItemHandler.GetDisplayed().Select(x => x.ToString(CultureInfo.InvariantCulture)).ToArray(); - - var cacheItem = new CacheItem - { - ContentType = response.ContentType, - StatusCode = response.StatusCode, - CachedOnUtc = _now, - ValidUntilUtc = _now.AddSeconds(cacheDuration), - QueryString = filterContext.HttpContext.Request.Url.Query, - Output = output, - CacheKey = _cacheKey, - InvariantCacheKey = _invariantCacheKey, - Tenant = _shellSettings.Name, - Url = filterContext.HttpContext.Request.Url.AbsolutePath, - Tags = new[] { _invariantCacheKey }.Union(contentItemIds).ToArray() - }; - - ApplyCacheControl(cacheItem, response, output); - - Logger.Debug("Cache item added: " + cacheItem.CacheKey); - - // remove old cache data - _cacheService.RemoveByTag(_invariantCacheKey); - - // add data to cache - _cacheStorageProvider.Set(_cacheKey, cacheItem); - - // add to the tags index - foreach (var tag in cacheItem.Tags) { - _tagCache.Tag(tag, _cacheKey); - } - - } - - public void OnResultExecuting(ResultExecutingContext filterContext) - { - } - - /// - /// Define valid cache control values - /// - private void ApplyCacheControl(CacheItem cacheItem, HttpResponseBase response, string content) { - if (_maxAge > 0) { - var maxAge = new TimeSpan(0, 0, 0, _maxAge); //cacheItem.ValidUntilUtc - _clock.UtcNow; - if (maxAge.TotalMilliseconds < 0) { - maxAge = TimeSpan.FromSeconds(0); - } - - response.Cache.SetCacheability(HttpCacheability.Public); - response.Cache.SetMaxAge(maxAge); - } - - response.Cache.SetETag(content.GetHashCode().ToString(CultureInfo.InvariantCulture)); - - response.Cache.SetOmitVaryStar(true); - - // different tenants with the same urls have different entries - response.Cache.VaryByHeaders["HOST"] = true; - - // Set the Vary: Accept-Encoding response header. - // This instructs the proxies to cache two versions of the resource: one compressed, and one uncompressed. - // The correct version of the resource is delivered based on the client request header. - // This is a good choice for applications that are singly homed and depend on public proxies for user locality. - response.Cache.VaryByHeaders["Accept-Encoding"] = true; - - // create a unique cache per browser, in case a Theme is rendered differently (e.g., mobile) - // c.f. http://msdn.microsoft.com/en-us/library/aa478965.aspx - // c.f. http://stackoverflow.com/questions/6007287/outputcache-varybyheader-user-agent-or-varybycustom-browser - response.Cache.SetVaryByCustom("browser"); - - // enabling this would create an entry for each different browser sub-version - // response.Cache.VaryByHeaders.UserAgent = true; - - } - - private string ComputeCacheKey(ControllerContext controllerContext, IEnumerable> parameters) { - var url = controllerContext.HttpContext.Request.RawUrl; - if(!VirtualPathUtility.IsAbsolute(url)) { - var applicationRoot = controllerContext.HttpContext.Request.ToRootUrlString(); - if(url.StartsWith(applicationRoot, StringComparison.OrdinalIgnoreCase)) { - url = url.Substring(applicationRoot.Length); - } - } - return ComputeCacheKey(_shellSettings.Name, url, () => _workContext.CurrentCulture, _themeManager.GetRequestTheme(controllerContext.RequestContext).Id, parameters); - } - - private string ComputeCacheKey(string tenant, string absoluteUrl, Func culture, string theme, IEnumerable> parameters){ - var keyBuilder = new StringBuilder(); - - keyBuilder.Append("tenant=").Append(tenant).Append(";"); - - keyBuilder.Append("url=").Append(absoluteUrl.ToLowerInvariant()).Append(";"); - - // include the theme in the cache key - if (_applyCulture) { - keyBuilder.Append("culture=").Append(culture().ToLowerInvariant()).Append(";"); - } - - // include the theme in the cache key - keyBuilder.Append("theme=").Append(theme.ToLowerInvariant()).Append(";"); - - // include the theme in the cache key - keyBuilder.Append("action=").Append(_actionName.ToLowerInvariant()).Append(";"); - - if (parameters != null) { - foreach (var pair in parameters) { - keyBuilder.AppendFormat("{0}={1};", pair.Key.ToLowerInvariant(), Convert.ToString(pair.Value).ToLowerInvariant()); - } - } - - return keyBuilder.ToString(); - } - - /// - /// Returns true if the given url should be ignored, as defined in the settings - /// - private static bool IsIgnoredUrl(string url, string ignoredUrls) - { - if(String.IsNullOrEmpty(ignoredUrls)) - { - return false; - } - - // remove ~ if present - if(url.StartsWith("~")) { - url = url.Substring(1); - } - - using (var urlReader = new StringReader(ignoredUrls)) - { - string relativePath; - while (null != (relativePath = urlReader.ReadLine())) - { - // remove ~ if present - if (relativePath.StartsWith("~")) { - relativePath = relativePath.Substring(1); - } - - if (String.IsNullOrWhiteSpace(relativePath)) - { - continue; - } - - relativePath = relativePath.Trim(); - - // ignore comments - if(relativePath.StartsWith("#")) - { - continue; - } - - if(String.Equals(relativePath, url, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - } - - return false; - } - - } - - /// - /// Captures the response stream while writing to it - /// - public class CapturingResponseFilter : Stream - { - private readonly Stream _sink; - private readonly MemoryStream _mem; - - public CapturingResponseFilter(Stream sink) - { - _sink = sink; - _mem = new MemoryStream(); - } - - // The following members of Stream must be overriden. - public override bool CanRead - { - get { return true; } - } - - public override bool CanSeek - { - get { return false; } - } - - public override bool CanWrite - { - get { return false; } - } - - public override long Length - { - get { return 0; } - } - - public override long Position { get; set; } - - public override long Seek(long offset, SeekOrigin direction) - { - return 0; - } - - public override void SetLength(long length) - { - _sink.SetLength(length); - } - - public override void Close() - { - _sink.Close(); - _mem.Close(); - } - - public override void Flush() - { - _sink.Flush(); - } - - public override int Read(byte[] buffer, int offset, int count) - { - return _sink.Read(buffer, offset, count); - } - - // Override the Write method to filter Response to a file. - public override void Write(byte[] buffer, int offset, int count) - { - //Here we will not write to the sink b/c we want to capture - _sink.Write(buffer, offset, count); - - //Write out the response to the file. - _mem.Write(buffer, 0, count); - } - - public string GetContents(Encoding enc) - { - var buffer = new byte[_mem.Length]; - _mem.Position = 0; - _mem.Read(buffer, 0, buffer.Length); - return enc.GetString(buffer, 0, buffer.Length); - } - - } - - public class ViewDataContainer : IViewDataContainer - { - public ViewDataDictionary ViewData { get; set; } - } - -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Handlers/CacheSettingsPartHandler.cs b/src/Orchard.Web/Modules/Contrib.Cache/Handlers/CacheSettingsPartHandler.cs deleted file mode 100644 index 4b598891c..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Handlers/CacheSettingsPartHandler.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Globalization; -using Contrib.Cache.Models; -using Contrib.Cache.Services; -using Orchard.ContentManagement; -using Orchard.Core.Common.Models; -using Orchard.Data; -using Orchard.ContentManagement.Handlers; - -namespace Contrib.Cache.Handlers { - public class CacheSettingsPartHandler : ContentHandler { - private readonly ICacheService _cacheService; - - public CacheSettingsPartHandler( - IRepository repository, - ICacheService cacheService) { - _cacheService = cacheService; - Filters.Add(new ActivatingFilter("Site")); - Filters.Add(StorageFilter.For(repository)); - - // initializing default cache settings values - OnInitializing((context, part) => { part.DefaultCacheDuration = 300; }); - - // evict modified routable content when updated - OnPublished((context, part) => Invalidate(part)); - } - - private void Invalidate(IContent content) { - // remove any page tagged with this content item id - _cacheService.RemoveByTag(content.ContentItem.Id.ToString(CultureInfo.InvariantCulture)); - - // search the cache for containers too - var commonPart = content.As(); - if (commonPart != null) { - if (commonPart.Container != null) { - _cacheService.RemoveByTag(commonPart.Container.Id.ToString(CultureInfo.InvariantCulture)); - } - } - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Handlers/DisplayedContentItemHandler.cs b/src/Orchard.Web/Modules/Contrib.Cache/Handlers/DisplayedContentItemHandler.cs deleted file mode 100644 index 987320c5f..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Handlers/DisplayedContentItemHandler.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using Contrib.Cache.Services; -using Orchard.ContentManagement.Handlers; - -namespace Contrib.Cache.Handlers { - /// - /// Saves references to content items which have been displayed during a request - /// - public class DisplayedContentItemHandler : ContentHandler, IDisplayedContentItemHandler { - private readonly Collection _itemIds = new Collection(); - - protected override void BuildDisplayShape(BuildDisplayContext context) { - _itemIds.Add(context.Content.Id); - } - - public bool IsDisplayed(int id) { - return _itemIds.Contains(id); - } - - public IEnumerable GetDisplayed() { - return _itemIds.Distinct(); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Migrations.cs b/src/Orchard.Web/Modules/Contrib.Cache/Migrations.cs deleted file mode 100644 index 4ead3cb32..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Migrations.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Orchard.Data.Migration; - -namespace Contrib.Cache { - public class Migrations : DataMigrationImpl { - public int Create() { - - SchemaBuilder.CreateTable("CacheSettingsPartRecord", - table => table - .ContentPartRecord() - .Column("DefaultCacheDuration") - .Column("DefaultMaxAge") - .Column("IgnoredUrls", c => c.Unlimited()) - .Column("DebugMode", c => c.WithDefault(false)) - .Column("ApplyCulture", c => c.WithDefault(false)) - ); - - SchemaBuilder.CreateTable("CacheParameterRecord", - table => table - .Column("Id", c => c.PrimaryKey().Identity()) - .Column("Duration") - .Column("MaxAge") - .Column("RouteKey", c => c.WithLength(255)) - ); - - return 4; - } - - public int UpdateFrom1() { - SchemaBuilder.CreateTable("CacheParameterRecord", - table => table - .Column("Id", c => c.PrimaryKey().Identity()) - .Column("Duration") - .Column("RouteKey", c => c.WithLength(255)) - ); - - SchemaBuilder.AlterTable("CacheSettingsPartRecord", - table => table - .AddColumn("IgnoredUrls", c => c.Unlimited()) - ); - - SchemaBuilder.AlterTable("CacheSettingsPartRecord", - table => table - .AddColumn("DebugMode", c => c.WithDefault(false)) - ); - - return 2; - } - - public int UpdateFrom2() { - - SchemaBuilder.AlterTable("CacheSettingsPartRecord", - table => table - .AddColumn("ApplyCulture", c => c.WithDefault(false)) - ); - - return 3; - } - - public int UpdateFrom3() { - - SchemaBuilder.AlterTable("CacheSettingsPartRecord", - table => table - .AddColumn("DefaultMaxAge") - ); - - SchemaBuilder.AlterTable("CacheParameterRecord", - table => table - .AddColumn("MaxAge") - ); - - return 4; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Models/CacheItem.cs b/src/Orchard.Web/Modules/Contrib.Cache/Models/CacheItem.cs deleted file mode 100644 index 650847585..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Models/CacheItem.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace Contrib.Cache.Models { - [Serializable] - public class CacheItem { - public DateTime ValidUntilUtc { get; set; } - public DateTime CachedOnUtc { get; set; } - public string Output { get; set; } - public string ContentType { get; set; } - public string QueryString { get; set; } - public string CacheKey { get; set; } - public string InvariantCacheKey { get; set; } - public string Url { get; set; } - public string Tenant { get; set; } - public int StatusCode { get; set; } - public string[] Tags { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Models/CacheParameterRecord.cs b/src/Orchard.Web/Modules/Contrib.Cache/Models/CacheParameterRecord.cs deleted file mode 100644 index c9c24fa27..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Models/CacheParameterRecord.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Contrib.Cache.Models -{ - public class CacheParameterRecord - { - public virtual int Id { get; set; } - public virtual string RouteKey { get; set; } - public virtual int Duration { get; set; } - public virtual int MaxAge { get; set; } - } - -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Models/CacheSettingsPart.cs b/src/Orchard.Web/Modules/Contrib.Cache/Models/CacheSettingsPart.cs deleted file mode 100644 index a1138f543..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Models/CacheSettingsPart.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Orchard.ContentManagement; - -namespace Contrib.Cache.Models { - public class CacheSettingsPart : ContentPart { - public const string CacheKey = "CacheSettingsPart"; - - public int DefaultCacheDuration { - get { return Record.DefaultCacheDuration; } - set { Record.DefaultCacheDuration = value; } - } - - public int DefaultMaxAge { - get { return Record.DefaultMaxAge; } - set { Record.DefaultMaxAge = value; } - } - - public string IgnoredUrls { - get { return Record.IgnoredUrls; } - set { Record.IgnoredUrls = value; } - } - - public bool ApplyCulture { - get { return Record.ApplyCulture; } - set { Record.ApplyCulture = value; } - } - - public bool DebugMode { - get { return Record.DebugMode; } - set { Record.DebugMode = value; } - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Models/CacheSettingsPartRecord.cs b/src/Orchard.Web/Modules/Contrib.Cache/Models/CacheSettingsPartRecord.cs deleted file mode 100644 index 4124fc371..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Models/CacheSettingsPartRecord.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Orchard.ContentManagement.Records; -using Orchard.Data.Conventions; - -namespace Contrib.Cache.Models { - public class CacheSettingsPartRecord : ContentPartRecord { - public virtual int DefaultCacheDuration { get; set; } - public virtual int DefaultMaxAge { get; set; } - public virtual bool DebugMode { get; set; } - public virtual bool ApplyCulture { get; set; } - - [StringLengthMax] - public virtual string IgnoredUrls { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Module.txt b/src/Orchard.Web/Modules/Contrib.Cache/Module.txt deleted file mode 100644 index 5937aa9bb..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Module.txt +++ /dev/null @@ -1,11 +0,0 @@ -Name: Cache -AntiForgery: enabled -Author: Sébastien Ros -Website: http://orchardcache.codeplex.com/ -Version: 1.3 -OrchardVersion: 1.0 -Description: Adds Caching functionality. -Features: - Contrib.Cache: - Description: Adds Caching functionality. - Category: Performance \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Contrib.Cache/Properties/AssemblyInfo.cs deleted file mode 100644 index 4b3fc5b0d..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Contrib.Cache")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Orchard")] -[assembly: AssemblyCopyright("")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("cc5ee19a-8a16-49cf-96a8-5a1bcdd4fa7d")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Scripts/Web.config b/src/Orchard.Web/Modules/Contrib.Cache/Scripts/Web.config deleted file mode 100644 index 178ff35ba..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Scripts/Web.config +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Services/CacheService.cs b/src/Orchard.Web/Modules/Contrib.Cache/Services/CacheService.cs deleted file mode 100644 index 69c52c9c8..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Services/CacheService.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using System.Web; -using System.Web.Routing; -using Contrib.Cache.Models; -using Contrib.Cache.ViewModels; -using Orchard; -using Orchard.Caching; -using Orchard.Data; -using Orchard.Utility.Extensions; - -namespace Contrib.Cache.Services { - public class CacheService : ICacheService { - private readonly IWorkContextAccessor _workContextAccessor; - private readonly IRepository _repository; - private readonly ICacheManager _cacheManager; - private readonly IOutputCacheStorageProvider _cacheStorageProvider; - private readonly ITagCache _tagCache; - private readonly ISignals _signals; - - public CacheService( - IWorkContextAccessor workContextAccessor, - IRepository repository, - ICacheManager cacheManager, - IOutputCacheStorageProvider cacheStorageProvider, - ITagCache tagCache, - ISignals signals) { - _workContextAccessor = workContextAccessor; - _repository = repository; - _cacheManager = cacheManager; - _cacheStorageProvider = cacheStorageProvider; - _tagCache = tagCache; - _signals = signals; - } - - public void RemoveByTag(string tag) { - Collection itemKeys; - if (_tagCache.TryGetValue(tag, out itemKeys)) { - foreach (var key in itemKeys) { - _cacheStorageProvider.Remove(key); - } - } - } - - public IEnumerable GetCacheItems() { - var workContext = _workContextAccessor.GetContext(); - - foreach (DictionaryEntry cacheEntry in workContext.HttpContext.Cache) { - var cacheItem = cacheEntry.Value as CacheItem; - if (cacheItem != null) { - yield return cacheItem; - } - } - } - - public void Evict(string cacheKey) { - var workContext = _workContextAccessor.GetContext(); - workContext.HttpContext.Cache.Remove(cacheKey); - } - - public string GetRouteDescriptorKey(HttpContextBase httpContext, RouteBase routeBase) { - var route = routeBase as Route; - - var dataTokens = route != null ? route.DataTokens : routeBase.GetRouteData(httpContext).DataTokens; - - var keyBuilder = new StringBuilder(); - - if (route != null) { - keyBuilder.AppendFormat("url={0};", route.Url); - } - - // the data tokens are used in case the same url is used by several features, like *{path} (Rewrite Rules and Home Page Provider) - if (dataTokens != null) { - foreach (var key in dataTokens.Keys) { - keyBuilder.AppendFormat("{0}={1};", key, dataTokens[key]); - } - } - - return keyBuilder.ToString().ToLowerInvariant(); - } - - public CacheParameterRecord GetCacheParameterByKey(string key) { - return _repository.Get(c => c.RouteKey == key); - } - - public IEnumerable GetRouteConfigurations() { - return _cacheManager.Get("GetRouteConfigurations", - ctx => { - ctx.Monitor(_signals.When("GetRouteConfigurations")); - return _repository.Fetch(c => true).Select(c => new RouteConfiguration { RouteKey = c.RouteKey, Duration = c.Duration }).ToReadOnlyCollection(); - }); - } - - public void SaveCacheConfigurations(IEnumerable routeConfigurations) { - // remove all current configurations - var configurations = _repository.Fetch(c => true); - - foreach (var configuration in configurations) { - _repository.Delete(configuration); - } - - // save the new configurations - foreach (var configuration in routeConfigurations) { - if (!configuration.Duration.HasValue) { - continue; - } - - _repository.Create(new CacheParameterRecord { - Duration = configuration.Duration.Value, - RouteKey = configuration.RouteKey - }); - } - - // invalidate the cache - _signals.Trigger("GetRouteConfigurations"); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Services/DefaultCacheStorageProvider.cs b/src/Orchard.Web/Modules/Contrib.Cache/Services/DefaultCacheStorageProvider.cs deleted file mode 100644 index 7eb9d2985..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Services/DefaultCacheStorageProvider.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using Contrib.Cache.Models; -using Orchard; -using Orchard.Environment.Configuration; - -namespace Contrib.Cache.Services { - public class DefaultCacheStorageProvider : IOutputCacheStorageProvider { - private readonly string _tenantName; - private readonly WorkContext _workContext; - - public DefaultCacheStorageProvider(IWorkContextAccessor workContextAccessor, ShellSettings shellSettings) { - _workContext = workContextAccessor.GetContext(); - _tenantName = shellSettings.Name; - } - - public void Set(string key, CacheItem cacheItem) { - _workContext.HttpContext.Cache.Add( - key, - cacheItem, - null, - cacheItem.ValidUntilUtc, - System.Web.Caching.Cache.NoSlidingExpiration, - System.Web.Caching.CacheItemPriority.Normal, - null); - } - - public void Remove(string key) { - _workContext.HttpContext.Cache.Remove(key); - } - - public void RemoveAll() { - var items = GetCacheItems(0, 100).ToList(); - while (items.Any()) { - foreach (var item in items) { - Remove(item.CacheKey); - } - } - } - - public CacheItem GetCacheItem(string key) { - return _workContext.HttpContext.Cache.Get(key) as CacheItem; - } - - public IEnumerable GetCacheItems(int skip, int count) { - // the ASP.NET cache can also contain other types of items - return _workContext.HttpContext.Cache - .Cast() - .Select(x => x.Value) - .OfType() - .Where(x => x.Tenant.Equals(_tenantName, StringComparison.OrdinalIgnoreCase)) - .Skip(skip) - .Take(count); - } - - public int GetCacheItemsCount() { - return _workContext.HttpContext.Cache - .Cast() - .Select(x => x.Value) - .OfType() - .Count(x => x.Tenant.Equals(_tenantName, StringComparison.OrdinalIgnoreCase)); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Services/DefaultTagCache.cs b/src/Orchard.Web/Modules/Contrib.Cache/Services/DefaultTagCache.cs deleted file mode 100644 index da566a5c8..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Services/DefaultTagCache.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.ObjectModel; -using Contrib.Cache.Models; - -namespace Contrib.Cache.Services { - /// - /// Tenant wide case insensitive reverse index for tags. - /// - public class DefaultTagCache : ConcurrentDictionary>, ITagCache { - public DefaultTagCache() : base(StringComparer.OrdinalIgnoreCase) { - } - - public void Tag(string tag, params string[] keys) { - var collection = GetOrAdd(tag, x => new Collection()); - - foreach (var key in keys) { - if (!collection.Contains(key)) { - collection.Add(key); - } - } - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Services/ICacheService.cs b/src/Orchard.Web/Modules/Contrib.Cache/Services/ICacheService.cs deleted file mode 100644 index c5f8c4151..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Services/ICacheService.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Collections.Generic; -using System.Web; -using System.Web.Routing; -using Contrib.Cache.ViewModels; -using Orchard; -using Contrib.Cache.Models; - -namespace Contrib.Cache.Services { - public interface ICacheService : IDependency { - /// - /// Returns the parameters for a specific route - /// - /// The key representing the route - /// A instance for the specified key, or null - CacheParameterRecord GetCacheParameterByKey(string key); - - /// - /// Removes all cache entries associated with a specific tag. - /// - /// The tag value. - void RemoveByTag(string tag); - - /// - /// Returns the key representing a specific route in the db - /// - string GetRouteDescriptorKey(HttpContextBase httpContext, RouteBase route); - - /// - /// Saves a set of to the database - /// - /// - void SaveCacheConfigurations(IEnumerable routeConfigurations); - - /// - /// Returns all defined configurations for specific routes - /// - IEnumerable GetRouteConfigurations(); - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Services/IDisplayedContentItemHandler.cs b/src/Orchard.Web/Modules/Contrib.Cache/Services/IDisplayedContentItemHandler.cs deleted file mode 100644 index 44f59b9b1..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Services/IDisplayedContentItemHandler.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; -using Orchard; - -namespace Contrib.Cache.Services { - public interface IDisplayedContentItemHandler : IDependency { - bool IsDisplayed(int id); - IEnumerable GetDisplayed(); - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Services/IOutputCacheStorageProvider.cs b/src/Orchard.Web/Modules/Contrib.Cache/Services/IOutputCacheStorageProvider.cs deleted file mode 100644 index 185e045e1..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Services/IOutputCacheStorageProvider.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; -using Contrib.Cache.Models; -using Orchard; - -namespace Contrib.Cache.Services { - public interface IOutputCacheStorageProvider : IDependency { - /// - /// Adds a new or substitute it with a new one if the - /// cache key is already used. - /// - /// The unique key representing the . - /// The instance to add to the cache. - void Set(string key, CacheItem cacheItem); - - void Remove(string key); - void RemoveAll(); - - CacheItem GetCacheItem(string key); - IEnumerable GetCacheItems(int skip, int count); - int GetCacheItemsCount(); - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Services/ITagCache.cs b/src/Orchard.Web/Modules/Contrib.Cache/Services/ITagCache.cs deleted file mode 100644 index d8c50efa1..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Services/ITagCache.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using Orchard; - -namespace Contrib.Cache.Services { - public interface ITagCache : IDictionary>, ISingletonDependency { - void Tag(string tag, params string[] keys); - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Styles/Web.config b/src/Orchard.Web/Modules/Contrib.Cache/Styles/Web.config deleted file mode 100644 index 178ff35ba..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Styles/Web.config +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/Orchard.Web/Modules/Contrib.Cache/ViewModels/IndexViewModel.cs b/src/Orchard.Web/Modules/Contrib.Cache/ViewModels/IndexViewModel.cs deleted file mode 100644 index b8e3ca1dc..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/ViewModels/IndexViewModel.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; - -namespace Contrib.Cache.ViewModels { - public class IndexViewModel { - public List RouteConfigurations { get; set; } - [Range(0, int.MaxValue), Required] - public int DefaultCacheDuration { get; set; } - [Range(0, int.MaxValue), Required] - public int DefaultMaxAge { get; set; } - public string IgnoredUrls { get; set; } - public bool ApplyCulture { get; set; } - public bool DebugMode { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/ViewModels/RouteConfiguration.cs b/src/Orchard.Web/Modules/Contrib.Cache/ViewModels/RouteConfiguration.cs deleted file mode 100644 index a606cf2fb..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/ViewModels/RouteConfiguration.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Contrib.Cache.ViewModels { - public class RouteConfiguration { - public string RouteKey { get; set; } - public string Url { get; set; } - public int Priority { get; set; } - public int? Duration { get; set; } - public int? MaxAge { get; set; } - public string FeatureName { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/ViewModels/StatisticsViewModel.cs b/src/Orchard.Web/Modules/Contrib.Cache/ViewModels/StatisticsViewModel.cs deleted file mode 100644 index 50a91987f..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/ViewModels/StatisticsViewModel.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; -using Contrib.Cache.Models; - -namespace Contrib.Cache.ViewModels { - public class StatisticsViewModel { - public IEnumerable CacheItems { get; set; } - public dynamic Pager { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Contrib.Cache/Views/Admin/Index.cshtml deleted file mode 100644 index fa102c57d..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Views/Admin/Index.cshtml +++ /dev/null @@ -1,72 +0,0 @@ -@model Contrib.Cache.ViewModels.IndexViewModel - -@{ - Layout.Title = T("Cache Settings"); - - // group configurations by feature name - var featureRouteConfigurations = Model.RouteConfigurations - .GroupBy(x => x.FeatureName) - .ToDictionary(x => x.Key, x => x.Select(y => y)); -} - -@using (Html.BeginFormAntiForgeryPost()) -{ - @Html.ValidationSummary() - -
- - @Html.TextBoxFor(m => m.DefaultCacheDuration, new { @class = "text-small" }) - @T("Number of seconds the pages should be kept in cache on the server.") -
- -
- - @Html.TextBoxFor(m => m.DefaultMaxAge, new { @class = "text-small" }) - @T("When defined, a cache-control header with a max-age property will be added. Use this in order to enable kernel cache on IIS.") -
- -
- - @Html.TextAreaFor(m => m.IgnoredUrls, new { @class = "textMedium" }) - @T("This must be a set of relative paths, e.g., /, /About. Please ensure that you enter only one path per line.") - @T("You can add comments by starting the line with #.") -
- -
- - @Html.CheckBoxFor(m => m.ApplyCulture) - @T("When checked, the cached content will differ per culture too. For performance reasons leave it unchecked if you website uses only one culture.") -
- -
- - @Html.CheckBoxFor(m => m.DebugMode) -
- - foreach (var feature in featureRouteConfigurations.Keys) { -

@T(feature)

- - - - - - - - - @foreach (var routeConfiguration in featureRouteConfigurations[feature]) { - var index = Model.RouteConfigurations.IndexOf(routeConfiguration); - - - - - @Html.HiddenFor(m => m.RouteConfigurations[index].RouteKey) - - } -
@T("Route")@T("Priority")@T("Duration")
@routeConfiguration.Url@routeConfiguration.Priority - @Html.TextBoxFor(m => m.RouteConfigurations[index].Duration, new { @class = "text-small" }) - @T("Leave empty to use default duration, 0 to disable caching on this route.") -
- } - - -} diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Views/Statistics/Index.cshtml b/src/Orchard.Web/Modules/Contrib.Cache/Views/Statistics/Index.cshtml deleted file mode 100644 index 02a1112ed..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Views/Statistics/Index.cshtml +++ /dev/null @@ -1,35 +0,0 @@ -@using Contrib.Cache.ViewModels -@model StatisticsViewModel - -@{ - Layout.Title = T("Cache Statistics"); -} - -@using (Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() -
@Html.ActionLink(T("Evict All").ToString(), "EvictAll", new { Area = "Contrib.Cache", Controller = "Statistics" }, new { @class = "button primaryAction", itemprop = "UnsafeUrl" })
-} - -

@T("Cached pages")

- - - - - - - - - - @foreach (var cacheItem in Model.CacheItems) { - - - - - - - } -
@T("Url")@T("Cached On")@T("Cached Until") 
@cacheItem.Url@Display.DateTimeRelative(dateTimeUtc: cacheItem.CachedOnUtc)@cacheItem.ValidUntilUtc.ToLocalTime()@Html.ActionLink(T("Evict").Text, "Evict", new { Area = "Contrib.Cache", Controller = "Statistics", cacheKey = cacheItem.CacheKey })
- -@Display(Model.Pager) - - diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Views/Web.config b/src/Orchard.Web/Modules/Contrib.Cache/Views/Web.config deleted file mode 100644 index b7d215131..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Views/Web.config +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Orchard.Web/Modules/Contrib.Cache/Web.config b/src/Orchard.Web/Modules/Contrib.Cache/Web.config deleted file mode 100644 index 1c781fdb8..000000000 --- a/src/Orchard.Web/Modules/Contrib.Cache/Web.config +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/AdminMenu.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/AdminMenu.cs deleted file mode 100644 index 089186c63..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/AdminMenu.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Orchard.Localization; -using Orchard.UI.Navigation; - -namespace Contrib.Taxonomies { - public class AdminMenu : INavigationProvider { - public Localizer T { get; set; } - public string MenuName { get { return "admin"; } } - - public void GetNavigation(NavigationBuilder builder) { - builder.Add(T("Taxonomies"), "4", - menu => menu - .Add(T("Manage Taxonomies"), "1.0", item => item.Action("Index", "Admin", new { area = "Contrib.Taxonomies" }).Permission(Permissions.ManageTaxonomies)) - ); - } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Contrib.Taxonomies.csproj b/src/Orchard.Web/Modules/Contrib.Taxonomies/Contrib.Taxonomies.csproj deleted file mode 100644 index 221a96614..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Contrib.Taxonomies.csproj +++ /dev/null @@ -1,242 +0,0 @@ - - - - Debug - AnyCPU - - - 2.0 - {E649EA64-D213-461B-87F7-D67035801443} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Contrib.Taxonomies - Contrib.Taxonomies - v4.0 - false - false - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - - - - False - ..\..\..\..\lib\linqnhibernate\NHibernate.Linq.dll - - - - - - - - - 3.5 - - - 3.5 - - - 3.5 - - - False - ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll - - - 3.5 - - - - 3.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} - Orchard.Framework - - - {9916839C-39FC-4CEB-A5AF-89CA7E87119F} - Orchard.Core - - - {66FCCD76-2761-47E3-8D11-B45D0001DDAA} - Orchard.Autoroute - - - - - - - - - - - - - - - - - - - - - - - Designer - - - Designer - - - - - - - - - - - - - - Designer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - False - True - 2078 - / - - - False - True - http://orchard.codeplex.com - False - - - - - \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Controllers/AdminController.cs deleted file mode 100644 index 7169e18b8..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Controllers/AdminController.cs +++ /dev/null @@ -1,210 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Web.Mvc; -using JetBrains.Annotations; -using Orchard; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Aspects; -using Orchard.Localization; -using Orchard.Settings; -using Contrib.Taxonomies.Models; -using Contrib.Taxonomies.ViewModels; -using Contrib.Taxonomies.Services; -using Orchard.UI.Notify; - -namespace Contrib.Taxonomies.Controllers { - - [ValidateInput(false)] - public class AdminController : Controller, IUpdateModel { - private readonly ITaxonomyService _taxonomyService; - - public AdminController( - IOrchardServices services, - ITaxonomyService taxonomyService) { - Services = services; - _taxonomyService = taxonomyService; - T = NullLocalizer.Instance; - } - - public IOrchardServices Services { get; set; } - protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; } - - public Localizer T { get; set; } - - public ActionResult Index() { - IEnumerable taxonomies = _taxonomyService.GetTaxonomies(); - var entries = taxonomies.Select(CreateTaxonomyEntry).ToList(); - var model = new TaxonomyAdminIndexViewModel { Taxonomies = entries }; - return View(model); - } - - [HttpPost] - public ActionResult Index(FormCollection input) { - var viewModel = new TaxonomyAdminIndexViewModel { Taxonomies = new List(), BulkAction = new TaxonomiesAdminIndexBulkAction() }; - - if (!TryUpdateModel(viewModel)) { - return View(viewModel); - } - - var checkedEntries = viewModel.Taxonomies.Where(t => t.IsChecked); - switch (viewModel.BulkAction) { - case TaxonomiesAdminIndexBulkAction.None: - break; - case TaxonomiesAdminIndexBulkAction.Delete: - if (!Services.Authorizer.Authorize(Permissions.ManageTaxonomies, T("Couldn't delete taxonomy"))) - return new HttpUnauthorizedResult(); - - foreach (var entry in checkedEntries) { - _taxonomyService.DeleteTaxonomy(entry.Taxonomy); - } - break; - - default: - throw new ArgumentOutOfRangeException(); - } - - return RedirectToAction("Index"); - } - - public ActionResult Delete(int id) { - if (!Services.Authorizer.Authorize(Permissions.CreateTaxonomy, T("Couldn't delete taxonomy"))) - return new HttpUnauthorizedResult(); - - var taxonomy = _taxonomyService.GetTaxonomy(id); - if (taxonomy == null) { - return HttpNotFound(); - } - - _taxonomyService.DeleteTaxonomy(taxonomy); - - return RedirectToAction("Index"); - } - - public ActionResult Import(int id, string terms) { - if (!Services.Authorizer.Authorize(Permissions.CreateTaxonomy, T("Couldn't import terms"))) - return new HttpUnauthorizedResult(); - - var taxonomy = _taxonomyService.GetTaxonomy(id); - - if (taxonomy == null) { - return HttpNotFound(); - } - - return View(new ImportViewModel { Taxonomy = taxonomy, Terms = terms }); - } - - [HttpPost, ActionName("Import")] - public ActionResult ImportPost(int id, string terms) { - if (!Services.Authorizer.Authorize(Permissions.CreateTaxonomy, T("Couldn't import terms"))) - return new HttpUnauthorizedResult(); - - var taxonomy = _taxonomyService.GetTaxonomy(id); - - if (taxonomy == null) { - return HttpNotFound(); - } - - var topTerm = new TermPosition(); - - using (var reader = new StringReader(terms)) { - string line; - var previousLevel = 0; - var parents = new Stack(); - TermPosition parentTerm = null; - while (null != (line = reader.ReadLine())) { - - // ignore empty lines - if(String.IsNullOrWhiteSpace(line)) { - continue; - } - - // compute level from tabs - var level = 0; - while (line[level] == '\t') level++; // number of tabs to know the level - - // create a new term content item - var term = _taxonomyService.NewTerm(taxonomy); - - // detect parent term - if (level == previousLevel + 1) { - parentTerm = parents.Peek(); - parents.Push(new TermPosition { Term = term }); - } else if (level == previousLevel) { - // same parent term - if (parents.Any()) - parents.Pop(); - - parents.Push(new TermPosition { Term = term }); - } else if (level < previousLevel) { - for (var i = previousLevel; i >= level; i--) - parents.Pop(); - - parentTerm = parents.Any() ? parents.Peek() : null; - parents.Push(new TermPosition { Term = term }); - } - - // increment number of children - if (parentTerm == null) { - parentTerm = topTerm; - } - - parentTerm.Position++; - term.Weight = parentTerm.Position; - - term.Container = parentTerm.Term == null ? taxonomy.ContentItem : parentTerm.Term.ContentItem; - - line = line.Trim(); - int scIndex = line.IndexOf(';'); // seek first semi-colon to extract term and slug - - // is there a semi-colon - if (scIndex != -1) { - term.Name = line.Substring(0, scIndex); - term.Slug = line.Substring(scIndex + 1); - } else { - term.Name = line; - } - - var existing = _taxonomyService.GetTermByName(id, term.Name); - - // a different term exist under the same parent term ? - if (existing != null && existing.Container.ContentItem.Record == term.Container.ContentItem.Record) { - Services.Notifier.Error(T("The term {0} already exists at this level", term.Name)); - Services.TransactionManager.Cancel(); - return View(new ImportViewModel {Taxonomy = taxonomy, Terms = terms}); - } - - _taxonomyService.ProcessPath(term); - Services.ContentManager.Create(term, VersionOptions.Published); - - previousLevel = level; - } - } - - Services.Notifier.Information(T("The terms have been imported successfully.")); - - return RedirectToAction("Index", "TermAdmin", new { taxonomyId = id }); - } - - private static TaxonomyEntry CreateTaxonomyEntry(TaxonomyPart taxonomy) { - return new TaxonomyEntry { - Taxonomy = taxonomy, - IsChecked = false, - }; - } - - bool IUpdateModel.TryUpdateModel(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) { - return TryUpdateModel(model, prefix, includeProperties, excludeProperties); - } - - void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) { - ModelState.AddModelError(key, errorMessage.ToString()); - } - - private class TermPosition { - public TermPart Term { get; set; } - public int Position { get; set; } - } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Controllers/HomeController.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Controllers/HomeController.cs deleted file mode 100644 index 674b942fc..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Controllers/HomeController.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System.Linq; -using System.Web.Mvc; -using System.Web.Routing; -using Contrib.Taxonomies.Routing; -using JetBrains.Annotations; -using Orchard.ContentManagement; -using Orchard.Core.Feeds; -using Orchard.DisplayManagement; -using Orchard.Localization; -using Orchard.Logging; -using Orchard.Mvc; -using Orchard.Settings; -using Contrib.Taxonomies.Services; -using Orchard.Themes; -using Orchard.UI.Navigation; - -namespace Contrib.Taxonomies.Controllers { - [ValidateInput(false), Themed] - public class HomeController : Controller { - private readonly ITaxonomyService _taxonomyService; - private readonly IContentManager _contentManager; - private readonly ISiteService _siteService; - private readonly ITermPathConstraint _termPathConstraint; - private readonly IFeedManager _feedManager; - - public HomeController( - ITaxonomyService taxonomyService, - IContentManager contentManager, - IShapeFactory shapeFactory, - ISiteService siteService, - ITermPathConstraint termPathConstraint, - IFeedManager feedManager) - { - _taxonomyService = taxonomyService; - _contentManager = contentManager; - _siteService = siteService; - _termPathConstraint = termPathConstraint; - _feedManager = feedManager; - Shape = shapeFactory; - T = NullLocalizer.Instance; - } - - dynamic Shape { get; set; } - - protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; } - - public ILogger Logger { get; set; } - public Localizer T { get; set; } - - public ActionResult List(string taxonomySlug, PagerParameters pagerParameters) { - var taxonomyPart = _taxonomyService.GetTaxonomyBySlug(taxonomySlug); - if (taxonomyPart == null) { - return HttpNotFound(); - } - - var terms = _taxonomyService.GetTerms(taxonomyPart.Id).Select(x => _contentManager.BuildDisplay(x.ContentItem, "Summary")); - dynamic taxonomy = _contentManager.BuildDisplay(taxonomyPart); - - var list = Shape.List(); - list.AddRange(terms); - taxonomy.Content.Add(list); - - return new ShapeResult(this, taxonomy); - } - - public ActionResult Item(string termPath, PagerParameters pagerParameters) { - var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters); - var correctedPath = _termPathConstraint.FindPath(termPath); - if (correctedPath == null) - return HttpNotFound(); - - var termPart = _taxonomyService.GetTermByPath(correctedPath); - - if (termPart == null) - return HttpNotFound(); - - var taxonomy = _taxonomyService.GetTaxonomy(termPart.TaxonomyId); - var totalItemCount = _taxonomyService.GetContentItemsCount(termPart); - - var termContentItems = _taxonomyService.GetContentItems(termPart, pager.GetStartIndex(), pager.PageSize) - .Select(c => _contentManager.BuildDisplay(c, "Summary").Taxonomy(taxonomy).Term(termPart)); - - dynamic term = _contentManager.BuildDisplay(termPart); - - var list = Shape.List(); - - list.AddRange(termContentItems); - - term.Content.Add( - Shape.Taxonomies_TermContentItems_List(ContentItems: list) - .Taxonomy(taxonomy) - .Term(termPart), "5"); - - term.Content.Add( - Shape.Pager(pager) - .TotalItemCount(totalItemCount) - .Taxonomy(taxonomy) - .Term(termPart), "Content:after"); - - // generates a link to the RSS feed for this term - _feedManager.Register(termPart.Name, "rss", new RouteValueDictionary { { "term", termPart.Id } }); - - return new ShapeResult(this, term); - } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Controllers/TermAdminController.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Controllers/TermAdminController.cs deleted file mode 100644 index 806afaa72..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Controllers/TermAdminController.cs +++ /dev/null @@ -1,228 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web.Mvc; -using Orchard; -using Orchard.Localization; -using Contrib.Taxonomies.ViewModels; -using Contrib.Taxonomies.Services; -using Orchard.UI.Admin; -using Orchard.ContentManagement; -using Orchard.UI.Notify; -using Contrib.Taxonomies.Helpers; - -namespace Contrib.Taxonomies.Controllers { - [ValidateInput(false), Admin] - public class TermAdminController : Controller, IUpdateModel { - private readonly ITaxonomyService _taxonomyService; - - public TermAdminController(IOrchardServices services, ITaxonomyService taxonomyService) { - Services = services; - _taxonomyService = taxonomyService; - T = NullLocalizer.Instance; - } - - public IOrchardServices Services { get; set; } - - public Localizer T { get; set; } - - public ActionResult Index(int taxonomyId) { - var taxonomy = _taxonomyService.GetTaxonomy(taxonomyId); - var terms = _taxonomyService.GetTerms(taxonomyId); - var entries = terms.Select(term => term.CreateTermEntry()).ToList(); - var model = new TermAdminIndexViewModel { Terms = entries, Taxonomy = taxonomy, TaxonomyId = taxonomyId }; - return View(model); - } - - [HttpPost] - public ActionResult Index(FormCollection input) { - var viewModel = new TermAdminIndexViewModel { Terms = new List(), BulkAction = new TermsAdminIndexBulkAction() }; - - if (!TryUpdateModel(viewModel)) { - return View(viewModel); - } - - IEnumerable checkedEntries = viewModel.Terms.Where(t => t.IsChecked); - switch (viewModel.BulkAction) { - case TermsAdminIndexBulkAction.None: - break; - case TermsAdminIndexBulkAction.Delete: - if (!Services.Authorizer.Authorize(Permissions.ManageTerms, T("Couldn't delete term"))) - return new HttpUnauthorizedResult(); - - foreach (var entry in checkedEntries) { - var term = _taxonomyService.GetTerm(entry.Id); - _taxonomyService.DeleteTerm(term); - } - break; - - default: - throw new ArgumentOutOfRangeException(); - } - - Services.Notifier.Information(T("{0} term have been removed.", checkedEntries.Count())); - - return RedirectToAction("Index", new { taxonomyId = viewModel.TaxonomyId }); - } - - public ActionResult SelectTerm(int taxonomyId) { - if (!Services.Authorizer.Authorize(Permissions.CreateTerm, T("Not allowed to create terms"))) - return new HttpUnauthorizedResult(); - - var terms = _taxonomyService.GetTerms(taxonomyId); - - if (terms.Any()) { - var model = new SelectTermViewModel { - Terms = terms, - SelectedTermId = -1 - }; - - return View(model); - } - - return RedirectToAction("Create", new { taxonomyId, parentTermId = -1 }); - } - - [HttpPost] - public ActionResult SelectTerm(int taxonomyId, int selectedTermId) { - if (!Services.Authorizer.Authorize(Permissions.ManageTerms, T("Not allowed to select terms"))) - return new HttpUnauthorizedResult(); - - return RedirectToAction("Create", new { taxonomyId, parentTermId = selectedTermId }); - } - - public ActionResult MoveTerm(int taxonomyId, int termId) { - if (!Services.Authorizer.Authorize(Permissions.CreateTerm, T("Not allowed to create terms"))) - return new HttpUnauthorizedResult(); - - var term = _taxonomyService.GetTerm(termId); - if(term == null) { - return HttpNotFound(); - } - - var model = new MoveTermViewModel { - Terms = _taxonomyService.GetTerms(taxonomyId).Where(t => !(t.FullPath + "/").StartsWith(term.FullPath + "/")), - TermId = termId, - SelectedTermId = -1 - }; - - return View(model); - } - - [HttpPost] - public ActionResult MoveTerm(int taxonomyId, int selectedTermId, int termId) { - if (!Services.Authorizer.Authorize(Permissions.ManageTerms, T("Not allowed to select terms"))) - return new HttpUnauthorizedResult(); - - var taxonomy = _taxonomyService.GetTaxonomy(taxonomyId); - var parentTerm = _taxonomyService.GetTerm(selectedTermId); - var term = _taxonomyService.GetTerm(termId); - - _taxonomyService.MoveTerm(taxonomy, term, parentTerm); - - return RedirectToAction("Index", new { taxonomyId }); - } - - public ActionResult Create(int taxonomyId, int parentTermId) { - if (!Services.Authorizer.Authorize(Permissions.CreateTerm, T("Not allowed to create terms"))) - return new HttpUnauthorizedResult(); - - var taxonomy = _taxonomyService.GetTaxonomy(taxonomyId); - var parentTerm = _taxonomyService.GetTerm(parentTermId); - var term = _taxonomyService.NewTerm(taxonomy); - - // assign a container to show the full route while editing - term.Container = parentTerm == null ? taxonomy : (IContent)parentTerm; - - var model = Services.ContentManager.BuildEditor(term); - return View((object)model); - } - - [HttpPost, ActionName("Create")] - public ActionResult CreatePost(int taxonomyId, int parentTermId) { - if (!Services.Authorizer.Authorize(Permissions.CreateTerm, T("Couldn't create term"))) - return new HttpUnauthorizedResult(); - - var taxonomy = _taxonomyService.GetTaxonomy(taxonomyId); - var parentTerm = _taxonomyService.GetTerm(parentTermId); - - var term = _taxonomyService.NewTerm(taxonomy); - term.Container = parentTerm == null ? taxonomy.ContentItem : parentTerm.ContentItem; - - var model = Services.ContentManager.UpdateEditor(term, this); - - if (!ModelState.IsValid) { - Services.TransactionManager.Cancel(); - return View((object)model); - } - - _taxonomyService.ProcessPath(term); - - Services.ContentManager.Create(term, VersionOptions.Published); - - Services.Notifier.Information(T("The {0} term has been created.", term.Name)); - - return RedirectToAction("Index", "TermAdmin", new { taxonomyId }); - } - - //public ActionResult Edit(int id) { - - // if (!Services.Authorizer.Authorize(Permissions.ManageTerms, T("Not allowed to manage taxonomies"))) - // return new HttpUnauthorizedResult(); - - // var term = _taxonomyService.GetTerm(id); - // if (term == null) - // return HttpNotFound(); - - // var model = Services.ContentManager.BuildEditor(term); - // return View((object)model); - //} - - //[HttpPost, ActionName("Edit")] - //public ActionResult EditPost(int id) { - // if (!Services.Authorizer.Authorize(Permissions.ManageTaxonomies, T("Couldn't edit taxonomy"))) - // return new HttpUnauthorizedResult(); - - // var term = _taxonomyService.GetTerm(id); - - // if (term == null) - // return HttpNotFound(); - - // var contentItem = Services.ContentManager.Get(term.ContentItem.Id, VersionOptions.DraftRequired); - - // var model = Services.ContentManager.UpdateEditor(contentItem, this); - - // if (!ModelState.IsValid) { - // Services.TransactionManager.Cancel(); - // return View((object)model); - // } - - // Services.ContentManager.Publish(contentItem); - // _taxonomyService.ProcessPath(term); - - // Services.Notifier.Information(T("Term information updated")); - - // return RedirectToAction("Index", "TermAdmin", new { taxonomyId = term.TaxonomyId }); - //} - - public ActionResult RenderTermSelect(int taxonomyId, int selectedTermId = -1) { - if (!Services.Authorizer.Authorize(Permissions.ManageTerms, T("Not allowed to manage terms"))) - return new HttpUnauthorizedResult(); - - var model = new SelectTermViewModel { - Terms = _taxonomyService.GetTerms(taxonomyId), - SelectedTermId = selectedTermId - }; - - return PartialView(model); - } - - bool IUpdateModel.TryUpdateModel(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) { - return TryUpdateModel(model, prefix, includeProperties, excludeProperties); - } - - void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) { - ModelState.AddModelError(key, errorMessage.ToString()); - } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyFieldDriver.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyFieldDriver.cs deleted file mode 100644 index f9d60e714..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyFieldDriver.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Contrib.Taxonomies.Models; -using JetBrains.Annotations; -using Orchard; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Drivers; -using Orchard.ContentManagement.Handlers; -using Orchard.Data; -using Orchard.Localization; -using Contrib.Taxonomies.Fields; -using Contrib.Taxonomies.Services; -using Contrib.Taxonomies.Settings; -using Contrib.Taxonomies.ViewModels; -using Contrib.Taxonomies.Helpers; - -namespace Contrib.Taxonomies.Drivers { - [UsedImplicitly] - public class TaxonomyFieldDriver : ContentFieldDriver { - private readonly ITaxonomyService _taxonomyService; - public IOrchardServices Services { get; set; } - private const string TemplateName = "Fields/Contrib.TaxonomyField"; - - public TaxonomyFieldDriver( - IOrchardServices services, - ITaxonomyService taxonomyService, - IRepository repository) { - _taxonomyService = taxonomyService; - Services = services; - T = NullLocalizer.Instance; - } - - public Localizer T { get; set; } - - private static string GetPrefix(ContentField field, ContentPart part) { - return part.PartDefinition.Name + "." + field.Name; - } - - private static string GetDifferentiator(TaxonomyField field, ContentPart part) { - return field.Name; - } - protected override DriverResult Display(ContentPart part, TaxonomyField field, string displayType, dynamic shapeHelper) { - - return ContentShape("Fields_Contrib_TaxonomyField", GetDifferentiator(field, part), - () => { - var settings = field.PartFieldDefinition.Settings.GetModel(); - var terms = _taxonomyService.GetTermsForContentItem(part.ContentItem.Id, field.Name).ToList(); - var taxonomy = _taxonomyService.GetTaxonomyByName(settings.Taxonomy); - - return shapeHelper.Fields_Contrib_TaxonomyField( - ContentField: field, - Terms: terms, - Settings: settings, - Taxonomy: taxonomy); - }); - } - - protected override DriverResult Editor(ContentPart part, TaxonomyField field, dynamic shapeHelper) { - var settings = field.PartFieldDefinition.Settings.GetModel(); - - var appliedTerms = _taxonomyService.GetTermsForContentItem(part.ContentItem.Id, field.Name).ToDictionary(t => t.Id, t => t); - var taxonomy = _taxonomyService.GetTaxonomyByName(settings.Taxonomy); - var terms = _taxonomyService.GetTerms(taxonomy.Id).Select(t => t.CreateTermEntry()).ToList(); - - terms.ForEach(t => t.IsChecked = appliedTerms.ContainsKey(t.Id)); - - var viewModel = new TaxonomyFieldViewModel { - Name = field.Name, - Terms = terms, - Settings = settings, - SingleTermId = terms.Where(t => t.IsChecked).Select(t => t.Id).FirstOrDefault() - }; - - return ContentShape("Fields_Contrib_TaxonomyField_Edit", GetDifferentiator(field, part), - () => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: viewModel, Prefix: GetPrefix(field, part))); - } - - protected override DriverResult Editor(ContentPart part, TaxonomyField field, IUpdateModel updater, dynamic shapeHelper) { - var viewModel = new TaxonomyFieldViewModel { Terms = new List() }; - - if(updater.TryUpdateModel(viewModel, GetPrefix(field, part), null, null)) { - var checkedTerms = viewModel.Terms.Where(t => t.IsChecked || t.Id == viewModel.SingleTermId).Select(t => _taxonomyService.GetTerm(t.Id)).ToList(); - _taxonomyService.UpdateTerms(part.ContentItem, checkedTerms, field.Name); - } - - return Editor(part, field, shapeHelper); - } - - protected override void Exporting(ContentPart part, TaxonomyField field, ExportContentContext context) { - var appliedTerms = _taxonomyService.GetTermsForContentItem(part.ContentItem.Id, field.Name); - - // stores all content items associated to this field - var termIdentities = appliedTerms.Select(x => Services.ContentManager.GetItemMetadata(x).Identity.ToString()) - .ToArray(); - - context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Terms", String.Join(",", termIdentities)); - } - - protected override void Importing(ContentPart part, TaxonomyField field, ImportContentContext context) { - var termIdentities = context.Attribute(field.FieldDefinition.Name + "." + field.Name, "Terms"); - if (termIdentities == null) { - return; - } - - var terms = new List(); - - foreach (var identity in termIdentities.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { - var contentItem = context.GetItemFromSession(identity); - - if (contentItem == null) { - continue; - } - - terms.Add(contentItem); - } - - _taxonomyService.UpdateTerms(part.ContentItem, terms.Select(x => x.As()), field.Name); - } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyMenuItemPartDriver.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyMenuItemPartDriver.cs deleted file mode 100644 index e4b9257f6..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyMenuItemPartDriver.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Drivers; -using Contrib.Taxonomies.Models; -using Orchard.ContentManagement.Handlers; -using Orchard.Environment.Extensions; -using Orchard.Localization; - -namespace Contrib.Taxonomies.Drivers { - [OrchardFeature("TaxonomyMenuItem")] - public class TaxonomyMenuItemPartDriver : ContentPartDriver { - - public TaxonomyMenuItemPartDriver() { - T = NullLocalizer.Instance; - } - - Localizer T { get; set; } - - protected override string Prefix { get { return "TaxonomyMenuItemPart"; } } - - protected override DriverResult Editor(TaxonomyMenuItemPart part, dynamic shapeHelper) { - return ContentShape("Parts_Taxonomies_TaxonomyMenuItem_Edit", - () => shapeHelper.EditorTemplate(TemplateName: "Parts/Taxonomies.TaxonomyMenuItem", Model: part, Prefix: Prefix)); - } - - protected override DriverResult Editor(TaxonomyMenuItemPart menuItemPart, IUpdateModel updater, dynamic shapeHelper) { - updater.TryUpdateModel(menuItemPart, Prefix, null, null); - if(menuItemPart.RenderMenuItem) { - if(String.IsNullOrWhiteSpace(menuItemPart.Name)) { - updater.AddModelError("Name", T("Menu item name is required")); - } - - if (String.IsNullOrWhiteSpace(menuItemPart.Position)) { - menuItemPart.Position = "0"; - } - } - - return Editor(menuItemPart, shapeHelper); - } - - protected override void Exporting(TaxonomyMenuItemPart part, ExportContentContext context) { - context.Element(part.PartDefinition.Name).SetAttributeValue("Name", part.Record.Name); - context.Element(part.PartDefinition.Name).SetAttributeValue("Position", part.Record.Position); - context.Element(part.PartDefinition.Name).SetAttributeValue("RenderMenuItem", part.Record.RenderMenuItem); - } - - protected override void Importing(TaxonomyMenuItemPart part, ImportContentContext context) { - part.Record.Name = context.Attribute(part.PartDefinition.Name, "Name"); - part.Record.Position = context.Attribute(part.PartDefinition.Name, "Position"); - part.Record.RenderMenuItem = Boolean.Parse(context.Attribute(part.PartDefinition.Name, "RenderMenuItem")); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyMenuPartDriver.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyMenuPartDriver.cs deleted file mode 100644 index 97085764e..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyMenuPartDriver.cs +++ /dev/null @@ -1,195 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web.Mvc; -using Contrib.Taxonomies.Helpers; -using Contrib.Taxonomies.Models; -using Contrib.Taxonomies.Services; -using Contrib.Taxonomies.ViewModels; -using JetBrains.Annotations; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Drivers; -using Orchard.ContentManagement.Handlers; - -namespace Contrib.Taxonomies.Drivers { - [UsedImplicitly] - public class TaxonomyMenuPartDriver : ContentPartDriver { - private readonly ITaxonomyService _taxonomyService; - private readonly IContentManager _contentManager; - - public TaxonomyMenuPartDriver(ITaxonomyService taxonomyService, IContentManager contentManager) { - _taxonomyService = taxonomyService; - _contentManager = contentManager; - } - - protected override string Prefix { get { return "TaxonomyMenu"; } } - - protected override DriverResult Display(TaxonomyMenuPart part, string displayType, dynamic shapeHelper) { - return ContentShape("Parts_Taxonomies_Menu", - () => { - var taxonomy = _taxonomyService.GetTaxonomy(part.TaxonomyPartRecord.Id); - var terms = new List(); - if (taxonomy != null) { - var allTerms = _taxonomyService.GetTerms(taxonomy.Id).Select((t, i) => new { Level = t.GetLevels(), Term = t, Index = i }).ToList(); - - int index = 0, minLevel = 0, maxLevel = int.MaxValue - 1; - // display only a subset ? - if (part.TermPartRecord != null) { - index = allTerms.Where(t => t.Term.Id == part.TermPartRecord.Id).Single().Index; - minLevel = allTerms[index].Level; - } - - if (part.LevelsToDisplay != 0) { - maxLevel = minLevel + part.LevelsToDisplay - 1; - } - - // ignore top term ? - if (part.TermPartRecord != null && !part.DisplayTopMenuItem && allTerms.Any()) - { - minLevel++; - maxLevel++; - } - else - { - // don't add it if it should be hidden - if (!part.HideEmptyTerms || allTerms[index].Term.Count > 0) - { - terms.Add(allTerms[index].Term); - } - - if (part.DisplayTopMenuItem) - { - minLevel++; - } - } - - for (index++; index < allTerms.Count; index++) { - var indexed = allTerms[index]; - // ignore deep terms - if (indexed.Level > maxLevel) { - continue; - } - - // stop looping when reached another branch - if (indexed.Level < minLevel) { - break; - } - - if (part.HideEmptyTerms && indexed.Term.Count == 0) { - continue; - } - - terms.Add(indexed.Term); - } - } - - return shapeHelper.Parts_Taxonomies_Menu(ContentPart: part, Terms: terms, Taxonomy: taxonomy); - }); - } - - protected override DriverResult Editor(TaxonomyMenuPart part, dynamic shapeHelper) { - return Editor(part, null, shapeHelper); - } - - protected override DriverResult Editor(TaxonomyMenuPart part, IUpdateModel updater, dynamic shapeHelper) { - return ContentShape( - "Parts_Taxonomies_Menu_Edit", () => { - var model = new TaxonomyMenuViewModel { - SelectedTaxonomyId = part.TaxonomyPartRecord != null ? part.TaxonomyPartRecord.Id : -1, - SelectedTermId = part.TermPartRecord != null ? part.TermPartRecord.Id : -1, - DisplayContentCount = part.DisplayContentCount, - DisplayTopMenuItem = part.DisplayTopMenuItem, - HideEmptyTerms = part.HideEmptyTerms, - LevelsToDisplay = part.LevelsToDisplay - }; - - if (updater != null) { - if (updater.TryUpdateModel(model, Prefix, null, null)) { - var selectedTerm = _taxonomyService.GetTerm(model.SelectedTermId); - - // taxonomy to render - part.TaxonomyPartRecord = _taxonomyService.GetTaxonomy(model.SelectedTaxonomyId).Record; - // root term (can be null) - part.TermPartRecord = selectedTerm == null ? null : selectedTerm.Record; - part.DisplayContentCount = model.DisplayContentCount; - part.DisplayTopMenuItem = model.DisplayTopMenuItem; - part.HideEmptyTerms = model.HideEmptyTerms; - part.LevelsToDisplay = model.LevelsToDisplay; - } - } - - var taxonomies = _taxonomyService.GetTaxonomies(); - - var listItems = taxonomies.Select(taxonomy => new SelectListItem { - Value = Convert.ToString(taxonomy.Id), - Text = taxonomy.Name, - Selected = taxonomy.Record == part.TaxonomyPartRecord, - }).ToList(); - - model.AvailableTaxonomies = new SelectList(listItems, "Value", "Text", model.SelectedTaxonomyId); - - // if no taxonomy is selected, take the first available one as - // the terms drop down needs one by default - if(model.SelectedTaxonomyId == -1) { - var firstTaxonomy = taxonomies.FirstOrDefault(); - if(firstTaxonomy != null) { - model.SelectedTaxonomyId = firstTaxonomy.Id; - } - } - - return shapeHelper.EditorTemplate(TemplateName: "Parts/Taxonomies.Menu", Model: model, Prefix: Prefix); - }); - } - - protected override void Exporting(TaxonomyMenuPart part, ExportContentContext context) { - context.Element(part.PartDefinition.Name).SetAttributeValue("DisplayTopMenuItem", part.DisplayTopMenuItem); - context.Element(part.PartDefinition.Name).SetAttributeValue("DisplayContentCount", part.DisplayContentCount); - context.Element(part.PartDefinition.Name).SetAttributeValue("LevelsToDisplay", part.LevelsToDisplay); - context.Element(part.PartDefinition.Name).SetAttributeValue("HideEmptyTerms", part.HideEmptyTerms); - - if (part.TaxonomyPartRecord != null) { - var taxonomy = _taxonomyService.GetTaxonomy(part.TaxonomyPartRecord.Id); - context.Element(part.PartDefinition.Name).SetAttributeValue("TaxonomyPartRecordId", _contentManager.GetItemMetadata(taxonomy).Identity); - } - if (part.TermPartRecord != null) { - var term = _taxonomyService.GetTerm(part.TermPartRecord.Id); - context.Element(part.PartDefinition.Name).SetAttributeValue("TermPartRecordId", _contentManager.GetItemMetadata(term).Identity); - } - } - - protected override void Importing(TaxonomyMenuPart part, ImportContentContext context) { - var partName = part.PartDefinition.Name; - - part.DisplayTopMenuItem = GetAttribute(context, partName, "DisplayTopMenuItem"); - part.DisplayContentCount = GetAttribute(context, partName, "DisplayContentCount"); - part.LevelsToDisplay = GetAttribute(context, partName, "LevelsToDisplay"); - part.HideEmptyTerms = GetAttribute(context, partName, "HideEmptyTerms"); - } - - protected override void Imported(TaxonomyMenuPart part, ImportContentContext context) { - var taxonomyId = GetAttribute(context, part.PartDefinition.Name, "TaxonomyPartRecordId"); - if (!string.IsNullOrWhiteSpace(taxonomyId)) { - var taxonomy = context.GetItemFromSession(taxonomyId); - if (taxonomy != null) { - part.TaxonomyPartRecord = taxonomy.As().Record; - } - } - - var termId = GetAttribute(context, part.PartDefinition.Name, "TermPartRecordId"); - if (!string.IsNullOrWhiteSpace(termId)) { - var term = context.GetItemFromSession(termId); - if (term != null) { - part.TermPartRecord = term.As().Record; - } - } - } - - public static T GetAttribute(ImportContentContext context, string partName, string elementName) { - string value = context.Attribute(partName, elementName); - if (value != null) { - return (T)Convert.ChangeType(value, typeof(T)); - } - return default(T); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyPartDriver.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyPartDriver.cs deleted file mode 100644 index 628eca6e3..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TaxonomyPartDriver.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Contrib.Taxonomies.Services; -using Orchard.ContentManagement.Handlers; -using Orchard.ContentManagement.Drivers; -using Contrib.Taxonomies.Models; -using Orchard.Localization; - -namespace Contrib.Taxonomies.Drivers { - public class TaxonomyPartDriver : ContentPartDriver { - private readonly ITaxonomyService _taxonomyService; - - public TaxonomyPartDriver(ITaxonomyService taxonomyService) { - _taxonomyService = taxonomyService; - } - - protected override string Prefix { get { return "Taxonomy"; } } - public Localizer T { get; set; } - - protected override DriverResult Editor(TaxonomyPart part, Orchard.ContentManagement.IUpdateModel updater, dynamic shapeHelper) { - TaxonomyPart existing = _taxonomyService.GetTaxonomyByName(part.Name); - - if (existing != null && existing.Record != part.Record) { - updater.AddModelError("Title", T("A taxonomy with the same name already exists")); - } - - // nothing to display for this part - return null; - } - - protected override void Exporting(TaxonomyPart part, ExportContentContext context) { - context.Element(part.PartDefinition.Name).SetAttributeValue("TermTypeName", part.TermTypeName); - } - - protected override void Importing(TaxonomyPart part, ImportContentContext context) { - part.TermTypeName = context.Attribute(part.PartDefinition.Name, "TermTypeName"); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TermPartDriver.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TermPartDriver.cs deleted file mode 100644 index e46e75988..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TermPartDriver.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Collections.Generic; -using Contrib.Taxonomies.Routing; -using Orchard; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Aspects; -using Orchard.ContentManagement.Drivers; -using Contrib.Taxonomies.Models; -using Contrib.Taxonomies.Services; -using Orchard.ContentManagement.Handlers; -using Orchard.Localization; - -namespace Contrib.Taxonomies.Drivers { - public class TermPartDriver : ContentPartDriver { - - private readonly ITaxonomyService _taxonomyService; - private readonly IContentManager _contentManager; - private readonly ITermPathConstraint _termPathConstraint; - - public TermPartDriver( - ITaxonomyService taxonomyService, - IContentManager contentManager, - ITermPathConstraint termPathConstraint ) { - _taxonomyService = taxonomyService; - _contentManager = contentManager; - _termPathConstraint = termPathConstraint; - T = NullLocalizer.Instance; - } - - Localizer T { get; set; } - - protected override string Prefix { get { return "Term"; } } - - protected override DriverResult Editor(TermPart part, dynamic shapeHelper) { - return ContentShape("Parts_Taxonomies_Term_Fields", - () => shapeHelper.EditorTemplate(TemplateName: "Parts/Taxonomies.Term.Fields", Model: part, Prefix: Prefix)); - } - - protected override DriverResult Editor(TermPart termPart, IUpdateModel updater, dynamic shapeHelper) { - if (updater.TryUpdateModel(termPart, Prefix, null, null)) { - var existing = _taxonomyService.GetTermByName(termPart.TaxonomyId, termPart.Name); - if (existing != null && existing.Record != termPart.Record && existing.Container.ContentItem.Record == termPart.Container.ContentItem.Record) { - updater.AddModelError("Name", T("The term {0} already exists at this level", termPart.Name)); - } - } - - return Editor(termPart, shapeHelper); - } - - protected override void Exporting(TermPart part, ExportContentContext context) { - context.Element(part.PartDefinition.Name).SetAttributeValue("Count", part.Record.Count); - context.Element(part.PartDefinition.Name).SetAttributeValue("Selectable", part.Record.Selectable); - context.Element(part.PartDefinition.Name).SetAttributeValue("Weight", part.Record.Weight); - - var taxonomy = _contentManager.Get(part.Record.TaxonomyId); - var identity = _contentManager.GetItemMetadata(taxonomy).Identity.ToString(); - context.Element(part.PartDefinition.Name).SetAttributeValue("TaxonomyId", identity); - - var identityPaths = new List(); - foreach(string pathPart in part.Record.Path.Split('/')) { - if(String.IsNullOrEmpty(pathPart)) { - continue; - } - - var parent = _contentManager.Get(Int32.Parse(pathPart)); - identityPaths.Add(_contentManager.GetItemMetadata(parent).Identity.ToString()); - } - - context.Element(part.PartDefinition.Name).SetAttributeValue("Path", String.Join(",", identityPaths.ToArray())); - - } - - protected override void Importing(TermPart part, ImportContentContext context) { - part.Record.Count = Int32.Parse(context.Attribute(part.PartDefinition.Name, "Count")); - part.Record.Selectable = Boolean.Parse(context.Attribute(part.PartDefinition.Name, "Selectable")); - part.Record.Weight = Int32.Parse(context.Attribute(part.PartDefinition.Name, "Weight")); - - var identity = context.Attribute(part.PartDefinition.Name, "TaxonomyId"); - var contentItem = context.GetItemFromSession(identity); - - if (contentItem == null) { - throw new OrchardException(T("Unknown taxonomy: {0}", identity)); - } - - part.Record.TaxonomyId = contentItem.Id; - - - part.Record.Path = "/"; - foreach(var identityPath in context.Attribute(part.PartDefinition.Name, "Path").Split(new [] {','}, StringSplitOptions.RemoveEmptyEntries)) { - var pathContentItem = context.GetItemFromSession(identityPath); - part.Record.Path += pathContentItem.Id + "/"; - } - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TermWidgetPartDriver.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TermWidgetPartDriver.cs deleted file mode 100644 index b31039343..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TermWidgetPartDriver.cs +++ /dev/null @@ -1,168 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Web.Mvc; -using Contrib.Taxonomies.Models; -using Contrib.Taxonomies.Services; -using Contrib.Taxonomies.ViewModels; -using Orchard; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Drivers; -using Orchard.ContentManagement.Handlers; -using Orchard.ContentManagement.MetaData; -using Orchard.Core.Common.Models; -using Orchard.Localization; - -namespace Contrib.Taxonomies.Drivers { - public class TermWidgetPartDriver : ContentPartDriver { - private readonly IContentManager _contentManager; - private readonly ITaxonomyService _taxonomyService; - private readonly IContentDefinitionManager _contentDefinitionManager; - - public TermWidgetPartDriver( - IContentManager contentManager, - ITaxonomyService taxonomyService, - IContentDefinitionManager contentDefinitionManager) { - _contentManager = contentManager; - _taxonomyService = taxonomyService; - _contentDefinitionManager = contentDefinitionManager; - - T = NullLocalizer.Instance; - } - - Localizer T { get; set; } - - protected override DriverResult Display(TermWidgetPart part, string displayType, dynamic shapeHelper) { - return ContentShape("Parts_TermWidget_List", - () => { - var termPart = _taxonomyService.GetTerm(part.TermPartRecord.Id); - var query = _taxonomyService.GetContentItemsQuery(termPart, part.FieldName); - - Expression> orderBy = d => d.CreatedUtc; - switch(part.OrderBy) { - case "Created": orderBy = d => d.CreatedUtc; break; - case "Published": orderBy = d => d.PublishedUtc; break; - case "Modified": orderBy = d => d.ModifiedUtc; break; - } - - var results = query.Join().OrderByDescending(orderBy); - - if(!String.IsNullOrWhiteSpace(part.ContentType)) { - results = results.Where(x => x.ContentItemRecord.ContentType.Name == part.ContentType); - } - - // build the Summary display for each content item - var list = shapeHelper.List(); - list.AddRange( - results - .Slice(0, part.Count) - .ToList() - .Select( tp => _contentManager.BuildDisplay(tp.ContentItem, "Summary")) - ); - - return shapeHelper.Parts_TermWidget_List(ContentPart: part, ContentItems: list); - }); - } - - protected override DriverResult Editor(TermWidgetPart part, dynamic shapeHelper) { - return Editor(part, null, shapeHelper); - } - - protected override DriverResult Editor(TermWidgetPart part, IUpdateModel updater, dynamic shapeHelper) { - var viewModel = new TermWidgetViewModel { - Part = part, - ContentTypeNames = GetContentTypes(), - Count = part.Count, - FieldName = part.FieldName, - OrderBy = part.OrderBy, - SelectedTaxonomyId = part.TaxonomyPartRecord != null ? part.TaxonomyPartRecord.Id : -1, - SelectedTermId = part.TermPartRecord != null ? part.TermPartRecord.Id : -1 - }; - - if(updater != null) { - if (updater.TryUpdateModel(viewModel, Prefix, null, null)) { - var selectedTerm = _taxonomyService.GetTerm(viewModel.SelectedTermId); - - // taxonomy to render - part.TaxonomyPartRecord = _taxonomyService.GetTaxonomy(viewModel.SelectedTaxonomyId).Record; - // root term (can be null) - part.TermPartRecord = selectedTerm == null ? null : selectedTerm.Record; - part.FieldName = viewModel.FieldName; - part.Count = viewModel.Count; - part.OrderBy = viewModel.OrderBy; - } - } - - var taxonomies = _taxonomyService.GetTaxonomies(); - - var listItems = taxonomies.Select(taxonomy => new SelectListItem { - Value = Convert.ToString(taxonomy.Id), - Text = taxonomy.Name, - Selected = taxonomy.Record == part.TaxonomyPartRecord, - }).ToList(); - - viewModel.AvailableTaxonomies = new SelectList(listItems, "Value", "Text", viewModel.SelectedTaxonomyId); - - // if no taxonomy is selected, take the first available one as - // the terms drop down needs one by default - if (viewModel.SelectedTaxonomyId == -1) { - var firstTaxonomy = taxonomies.FirstOrDefault(); - if (firstTaxonomy != null) { - viewModel.SelectedTaxonomyId = firstTaxonomy.Id; - } - } - - return ContentShape("Parts_Taxonomy_TermWidget_Edit", () => shapeHelper.EditorTemplate(TemplateName: "Parts/Taxonomies.TermWidget", Model: viewModel, Prefix: Prefix)); - } - - private IEnumerable GetContentTypes() - { - return _contentDefinitionManager - .ListTypeDefinitions() - .Select(t => t.Name) - .OrderBy(x => x); - } - - protected override void Importing(TermWidgetPart part, ImportContentContext context) { - // importing taxonomy - var taxonomyIdentity = context.Attribute(part.PartDefinition.Name, "TaxonomyId"); - var taxonomy = context.GetItemFromSession(taxonomyIdentity); - - if (taxonomy == null) { - throw new OrchardException(T("Unknown taxonomy: {0}", taxonomyIdentity)); - } - - part.TaxonomyPartRecord = taxonomy.As().Record; - - //importing term - var termIdentity = context.Attribute(part.PartDefinition.Name, "TermId"); - var term = context.GetItemFromSession(termIdentity); - - part.TermPartRecord = term.As().Record; - - if (term == null) { - throw new OrchardException(T("Unknown term: {0}", termIdentity)); - } - - // importing properties - part.FieldName = context.Attribute(part.PartDefinition.Name, "FieldName"); - part.Count = Int32.Parse(context.Attribute(part.PartDefinition.Name, "Count")); - part.OrderBy = context.Attribute(part.PartDefinition.Name, "OrderBy"); - } - - protected override void Exporting(TermWidgetPart part, ExportContentContext context) { - context.Element(part.PartDefinition.Name).SetAttributeValue("FieldName", part.FieldName); - context.Element(part.PartDefinition.Name).SetAttributeValue("Count", part.Count); - context.Element(part.PartDefinition.Name).SetAttributeValue("OrderBy", part.OrderBy); - - var taxonomy = _contentManager.Get(part.TaxonomyPartRecord.Id); - var taxonomyIdentity = _contentManager.GetItemMetadata(taxonomy).Identity.ToString(); - context.Element(part.PartDefinition.Name).SetAttributeValue("TaxonomyId", taxonomyIdentity); - - var term = _contentManager.Get(part.TermPartRecord.Id); - var termIdentity = _contentManager.GetItemMetadata(term).Identity.ToString(); - context.Element(part.PartDefinition.Name).SetAttributeValue("TermId", termIdentity); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TermsPartDriver.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TermsPartDriver.cs deleted file mode 100644 index 26c9fa480..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Drivers/TermsPartDriver.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Contrib.Taxonomies.Models; -using Orchard.ContentManagement.Drivers; - -namespace Contrib.Taxonomies.Drivers { - public class TermsPartDriver : ContentPartDriver { - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Fields/TaxonomyField.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Fields/TaxonomyField.cs deleted file mode 100644 index a5c0a7bec..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Fields/TaxonomyField.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using Contrib.Taxonomies.Models; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Utilities; - -namespace Contrib.Taxonomies.Fields { - /// - /// This field has not state, as all terms are saved using - /// - public class TaxonomyField : ContentField { - - public TaxonomyField() { - Terms = new LazyField>(); - } - - /// - /// Gets the Terms associated with this field - /// - public LazyField> Terms { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TaxonomyMenuItemPartHandler.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TaxonomyMenuItemPartHandler.cs deleted file mode 100644 index d705698bc..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TaxonomyMenuItemPartHandler.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Orchard.ContentManagement.Handlers; -using Orchard.Data; -using Contrib.Taxonomies.Models; -using Orchard.Environment.Extensions; - -namespace Contrib.Taxonomies.Handlers { - [OrchardFeature("TaxonomyMenuItem")] - public class TaxonomyMenuItemPartHandler : ContentHandler { - public TaxonomyMenuItemPartHandler(IRepository repository) { - Filters.Add(StorageFilter.For(repository)); - Filters.Add(new ActivatingFilter("Taxonomy")); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TaxonomyMenuPartHandler.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TaxonomyMenuPartHandler.cs deleted file mode 100644 index 290c3acaf..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TaxonomyMenuPartHandler.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Orchard.ContentManagement.Handlers; -using Orchard.Data; -using Contrib.Taxonomies.Models; - -namespace Contrib.Taxonomies.Handlers { - public class TaxonomyMenuPartHandler : ContentHandler { - public TaxonomyMenuPartHandler(IRepository repository) { - Filters.Add(StorageFilter.For(repository)); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TaxonomyPartHandler.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TaxonomyPartHandler.cs deleted file mode 100644 index f78e48a3f..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TaxonomyPartHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Contrib.Taxonomies.Routing; -using Contrib.Taxonomies.Services; -using JetBrains.Annotations; -using Contrib.Taxonomies.Models; -using Orchard.ContentManagement.Handlers; -using Orchard.Data; - -namespace Contrib.Taxonomies.Handlers { - [UsedImplicitly] - public class TaxonomyPartHandler : ContentHandler { - - public TaxonomyPartHandler( - IRepository repository, - ITaxonomySlugConstraint taxonomySlugConstraint, - ITaxonomyService taxonomyService - ) { - - Filters.Add(StorageFilter.For(repository)); - - OnPublished( - (context, part) => { - taxonomySlugConstraint.AddSlug(part.Slug); - taxonomyService.CreateTermContentType(part); - }); - - OnUnpublishing( - (context, part) => - taxonomySlugConstraint.RemoveSlug(part.Slug) - ); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TermPartHandler.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TermPartHandler.cs deleted file mode 100644 index f9d5aada4..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TermPartHandler.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Contrib.Taxonomies.Routing; -using Contrib.Taxonomies.Services; -using Contrib.Taxonomies.Models; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Handlers; -using Orchard.Data; - -namespace Contrib.Taxonomies.Handlers { - public class TermPartHandler : ContentHandler { - public TermPartHandler( - IRepository repository, - ITaxonomyService taxonomyService, - ITermPathConstraint termPathConstraint ) { - Filters.Add(StorageFilter.For(repository)); - - OnRemoved( - (context, tags) => - taxonomyService.DeleteAssociatedTerms(context.ContentItem) - ); - - OnInitializing( - (context, part) => - part.Selectable = true - ); - - OnPublished( - (context, part) => { - termPathConstraint.AddPath(part.Slug); - foreach (var child in taxonomyService.GetChildren(part)) { - termPathConstraint.AddPath(child.Slug); - } - }); - - OnUnpublishing( - (context, part) => - termPathConstraint.RemovePath(part.Slug) - ); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TermWidgetPartHandler.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TermWidgetPartHandler.cs deleted file mode 100644 index 86b3aa5b8..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TermWidgetPartHandler.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Contrib.Taxonomies.Models; -using Orchard.ContentManagement.Handlers; -using Orchard.Data; - -namespace Contrib.Taxonomies.Handlers { - public class TermWidgetPartHandler : ContentHandler { - public TermWidgetPartHandler(IRepository repository) { - Filters.Add(StorageFilter.For(repository)); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TermsPartHandler.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TermsPartHandler.cs deleted file mode 100644 index 8d7cfde27..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Handlers/TermsPartHandler.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Linq; -using Contrib.Taxonomies.Fields; -using Contrib.Taxonomies.Models; -using Contrib.Taxonomies.Services; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Handlers; -using Orchard.ContentManagement.MetaData; -using Orchard.Core.Title.Models; -using Orchard.Data; - -namespace Contrib.Taxonomies.Handlers { - public class TermsPartHandler : ContentHandler { - private readonly IContentDefinitionManager _contentDefinitionManager; - private readonly IContentManager _contentManager; - - public TermsPartHandler( - IContentDefinitionManager contentDefinitionManager, - IRepository repository, - ITaxonomyService taxonomyService, - IContentManager contentManager) { - _contentDefinitionManager = contentDefinitionManager; - _contentManager = contentManager; - - Filters.Add(StorageFilter.For(repository)); - - OnPublished((context, part) => RecalculateCount(contentManager, taxonomyService, part)); - OnUnpublished((context, part) => RecalculateCount(contentManager, taxonomyService, part)); - OnRemoved((context, part) => RecalculateCount(contentManager, taxonomyService, part)); - - // tells how to load the field terms on demand - OnLoaded((context, part) => { - foreach(var field in part.ContentItem.Parts.SelectMany(p => p.Fields).OfType()) { - var tempField = field.Name; - var fieldTermRecordIds = part.Record.Terms.Where(t => t.Field == tempField).Select(tci => tci.TermRecord.Id); - field.Terms.Loader(value => fieldTermRecordIds.Select(id => _contentManager.Get(id))); - } - }); - - OnIndexing( - (context, part) => { - foreach (var term in part.Terms) { - var value = context.ContentManager.Get(term.TermRecord.Id).As().Title; - context.DocumentIndex.Add(term.Field, value).Analyze(); - context.DocumentIndex.Add(term.Field + "-id", term.Id).Store(); - } - }); - } - - private static void RecalculateCount(IContentManager contentManager, ITaxonomyService taxonomyService, TermsPart part) { - // submits any change to the db so that GetContentItemsCount is accurate - contentManager.Flush(); - - foreach (var term in part.Terms) { - var termPart = taxonomyService.GetTerm(term.TermRecord.Id); - term.TermRecord.Count = (int)taxonomyService.GetContentItemsCount(termPart); - } - } - - protected override void Activating(ActivatingContentContext context) { - base.Activating(context); - - // weld the TermsPart dynamically, if a field has been assigned to one of its parts - var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(context.ContentType); - if (contentTypeDefinition == null) { - return; - } - - if (contentTypeDefinition.Parts.Any( - part => part.PartDefinition.Fields.Any( - field => field.FieldDefinition.Name == typeof(TaxonomyField).Name))) { - - context.Builder.Weld(); - } - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Helpers/PathExtensions.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Helpers/PathExtensions.cs deleted file mode 100644 index 88327b395..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Helpers/PathExtensions.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Contrib.Taxonomies.Models; -using System; -using Contrib.Taxonomies.ViewModels; -using System.Linq; - -namespace Contrib.Taxonomies.Helpers { - public static class TermExtensions { - public static int GetLevels(this TermPart term) { - return String.IsNullOrEmpty(term.Path) ? 0 : term.Path.Count( c => c == '/') - 1; - } - - public static int GetLevels(this TermEntry term) { - return String.IsNullOrEmpty(term.Path) ? 0 : term.Path.Count( c => c == '/') - 1; - } - - public static TermEntry CreateTermEntry(this TermPart term) { - return new TermEntry { - Id = term.Id, - Name = term.Name, - Selectable = term.Selectable, - Count = term.Count, - Path = term.Path, - Weight= term.Weight, - IsChecked = false, - ContentItem = term.ContentItem - }; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Helpers/PredicateBuilder.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Helpers/PredicateBuilder.cs deleted file mode 100644 index 62c374a46..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Helpers/PredicateBuilder.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; - -namespace Contrib.Taxonomies.Helpers -{ - using System; - using System.Linq; - using System.Linq.Expressions; - using System.Collections.Generic; - - public static class PredicateBuilder - { - public static Expression> True() { return f => true; } - public static Expression> False() { return f => false; } - - public static Expression> Or(this Expression> expr1, - Expression> expr2) - { - var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast()); - return Expression.Lambda> - (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters); - } - - public static Expression> And(this Expression> expr1, - Expression> expr2) - { - var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast()); - return Expression.Lambda> - (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Migrations.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Migrations.cs deleted file mode 100644 index 40dd60f53..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Migrations.cs +++ /dev/null @@ -1,99 +0,0 @@ -using Orchard.ContentManagement.MetaData; -using Orchard.Core.Contents.Extensions; -using Orchard.Data.Migration; - -namespace Contrib.Taxonomies { - public class Migrations : DataMigrationImpl { - - public int Create() { - SchemaBuilder.CreateTable("TaxonomyPartRecord", - table => table - .ContentPartRecord() - .Column("TermTypeName", column => column.WithLength(255)) - ); - - SchemaBuilder.CreateTable("TermPartRecord", - table => table - .ContentPartRecord() - .Column("Path", column => column.WithLength(255)) - .Column("TaxonomyId") - .Column("Count") - .Column("Weight") - .Column("Selectable") - ); - - SchemaBuilder.CreateTable("TermContentItem", - table => table - .Column("Id", column => column.PrimaryKey().Identity()) - .Column("Field", column => column.WithLength(50)) - .Column("TermRecord_id") - .Column("TermsPartRecord_id") - ); - - SchemaBuilder.CreateTable("TaxonomyMenuPartRecord", - table => table - .ContentPartRecord() - .Column("TaxonomyPartRecord_id") - .Column("TermPartRecord_id") - .Column("DisplayTopMenuItem") - .Column("LevelsToDisplay") - .Column("DisplayContentCount") - .Column("HideEmptyTerms") - ); - - ContentDefinitionManager.AlterTypeDefinition("Taxonomy", - cfg => cfg - .WithPart("TaxonomyPart") - .WithPart("CommonPart") - .WithPart("TitlePart") - .WithPart("AutoroutePart", builder => builder - .WithSetting("AutorouteSettings.AllowCustomPattern", "true") - .WithSetting("AutorouteSettings.AutomaticAdjustmentOnEdit", "false") - .WithSetting("AutorouteSettings.PatternDefinitions", "[{Name:'Title', Pattern: '{Content.Slug}', Description: 'my-taxonomy'}]") - .WithSetting("AutorouteSettings.DefaultPatternIndex", "0")) - ); - - ContentDefinitionManager.AlterTypeDefinition("TaxonomyMenu", - cfg => cfg - .WithPart("TaxonomyMenuPart") - .WithPart("CommonPart") - .WithPart("WidgetPart") - .WithSetting("Stereotype", "Widget") - ); - - SchemaBuilder.CreateTable("TaxonomyMenuItemPartRecord", - table => table - .ContentPartRecord() - .Column("RenderMenuItem") - .Column("Position", c => c.WithLength(30)) - .Column("Name", c => c.WithLength(255)) - ); - - SchemaBuilder.CreateTable("TermsPartRecord", - table => table - .ContentPartRecord() - ); - - SchemaBuilder.CreateTable("TermWidgetPartRecord", - table => table - .ContentPartRecord() - .Column("TaxonomyPartRecord_id") - .Column("TermPartRecord_id") - .Column("Count") - .Column("OrderBy") - .Column("FieldName") - .Column("ContentType", c => c.Nullable()) - ); - - ContentDefinitionManager.AlterTypeDefinition("TermWidget", - cfg => cfg - .WithPart("TermWidgetPart") - .WithPart("CommonPart") - .WithPart("WidgetPart") - .WithSetting("Stereotype", "Widget") - ); - - return 10; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuItemPart.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuItemPart.cs deleted file mode 100644 index bf0a859d1..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuItemPart.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Orchard.ContentManagement; - -namespace Contrib.Taxonomies.Models { - public class TaxonomyMenuItemPart : ContentPart { - public bool RenderMenuItem { - get { return Record.RenderMenuItem; } - set { Record.RenderMenuItem = value; } - } - - [StringLength(30)] - public string Position { - get { return Record.Position; } - set { Record.Position = value; } - } - - [StringLength(255)] - public string Name { - get { return Record.Name; } - set { Record.Name = value; } - } - - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuItemPartRecord.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuItemPartRecord.cs deleted file mode 100644 index 152e02736..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuItemPartRecord.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Orchard.ContentManagement.Records; - -namespace Contrib.Taxonomies.Models { - public class TaxonomyMenuItemPartRecord : ContentPartRecord { - public virtual bool RenderMenuItem { get; set; } - public virtual string Position { get; set; } - public virtual string Name { get; set; } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuPart.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuPart.cs deleted file mode 100644 index a62adf5b7..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuPart.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Orchard.ContentManagement; - -namespace Contrib.Taxonomies.Models { - /// - /// Represents the part for the Taxonomy Menu Widget - /// - public class TaxonomyMenuPart : ContentPart { - - /// - /// The taxonomy to display - /// - - [Required] - public TaxonomyPartRecord TaxonomyPartRecord { - get { return Record.TaxonomyPartRecord; } - set { Record.TaxonomyPartRecord = value; } - } - - /// - /// Top term to display in the menu. - /// If null, the taxonomy is supposed to be the top term. - /// - public TermPartRecord TermPartRecord { - get { return Record.TermPartRecord; } - set { Record.TermPartRecord = value; } - } - - /// - /// Whether to display the root node or not. - /// If False, the menu will have a flat first level. - /// - public bool DisplayTopMenuItem { - get { return Record.DisplayTopMenuItem; } - set { Record.DisplayTopMenuItem = value; } - } - - /// - /// How many sub-levels to display. - /// If 0, then there will be only one level displayed (default) - /// - public int LevelsToDisplay { - get { return Record.LevelsToDisplay; } - set { Record.LevelsToDisplay = value; } - } - - /// - /// Whether to display the number of content items - /// associated with this term, in the generated menu item text - /// - public bool DisplayContentCount { - get { return Record.DisplayContentCount; } - set { Record.DisplayContentCount = value; } - } - - /// - /// Whether to hide the terms without any associated content - /// - public bool HideEmptyTerms { - get { return Record.HideEmptyTerms; } - set { Record.HideEmptyTerms = value; } - } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuPartRecord.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuPartRecord.cs deleted file mode 100644 index 7ccac5169..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyMenuPartRecord.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Orchard.ContentManagement.Records; - -namespace Contrib.Taxonomies.Models { - /// - /// Contains the properties for the Taxonomy Menu Widget - /// - public class TaxonomyMenuPartRecord : ContentPartRecord { - public virtual TaxonomyPartRecord TaxonomyPartRecord { get; set; } - public virtual TermPartRecord TermPartRecord { get; set; } - public virtual bool DisplayTopMenuItem { get; set; } - public virtual int LevelsToDisplay { get; set; } - public virtual bool DisplayContentCount { get; set; } - public virtual bool HideEmptyTerms { get; set; } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyPart.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyPart.cs deleted file mode 100644 index 21ca9c0f0..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyPart.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Orchard.Autoroute.Models; -using Orchard.ContentManagement; -using Orchard.Core.Title.Models; - -namespace Contrib.Taxonomies.Models { - public class TaxonomyPart : ContentPart { - public string Name { - get { return this.As().Title; } - set { this.As().Title = value; } - } - - public string Slug { - get { return this.As().DisplayAlias; } - set { this.As().DisplayAlias = value; } - } - - public string TermTypeName { - get { return Record.TermTypeName; } - set { Record.TermTypeName = value; } - } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyPartRecord.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyPartRecord.cs deleted file mode 100644 index d6e7ce434..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TaxonomyPartRecord.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Orchard.ContentManagement.Records; - -namespace Contrib.Taxonomies.Models { - public class TaxonomyPartRecord : ContentPartRecord { - public virtual string TermTypeName { get; set; } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermContentItem.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermContentItem.cs deleted file mode 100644 index 4c002e63c..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermContentItem.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Orchard.Data.Conventions; - -namespace Contrib.Taxonomies.Models { - /// - /// Represents a relationship between a Term and a Content Item - /// - public class TermContentItem { - public virtual int Id { get; set; } - public virtual string Field { get; set; } - - public virtual TermPartRecord TermRecord { get; set; } - - [CascadeAllDeleteOrphan] - public virtual TermsPartRecord TermsPartRecord { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermPart.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermPart.cs deleted file mode 100644 index 661cbbf66..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermPart.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using Orchard.Autoroute.Models; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Aspects; -using Orchard.Core.Title.Models; - -namespace Contrib.Taxonomies.Models { - public class TermPart : ContentPart, IComparable { - public string Name { - get { return this.As().Title; } - set { this.As().Title = value; } - } - - public string Slug { - get { return this.As().DisplayAlias; } - set { this.As().DisplayAlias = value; } - } - - public IContent Container { - get { return this.As().Container; } - set { this.As().Container = value; } - } - - public int TaxonomyId { - get { return Record.TaxonomyId; } - set { Record.TaxonomyId = value; } - } - - /// - /// e.g., /; /1/; /1/2/ - /// - public string Path { - get { return Record.Path; } - set { Record.Path = value; } - } - - public int Count { - get { return Record.Count; } - set { Record.Count = value; } - } - - public bool Selectable { - get { return Record.Selectable; } - set { Record.Selectable = value; } - } - - public int Weight { - get { return Record.Weight; } - set { Record.Weight = value; } - } - - public string FullPath { get { return String.Concat(Path, Id); } } - - #region IComparable Members - - public int CompareTo(TermPart other) { - if(other.Path == this.Path) { - var weight = Weight.CompareTo(other.Weight); - - if(weight != 0) { - return weight; - } - // if same weight, compare by name - return this.Name.CompareTo(other.Name); - } - - return FullPath.CompareTo(other.FullPath); - } - - #endregion - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermPartRecord.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermPartRecord.cs deleted file mode 100644 index 7f95d32f4..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermPartRecord.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using Orchard.ContentManagement.Records; -namespace Contrib.Taxonomies.Models { - /// - /// Represents a Term of a Taxonomy - /// - public class TermPartRecord : ContentPartRecord { - public virtual int TaxonomyId { get; set; } - - public virtual string Path { get; set; } - public virtual int Count { get; set; } - public virtual bool Selectable { get; set; } - public virtual int Weight { get; set; } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermWidgetPart.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermWidgetPart.cs deleted file mode 100644 index b972a12c1..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermWidgetPart.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Orchard.ContentManagement; - -namespace Contrib.Taxonomies.Models { - public class TermWidgetPart : ContentPart { - /// - /// The taxonomy to display - /// - - public TaxonomyPartRecord TaxonomyPartRecord { - get { return Record.TaxonomyPartRecord; } - set { Record.TaxonomyPartRecord = value; } - } - - public TermPartRecord TermPartRecord { - get { return Record.TermPartRecord; } - set { Record.TermPartRecord = value; } - } - - [Range(1, int.MaxValue)] - public int Count { - get { return Record.Count; } - set { Record.Count = value; } - } - - public string OrderBy { - get { return Record.OrderBy; } - set { Record.OrderBy = value; } - } - - public string FieldName { - get { return Record.FieldName; } - set { Record.FieldName = value; } - } - - public string ContentType { - get { return Record.ContentType; } - set { Record.ContentType = value; } - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermWidgetPartRecord.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermWidgetPartRecord.cs deleted file mode 100644 index f61994ee0..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermWidgetPartRecord.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Orchard.ContentManagement.Records; - -namespace Contrib.Taxonomies.Models { - public class TermWidgetPartRecord : ContentPartRecord { - public TermWidgetPartRecord() { - Count = 10; - } - - public virtual TaxonomyPartRecord TaxonomyPartRecord { get; set; } - public virtual TermPartRecord TermPartRecord { get; set; } - - public virtual int Count { get; set; } - public virtual string OrderBy { get; set; } - - public virtual string FieldName { get; set; } - public virtual string ContentType { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermsPart.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermsPart.cs deleted file mode 100644 index df92f343f..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermsPart.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Collections.Generic; -using Orchard.ContentManagement; - -namespace Contrib.Taxonomies.Models { - /// - /// This Content Part is used to create a link to TermContentItem records, so - /// that the Content Manager can query them. It will be attached dynamically whenever - /// a TaxonomyField is found on a Content Type - /// - public class TermsPart : ContentPart { - public IList Terms { get { return Record.Terms; } } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermsPartRecord.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermsPartRecord.cs deleted file mode 100644 index 2b2cd33b0..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Models/TermsPartRecord.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using Orchard.ContentManagement.Records; -using Orchard.Data.Conventions; - -namespace Contrib.Taxonomies.Models { - public class TermsPartRecord : ContentPartRecord { - public TermsPartRecord() { - Terms = new List(); - } - - [CascadeAllDeleteOrphan] - public virtual IList Terms { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Module.txt b/src/Orchard.Web/Modules/Contrib.Taxonomies/Module.txt deleted file mode 100644 index d229bc2b7..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Module.txt +++ /dev/null @@ -1,18 +0,0 @@ -Name: Taxonomies -AntiForgery: enabled -Author: Sébastien Ros -Website: http://orchardtaxonomies.codeplex.com -Version: 1.4 -OrchardVersion: 1.4 -Description: The taxonomy module is providing custom categorization of arbitrary content types. -Features: - Contrib.Taxonomies: - Name: Taxonomies - Description: Categorize a content item. - Category: Content - Dependencies: Orchard.Autoroute, Title - TaxonomyMenuItem: - Name: Taxonomy Main Menu - Description: Displays Taxonomies on main menu. - Category: Navigation - Dependencies: Contrib.Taxonomies \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Permissions.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Permissions.cs deleted file mode 100644 index f59347d62..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Permissions.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Orchard.Environment.Extensions.Models; -using Orchard.Security.Permissions; - -namespace Contrib.Taxonomies { - public class Permissions : IPermissionProvider { - public static readonly Permission ManageTaxonomies = new Permission { Description = "Manage taxonomies", Name = "ManageTaxonomies" }; - public static readonly Permission CreateTaxonomy = new Permission { Description = "Create taxonomy", Name = "CreateTaxonomy", ImpliedBy = new[] { ManageTaxonomies } }; - public static readonly Permission ManageTerms = new Permission { Description = "Manage terms", Name = "ManageTerms", ImpliedBy = new[] { CreateTaxonomy } }; - public static readonly Permission CreateTerm = new Permission { Description = "Create term", Name = "CreateTerm", ImpliedBy = new[] { ManageTerms } }; - - public virtual Feature Feature { get; set; } - - public IEnumerable GetPermissions() { - return new[] { - ManageTaxonomies, - CreateTaxonomy - }; - } - - public IEnumerable GetDefaultStereotypes() { - return new[] { - new PermissionStereotype { - Name = "Administrator", - Permissions = new[] {ManageTaxonomies} - }, - new PermissionStereotype { - Name = "Editor", - Permissions = new[] {ManageTaxonomies} - }, - new PermissionStereotype { - Name = "Moderator", - Permissions = new[] {ManageTaxonomies} - }, - new PermissionStereotype { - Name = "Author", - Permissions = new[] {CreateTaxonomy} - }, - new PermissionStereotype { - Name = "Contributor", - Permissions = new Permission[0] - }, - }; - } - - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Placement.info b/src/Orchard.Web/Modules/Contrib.Taxonomies/Placement.info deleted file mode 100644 index c175ea022..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Placement.info +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Projections/TermsFilter.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Projections/TermsFilter.cs deleted file mode 100644 index 88feb163b..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Projections/TermsFilter.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Contrib.Taxonomies.Models; -using Contrib.Taxonomies.Services; -using Orchard.ContentManagement; -using Orchard.Events; -using Orchard.Localization; - -namespace Contrib.Taxonomies.Projections { - public interface IFilterProvider : IEventHandler { - void Describe(dynamic describe); - } - - public class TermsFilter : IFilterProvider { - private readonly ITaxonomyService _taxonomyService; - - public TermsFilter(ITaxonomyService taxonomyService) { - _taxonomyService = taxonomyService; - T = NullLocalizer.Instance; - } - - public Localizer T { get; set; } - - public void Describe(dynamic describe) { - describe.For("Taxonomy", T("Taxonomy"), T("Taxonomy")) - .Element("HasTerms", T("Has Terms"), T("Categorized content items"), - (Action)ApplyFilter, - (Func)DisplayFilter, - "SelectTerms" - ); - } - - public void ApplyFilter(dynamic context) { - string termIds = Convert.ToString(context.State.TermIds); - if (!String.IsNullOrEmpty(termIds)) { - var ids = termIds.Split(new[] { ',' }).Select(Int32.Parse).ToArray(); - - if (ids.Length == 0) { - return; - } - - var terms = ids.Select(_taxonomyService.GetTerm).ToList(); - - var predicates = new List>(); - - foreach(var term in terms) { - var localTerm = term; - Action ors = x => x.Or(a => a.Eq("Id", ids.First()), b => b.Like("Path", localTerm.FullPath + "/", HqlMatchMode.Start)); - predicates.Add(ors); - } - - Action selector = alias => alias.ContentPartRecord().Property("Terms", "terms").Property("TermRecord", "termRecord"); - Action filter = x => x.Conjunction(predicates.Take(1).Single(), predicates.Skip(1).ToArray()); - context.Query.Where(selector, filter); - } - } - - public LocalizedString DisplayFilter(dynamic context) { - string terms = Convert.ToString(context.State.TermIds); - - if (String.IsNullOrEmpty(terms)) { - return T("Any term"); - } - - var tagNames = terms.Split(new[] { ',' }).Select(x => _taxonomyService.GetTerm(Int32.Parse(x)).Name); - - return T("Categorized with {0}", String.Join(", ", tagNames)); - } - } - -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Projections/TermsFilterForms.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Projections/TermsFilterForms.cs deleted file mode 100644 index 99b87de60..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Projections/TermsFilterForms.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Web.Mvc; -using Contrib.Taxonomies.Helpers; -using Contrib.Taxonomies.Services; -using Orchard.DisplayManagement; -using Orchard.Events; -using Orchard.Localization; - -namespace Contrib.Taxonomies.Projections { - public interface IFormProvider : IEventHandler { - void Describe(dynamic context); - } - - public class TermsFilterForms : IFormProvider { - private readonly ITaxonomyService _taxonomyService; - protected dynamic Shape { get; set; } - public Localizer T { get; set; } - - public TermsFilterForms( - IShapeFactory shapeFactory, - ITaxonomyService taxonomyService) { - _taxonomyService = taxonomyService; - Shape = shapeFactory; - T = NullLocalizer.Instance; - } - - public void Describe(dynamic context) { - Func form = - shape => { - - var f = Shape.Form( - Id: "SelectTerms", - _Terms: Shape.SelectList( - Id: "termids", Name: "TermIds", - Title: T("Terms"), - Description: T("Select some terms."), - Size: 10, - Multiple: true - ) - ); - - foreach (var taxonomy in _taxonomyService.GetTaxonomies()) { - f._Terms.Add(new SelectListItem { Value = "", Text = taxonomy.Name }); - foreach (var term in _taxonomyService.GetTerms(taxonomy.Id)) { - var gap = new string(' ', term.GetLevels()); - f._Terms.Add(new SelectListItem { Value = term.Id.ToString(), Text = gap + term.Name }); - } - } - - return f; - }; - - context.Form("SelectTerms", form); - - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Properties/AssemblyInfo.cs deleted file mode 100644 index d81fe3ad7..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Taxonomies")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Taxonomies")] -[assembly: AssemblyCopyright("Copyright © CodePlex Foundation 2009")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("f4bc2ee8-80e9-4240-a3a7-f9d7c09c7957")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0")] -[assembly: AssemblyFileVersion("1.0.0")] diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routes.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Routes.cs deleted file mode 100644 index 7fdab8fbc..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routes.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Collections.Generic; -using System.Web.Mvc; -using System.Web.Routing; -using Orchard.Mvc.Routes; -using Contrib.Taxonomies.Routing; - -namespace Contrib.Taxonomies { - public class Routes : IRouteProvider { - private readonly ITaxonomySlugConstraint _taxonomySlugConstraint; - private readonly ITermPathConstraint _termPathConstraint; - - public Routes(ITaxonomySlugConstraint taxonomySlugConstraint, ITermPathConstraint termPathConstraint) { - _taxonomySlugConstraint = taxonomySlugConstraint; - _termPathConstraint = termPathConstraint; - } - - public void GetRoutes(ICollection routes) { - foreach (var routeDescriptor in GetRoutes()) - routes.Add(routeDescriptor); - } - - public IEnumerable GetRoutes() { - return new[] { - new RouteDescriptor { - Priority = 90, - Route = new Route( - "{taxonomySlug}", - new RouteValueDictionary { - {"area", "Contrib.Taxonomies"}, - {"controller", "Home"}, - {"action", "List"}, - {"taxonomySlug", ""} - }, - new RouteValueDictionary { - {"taxonomySlug", _taxonomySlugConstraint} - }, - new RouteValueDictionary { - {"area", "Contrib.Taxonomies"} - }, - new MvcRouteHandler()) - }, - new RouteDescriptor { - Priority = 90, - Route = new Route( - "{*termPath}", - new RouteValueDictionary { - {"area", "Contrib.Taxonomies"}, - {"controller", "Home"}, - {"action", "Item"}, - {"termPath", ""} - }, - new RouteValueDictionary { - {"termPath", _termPathConstraint} - }, - new RouteValueDictionary { - {"area", "Contrib.Taxonomies"} - }, - new MvcRouteHandler()) - } - }; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/ITaxonomySlugConstraint.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/ITaxonomySlugConstraint.cs deleted file mode 100644 index 04c2bc5ca..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/ITaxonomySlugConstraint.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using System.Web.Routing; -using Orchard; - -namespace Contrib.Taxonomies.Routing { - public interface ITaxonomySlugConstraint : IRouteConstraint, ISingletonDependency { - void SetSlugs(IEnumerable slugs); - string FindSlug(string slug); - void AddSlug(string slug); - void RemoveSlug(string slug); - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/ITermPathConstraint.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/ITermPathConstraint.cs deleted file mode 100644 index 5e9871362..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/ITermPathConstraint.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using System.Web.Routing; -using Orchard; - -namespace Contrib.Taxonomies.Routing { - public interface ITermPathConstraint : IRouteConstraint, ISingletonDependency { - void SetPaths(IEnumerable paths); - string FindPath(string path); - void AddPath(string path); - void RemovePath(string path); - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TaxonomySlugConstraint.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TaxonomySlugConstraint.cs deleted file mode 100644 index d72620cc3..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TaxonomySlugConstraint.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Routing; -using JetBrains.Annotations; -using Orchard.Logging; - -namespace Contrib.Taxonomies.Routing { - [UsedImplicitly] - public class TaxonomySlugConstraint : ITaxonomySlugConstraint { - /// - /// Singleton object, per Orchard Shell instance. We need to protect concurrent access to the dictionary. - /// - private readonly object _syncLock = new object(); - private IDictionary _slugs = new Dictionary(); - - public TaxonomySlugConstraint() { - Logger = NullLogger.Instance; - } - - public ILogger Logger { get; set; } - - public void SetSlugs(IEnumerable slugs) { - // Make a copy to avoid performing potential lazy computation inside the lock - var slugsArray = slugs.ToArray(); - - lock (_syncLock) { - _slugs = slugsArray.Distinct(StringComparer.OrdinalIgnoreCase).ToDictionary(value => value, StringComparer.OrdinalIgnoreCase); - } - - Logger.Debug("Taxonomy slugs: {0}", string.Join(", ", slugsArray)); - } - - public string FindSlug(string slug) { - lock (_syncLock) { - string actual; - return _slugs.TryGetValue(slug, out actual) ? actual : slug; - } - } - - public void AddSlug(string slug) { - lock (_syncLock) { - _slugs[slug] = slug; - } - } - - public void RemoveSlug(string slug) { - lock (_syncLock) { - _slugs.Remove(slug); - } - } - - public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { - if (routeDirection == RouteDirection.UrlGeneration) - return true; - - object value; - if (values.TryGetValue(parameterName, out value)) { - var parameterValue = Convert.ToString(value); - - lock (_syncLock) { - return _slugs.ContainsKey(parameterValue); - } - } - - return false; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TaxonomySlugConstraintUpdator.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TaxonomySlugConstraintUpdator.cs deleted file mode 100644 index 7012e863a..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TaxonomySlugConstraintUpdator.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Contrib.Taxonomies.Services; -using Orchard; -using Orchard.Environment; - -namespace Contrib.Taxonomies.Routing { - public interface ITaxonomySlugConstraintUpdator : IDependency { - void Refresh(); - } - - public class TaxonomySlugConstraintUpdator : ITaxonomySlugConstraintUpdator, IOrchardShellEvents { - private readonly ITaxonomySlugConstraint _taxonomySlugConstraint; - private readonly ITaxonomyService _taxonomyService; - - public TaxonomySlugConstraintUpdator(ITaxonomySlugConstraint taxonomySlugConstraint, ITaxonomyService taxonomyService) { - _taxonomySlugConstraint = taxonomySlugConstraint; - _taxonomyService = taxonomyService; - } - - void IOrchardShellEvents.Activated() { - Refresh(); - } - - void IOrchardShellEvents.Terminating() { - } - - public void Refresh() { - _taxonomySlugConstraint.SetSlugs(_taxonomyService.GetSlugs()); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TermPathConstraint.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TermPathConstraint.cs deleted file mode 100644 index 138c31f43..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TermPathConstraint.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Routing; -using JetBrains.Annotations; -using Orchard.Logging; - -namespace Contrib.Taxonomies.Routing { - [UsedImplicitly] - public class TermPathConstraint : ITermPathConstraint { - /// - /// Singleton object, per Orchard Shell instance. We need to protect concurrent access to the dictionary. - /// - private readonly object _syncLock = new object(); - private IDictionary _paths = new Dictionary(); - - public TermPathConstraint() { - Logger = NullLogger.Instance; - } - - public ILogger Logger { get; set; } - - public void SetPaths(IEnumerable paths) { - // Make a copy to avoid performing potential lazy computation inside the lock - var pathsArray = paths.Where(p => p != null).ToArray(); - - lock (_syncLock) { - _paths = pathsArray.Distinct(StringComparer.OrdinalIgnoreCase).ToDictionary(value => value, StringComparer.OrdinalIgnoreCase); - } - - Logger.Debug("Taxonomy paths: {0}", string.Join(", ", pathsArray)); - } - - public string FindPath(string path) { - lock (_syncLock) { - string actual; - return _paths.TryGetValue(path, out actual) ? actual : path; - } - } - - public void AddPath(string path) { - lock (_syncLock) { - _paths[path] = path; - } - } - - public void RemovePath(string path) { - lock (_syncLock) { - _paths.Remove(path); - } - } - - public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { - if (routeDirection == RouteDirection.UrlGeneration) - return true; - - object value; - if (values.TryGetValue(parameterName, out value)) { - var parameterValue = Convert.ToString(value); - - lock (_syncLock) { - return _paths.ContainsKey(parameterValue); - } - } - - return false; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TermPathConstraintUpdator.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TermPathConstraintUpdator.cs deleted file mode 100644 index 5584d783b..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Routing/TermPathConstraintUpdator.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Contrib.Taxonomies.Services; -using Orchard; -using Orchard.Environment; - -namespace Contrib.Taxonomies.Routing { - public interface ITermPathConstraintUpdator : IDependency { - void Refresh(); - } - - public class TermPathConstraintUpdator : ITermPathConstraintUpdator, IOrchardShellEvents { - private readonly ITermPathConstraint _termPathConstraint; - private readonly ITaxonomyService _taxonomyService; - - public TermPathConstraintUpdator(ITermPathConstraint termPathConstraint, ITaxonomyService taxonomyService) { - _termPathConstraint = termPathConstraint; - _taxonomyService = taxonomyService; - } - - void IOrchardShellEvents.Activated() { - Refresh(); - } - - void IOrchardShellEvents.Terminating() { - } - - public void Refresh() { - _termPathConstraint.SetPaths(_taxonomyService.GetTermPaths()); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Scripts/Web.config b/src/Orchard.Web/Modules/Contrib.Taxonomies/Scripts/Web.config deleted file mode 100644 index df1c33504..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Scripts/Web.config +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Scripts/admin-taxonomy-expando.js b/src/Orchard.Web/Modules/Contrib.Taxonomies/Scripts/admin-taxonomy-expando.js deleted file mode 100644 index 64a651769..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Scripts/admin-taxonomy-expando.js +++ /dev/null @@ -1,3 +0,0 @@ -(function ($) { - $("fieldset legend").expandoControl(function (controller) { return controller.nextAll(".expando"); }, { collapse: true, remember: false }); -})(jQuery); \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Services/ITaxonomyService.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Services/ITaxonomyService.cs deleted file mode 100644 index 66b0154e3..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Services/ITaxonomyService.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Collections.Generic; -using Orchard; -using Orchard.ContentManagement; -using Contrib.Taxonomies.Models; - -namespace Contrib.Taxonomies.Services { - public interface ITaxonomyService : IDependency { - IEnumerable GetTaxonomies(); - TaxonomyPart GetTaxonomy(int id); - TaxonomyPart GetTaxonomyByName(string name); - TaxonomyPart GetTaxonomyBySlug(string slug); - void CreateTermContentType(TaxonomyPart taxonomy); - void DeleteTaxonomy(TaxonomyPart taxonomy); - void EditTaxonomy(TaxonomyPart taxonomy, string oldName); - - IEnumerable GetAllTerms(); - IEnumerable GetTerms(int taxonomyId); - TermPart GetTerm(int id); - TermPart GetTermByPath(string path); - TermPart GetTermByName(int taxonomyId, string name); - void DeleteTerm(TermPart termPart); - void DeleteAssociatedTerms(ContentItem contentItem); - void MoveTerm(TaxonomyPart taxonomy, TermPart term, TermPart parentTerm); - void ProcessPath(TermPart term); - IEnumerable GetTermPaths(); - - string GenerateTermTypeName(string taxonomyName); - TermPart NewTerm(TaxonomyPart taxonomy); - IEnumerable GetTermsForContentItem(int contentItemId, string field = null); - void UpdateTerms(ContentItem contentItem, IEnumerable terms, string field); - IEnumerable GetParents(TermPart term); - IEnumerable GetChildren(TermPart term); - IEnumerable GetContentItems(TermPart term, int skip = 0, int count = 0, string fieldName = null); - long GetContentItemsCount(TermPart term, string fieldName = null); - IContentQuery GetContentItemsQuery(TermPart term, string fieldName = null); - - /// - /// Returns all the slugs which can reach a taxonomy - /// - IEnumerable GetSlugs(); - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Services/TaxonomyNavigationProvider.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Services/TaxonomyNavigationProvider.cs deleted file mode 100644 index 24d028cad..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Services/TaxonomyNavigationProvider.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Contrib.Taxonomies.Models; -using Orchard.ContentManagement; -using Orchard.Localization; -using Orchard.UI.Navigation; - -namespace Contrib.Taxonomies.Services { - public class TaxonomyNavigationProvider : INavigationProvider { - private readonly IContentManager _contentManager; - private readonly ITaxonomyService _taxonomyService; - - public Localizer T { get; set; } - - public TaxonomyNavigationProvider(IContentManager contentManager, ITaxonomyService taxonomyService) { - _contentManager = contentManager; - _taxonomyService = taxonomyService; - } - - public string MenuName { - get { return "main"; } - } - - public void GetNavigation(NavigationBuilder builder) { - var parts = _contentManager.Query() - .Where(x => x.RenderMenuItem) - .List(); - - foreach(var menuItemPart in parts) { - var taxonomy = _taxonomyService.GetTaxonomy(menuItemPart.ContentItem.Id); - foreach(var term in _taxonomyService.GetTerms(menuItemPart.ContentItem.Id)) { - builder.Add(new LocalizedString(menuItemPart.Name), menuItemPart.Position, - menu => menu.Action("List", "Home", new { area = "Contrib.Taxonomies", taxonomySlug = taxonomy.Slug}) - .Add(T(term.Name), - term.Weight.ToString(), - x => x.Action("Item", "Home", new { area = "Contrib.Taxonomies", termPath = term.Slug }))); - } - } - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Services/TaxonomyService.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Services/TaxonomyService.cs deleted file mode 100644 index 9edd3bb2a..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Services/TaxonomyService.cs +++ /dev/null @@ -1,329 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using Contrib.Taxonomies.Models; -using Orchard; -using Orchard.Autoroute.Models; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Aspects; -using Orchard.ContentManagement.MetaData; -using Orchard.Core.Common.Models; -using Orchard.Core.Title.Models; -using Orchard.Data; -using Orchard.Localization; -using Orchard.Logging; -using Orchard.Security; -using Orchard.UI.Notify; - -namespace Contrib.Taxonomies.Services { - - public class TaxonomyService : ITaxonomyService { - private readonly IRepository _termContentItemRepository; - private readonly IContentManager _contentManager; - private readonly INotifier _notifier; - private readonly IAuthorizationService _authorizationService; - private readonly IContentDefinitionManager _contentDefinitionManager; - private readonly IOrchardServices _services; - - public TaxonomyService( - IRepository termContentItemRepository, - IContentManager contentManager, - INotifier notifier, - IContentDefinitionManager contentDefinitionManager, - IAuthorizationService authorizationService, - IOrchardServices services) { - _termContentItemRepository = termContentItemRepository; - _contentManager = contentManager; - _notifier = notifier; - _authorizationService = authorizationService; - _contentDefinitionManager = contentDefinitionManager; - _services = services; - - Logger = NullLogger.Instance; - T = NullLocalizer.Instance; - } - - public ILogger Logger { get; set; } - public Localizer T { get; set; } - - public IEnumerable GetTaxonomies() { - return _contentManager.Query().List(); - } - - public TaxonomyPart GetTaxonomy(int id) { - return _contentManager.Get(id).As(); - } - - public TaxonomyPart GetTaxonomyByName(string name) { - if (String.IsNullOrWhiteSpace(name)) { - throw new ArgumentNullException("name"); - } - - return _contentManager - .Query() - .Join() - .Where(r => r.Title == name) - .List() - .FirstOrDefault(); - } - - public TaxonomyPart GetTaxonomyBySlug(string slug) { - if (String.IsNullOrWhiteSpace(slug)) { - throw new ArgumentNullException("slug"); - } - - return _contentManager - .Query() - .Join() - .Where(r => r.DisplayAlias == slug) - .List() - .FirstOrDefault(); - } - - public void CreateTermContentType(TaxonomyPart taxonomy) { - // create the associated term's content type - taxonomy.TermTypeName = GenerateTermTypeName(taxonomy.Name); - - _contentDefinitionManager.AlterTypeDefinition(taxonomy.TermTypeName, - cfg => cfg - .WithSetting("Taxonomy", taxonomy.Name) - .WithPart("TermPart") - .WithPart("TitlePart") - .WithPart("AutoroutePart", builder => builder - .WithSetting("AutorouteSettings.AllowCustomPattern", "true") - .WithSetting("AutorouteSettings.AutomaticAdjustmentOnEdit", "false") - .WithSetting("AutorouteSettings.PatternDefinitions", "[{Name:'Taxonomy and Title', Pattern: '{Content.Container.Path}/{Content.Slug}', Description: 'my-taxonomy/my-term/sub-term'}]") - .WithSetting("AutorouteSettings.DefaultPatternIndex", "0")) - .WithPart("CommonPart") - .DisplayedAs(taxonomy.Name + " Term") - ); - - } - - public void EditTaxonomy(TaxonomyPart taxonomy, string oldName) { - // rename term definition - _contentDefinitionManager.AlterTypeDefinition(taxonomy.TermTypeName, - cfg => cfg - .WithSetting("Taxonomy", taxonomy.Name) - .DisplayedAs(taxonomy.Name + " Term") - ); - } - - public void DeleteTaxonomy(TaxonomyPart taxonomy) { - _contentManager.Remove(taxonomy.ContentItem); - - // removing terms - foreach (var term in GetTerms(taxonomy.Id)) { - DeleteTerm(term); - } - - _contentDefinitionManager.DeleteTypeDefinition(taxonomy.TermTypeName); - } - - public string GenerateTermTypeName(string taxonomyName) { - var disallowed = new Regex(@"[^\w]+"); - return disallowed.Replace(taxonomyName, "-"); - } - - public TermPart NewTerm(TaxonomyPart taxonomy) { - var term = _contentManager.New(taxonomy.TermTypeName); - term.TaxonomyId = taxonomy.Id; - - return term; - } - - public IEnumerable GetTerms(int taxonomyId) { - return _contentManager.Query() - .Where(x => x.TaxonomyId == taxonomyId) - .WithQueryHints(new QueryHints().ExpandRecords()) - .List() - .OrderBy(t => t); - } - - public TermPart GetTermByPath(string path) { - return _contentManager.Query() - .Join() - .WithQueryHints(new QueryHints().ExpandRecords()) - .Where(rr => rr.DisplayAlias == path) - .List() - .FirstOrDefault(); - } - - public IEnumerable GetAllTerms() { - return _contentManager.Query().List().OrderBy(t => t); - } - - public TermPart GetTerm(int id) { - return _contentManager.Query().Where(x => x.Id == id).List().FirstOrDefault(); - } - - public IEnumerable GetTermsForContentItem(int contentItemId, string field = null) { - return String.IsNullOrEmpty(field) - ? _termContentItemRepository.Fetch(x => x.TermsPartRecord.ContentItemRecord.Id == contentItemId).Select(t => GetTerm(t.TermRecord.Id)).OrderBy(t => t) - : _termContentItemRepository.Fetch(x => x.TermsPartRecord.Id == contentItemId && x.Field == field).Select(t => GetTerm(t.TermRecord.Id)).OrderBy(t => t); - } - - public TermPart GetTermByName(int taxonomyId, string name) { - return _contentManager - .Query() - .Where(t => t.TaxonomyId == taxonomyId) - .Join() - .Where(r => r.Title == name) - .List() - .FirstOrDefault(); - } - - public void CreateTerm(TermPart termPart) { - if (GetTermByName(termPart.TaxonomyId, termPart.Name) == null) { - _authorizationService.CheckAccess(Permissions.CreateTerm, _services.WorkContext.CurrentUser, null); - - termPart.As().Container = GetTaxonomy(termPart.TaxonomyId).ContentItem; - _contentManager.Create(termPart); - } - else { - _notifier.Warning(T("The term {0} already exists in this taxonomy", termPart.Name)); - } - } - - public void DeleteTerm(TermPart termPart) { - _contentManager.Remove(termPart.ContentItem); - - foreach(var childTerm in GetChildren(termPart)) { - _contentManager.Remove(childTerm.ContentItem); - } - - // delete termContentItems - var termContentItems = _termContentItemRepository - .Fetch(t => t.TermRecord == termPart.Record) - .ToList(); - - foreach (var termContentItem in termContentItems) { - _termContentItemRepository.Delete(termContentItem); - } - } - - public void DeleteAssociatedTerms(ContentItem contentItem) { - var termContentItems = _termContentItemRepository - .Fetch(t => t.TermsPartRecord.ContentItemRecord == contentItem.Record) - .ToList(); - - foreach(var termContentItem in termContentItems) { - _termContentItemRepository.Delete(termContentItem); - } - } - - public void UpdateTerms(ContentItem contentItem, IEnumerable terms, string field) { - var termsPart = contentItem.As(); - - // removing current terms for specific field - var fieldIndexes = termsPart.Terms - .Where(t => t.Field == field) - .Select((t, i) => i) - .OrderByDescending(i => i) - .ToList(); - - foreach(var x in fieldIndexes) { - termsPart.Terms.RemoveAt(x); - } - - // adding new terms list - foreach(var term in terms) { - termsPart.Terms.Add( - new TermContentItem { - TermsPartRecord = termsPart.Record, - TermRecord = term.Record, Field = field - }); - } - } - - public IContentQuery GetContentItemsQuery(TermPart term, string fieldName = null) - { - var rootPath = term.FullPath + "/"; - - var query = _contentManager - .Query(); - - if (String.IsNullOrWhiteSpace(fieldName)) { - query = query.Where( - tpr => tpr.Terms.Any(tr => - tr.TermRecord.Id == term.Id - || tr.TermRecord.Path.StartsWith(rootPath))); - } else { - query = query.Where( - tpr => tpr.Terms.Any(tr => - tr.Field == fieldName - && (tr.TermRecord.Id == term.Id || tr.TermRecord.Path.StartsWith(rootPath)))); - } - - return query; - } - - public long GetContentItemsCount(TermPart term, string fieldName = null) { - return GetContentItemsQuery(term, fieldName).Count(); - } - - public IEnumerable GetContentItems(TermPart term, - int skip = 0, - int count = 0, - string fieldName = null) - { - - return - GetContentItemsQuery(term, fieldName) - .Join() - .OrderByDescending(x => x.CreatedUtc) - .Slice(skip, count); - } - - public IEnumerable GetChildren(TermPart term){ - var rootPath = term.FullPath + "/"; - - return _contentManager.Query() - .Where(x => x.Path.StartsWith(rootPath)) - .List() - .OrderBy(t => t); - } - - public IEnumerable GetParents(TermPart term) { - return term.Path.Split(new [] {'/'}, StringSplitOptions.RemoveEmptyEntries).Select(id => GetTerm(int.Parse(id))); - } - - public IEnumerable GetSlugs() { - return _contentManager - .Query() - .Join() - .List() - .Select(t => t.Slug); - } - - public IEnumerable GetTermPaths() { - return _contentManager - .Query() - .Join() - .List() - .Select(t => t.Slug); - } - - public void MoveTerm(TaxonomyPart taxonomy, TermPart term, TermPart parentTerm) { - var children = GetChildren(term); - term.Container = parentTerm == null ? taxonomy.ContentItem : parentTerm.ContentItem; - ProcessPath(term); - - var contentItem = _contentManager.Get(term.ContentItem.Id, VersionOptions.DraftRequired); - _contentManager.Publish(contentItem); - - foreach (var childTerm in children) { - ProcessPath(childTerm); - - contentItem = _contentManager.Get(childTerm.ContentItem.Id, VersionOptions.DraftRequired); - _contentManager.Publish(contentItem); - } - } - - public void ProcessPath(TermPart term) { - var parentTerm = term.Container.As(); - term.Path = parentTerm != null ? parentTerm.FullPath + "/": "/"; - } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Settings/TaxonomyFieldEditorEvents.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Settings/TaxonomyFieldEditorEvents.cs deleted file mode 100644 index 1fad1e9e6..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Settings/TaxonomyFieldEditorEvents.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -using Orchard.ContentManagement; -using Orchard.ContentManagement.MetaData; -using Orchard.ContentManagement.MetaData.Builders; -using Orchard.ContentManagement.MetaData.Models; -using Orchard.ContentManagement.ViewModels; -using Contrib.Taxonomies.Services; -using Orchard.Localization; - -namespace Contrib.Taxonomies.Settings { - public class TaxonomyFieldEditorEvents : ContentDefinitionEditorEventsBase { - private readonly ITaxonomyService _taxonomyService; - - public TaxonomyFieldEditorEvents(ITaxonomyService taxonomyService) { - _taxonomyService = taxonomyService; - T = NullLocalizer.Instance; - } - - public Localizer T { get; set; } - - public override IEnumerable PartFieldEditor(ContentPartFieldDefinition definition) { - if (definition.FieldDefinition.Name == "TaxonomyField") { - var model = definition.Settings.GetModel(); - model.Taxonomies = _taxonomyService.GetTaxonomies(); - yield return DefinitionTemplate(model); - } - } - - public override IEnumerable PartFieldEditorUpdate(ContentPartFieldDefinitionBuilder builder, IUpdateModel updateModel) { - if (builder.FieldType != "TaxonomyField") { - yield break; - } - - var model = new TaxonomyFieldSettings(); - - if (updateModel.TryUpdateModel(model, "TaxonomyFieldSettings", null, null)) - { - builder - .WithSetting("TaxonomyFieldSettings.Taxonomy", model.Taxonomy) - .WithSetting("TaxonomyFieldSettings.LeavesOnly", model.LeavesOnly.ToString()) - .WithSetting("TaxonomyFieldSettings.SingleChoice", model.SingleChoice.ToString()) - .WithSetting("TaxonomyFieldSettings.Hint", model.Hint); - } - - yield return DefinitionTemplate(model); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Settings/TaxonomyFieldSettings.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Settings/TaxonomyFieldSettings.cs deleted file mode 100644 index ba4c469e1..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Settings/TaxonomyFieldSettings.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Collections.Generic; -using Contrib.Taxonomies.Models; - -namespace Contrib.Taxonomies.Settings { - public class TaxonomyFieldSettings { - /// - /// Wether the field allows the user to add new Terms to the taxonomy (similar to tags) - /// - public bool AllowCustomTerms { get; set; } - - /// - /// The Taxonomy to which this field is related to - /// - public string Taxonomy { get; set; } - - /// - /// Wether the user can only select leaves in the taxonomy - /// - public bool LeavesOnly { get; set; } - - /// - /// Wether the user can select only one term or not - /// - public bool SingleChoice { get; set; } - - /// - /// A help text to display in the editor - /// - public string Hint { get; set; } - - /// - /// All existing taxonomies - /// - public IEnumerable Taxonomies { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Shapes.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/Shapes.cs deleted file mode 100644 index 88f9afefd..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Shapes.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System.Collections.Generic; -using Contrib.Taxonomies.Models; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Aspects; -using Orchard.DisplayManagement.Descriptors; - -namespace Contrib.Taxonomies { - public class Shapes : IShapeTableProvider { - public void Discover(ShapeTableBuilder builder) { - builder.Describe("Content") - .OnDisplaying(displaying => { - var term = displaying.Shape.Term as TermPart; - var taxonomy = displaying.Shape.Taxonomy as TaxonomyPart; - - if (taxonomy == null) { - return; - } - - if (term != null) { - - // Taxonomy.Content.Categories.cshtml - // Taxonomy.Content.BlogPost-Categories.cshtml - // Taxonomy.Content.Categories-World.cshtml - // Taxonomy.Content.BlogPost-Categories-World.cshtml - // Taxonomy.Content.Categories-World-France.cshtml - // Taxonomy.Content.BlogPost-Categories-World-France.cshtml - // Taxonomy.Content.23.cshtml - // Taxonomy.Content.BlogPost-23.cshtml - - var metadata = displaying.ShapeMetadata; - ContentItem contentItem = displaying.Shape.ContentItem; - - metadata.Alternates.Add("Taxonomy_Content_" + FormatAlternate(taxonomy.Slug)); - metadata.Alternates.Add("Taxonomy_Content_" + contentItem.ContentType + "__" + FormatAlternate(taxonomy.Slug)); - - var curTerm = term; - var alternates = new List(); - while (curTerm != null) { - var alternate = FormatAlternate(term.Slug); - alternates.Add("Taxonomy_Content_" + alternate); - alternates.Add("Taxonomy_Content_" + contentItem.ContentType + "__" + alternate); - curTerm = curTerm.Container.As(); - } - - alternates.Reverse(); - foreach (var alternate in alternates) { - metadata.Alternates.Add(alternate); - } - - metadata.Alternates.Add("Taxonomy_Content_" + term.Id); - metadata.Alternates.Add("Taxonomy_Content_" + contentItem.ContentType + "__" + term.Id); - } - }); - - builder.Describe("Taxonomies_TermContentItems_List") - .OnDisplaying(displaying => { - - // Taxonomy.TermContentItems.List.Categories.cshtml - // Taxonomy.TermContentItems.List.Categories-World.cshtml - // Taxonomy.TermContentItems.List.Categories-World-France.cshtml - // Taxonomy.TermContentItems.List.12.cshtml - - var shape = displaying.Shape; - var metadata = displaying.ShapeMetadata; - var term = shape.Term as TermPart; - var taxonomy = shape.Taxonomy as TaxonomyPart; - - if (taxonomy == null || term == null){ - return; - } - - metadata.Alternates.Add("Taxonomies_TermContentItems_List_" + FormatAlternate(taxonomy.Slug)); - - var curTerm = term; - var alternates = new List(); - while (curTerm != null) { - alternates.Add("Taxonomies_TermContentItems_List_" + FormatAlternate(term.Slug)); - curTerm = curTerm.Container.As(); - } - - alternates.Reverse(); - foreach(var alternate in alternates) { - metadata.Alternates.Add(alternate); - } - - metadata.Alternates.Add("Taxonomy_List_" + term.Id); - }); - - builder.Describe("Pager") - .OnDisplaying(displaying => { - - // Taxonomy.Pager.Categories.cshtml - // Taxonomy.Pager.Categories-World.cshtml - // Taxonomy.Pager.Categories-World-France.cshtml - // Taxonomy.Pager.12.cshtml - - var shape = displaying.Shape; - var metadata = displaying.ShapeMetadata; - var term = shape.Term as TermPart; - var taxonomy = shape.Taxonomy as TaxonomyPart; - - if(taxonomy == null || term == null) { - return; - } - - metadata.Alternates.Add("Taxonomy_Pager_" + FormatAlternate(taxonomy.Slug)); - - var curTerm = term; - var alternates = new List(); - while (curTerm != null) { - alternates.Add("Taxonomy_Pager_" + FormatAlternate(term.Slug)); - curTerm = curTerm.Container.As(); - } - - alternates.Reverse(); - foreach (var alternate in alternates) { - metadata.Alternates.Add(alternate); - } - - metadata.Alternates.Add("Taxonomy_Pager_" + term.Id); - }); - - } - - public string FormatAlternate(string path) { - return path.Replace("-", "__").Replace("/", "__"); - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/StandardQueries/TermFeedQuery.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/StandardQueries/TermFeedQuery.cs deleted file mode 100644 index cfd85d990..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/StandardQueries/TermFeedQuery.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Web.Mvc; -using System.Xml.Linq; -using Contrib.Taxonomies.Models; -using Contrib.Taxonomies.Services; -using JetBrains.Annotations; -using Orchard.ContentManagement; -using Orchard.Core.Common.Models; -using Orchard.Core.Feeds; -using Orchard.Core.Feeds.Models; -using Orchard.Core.Feeds.StandardBuilders; -using Orchard.Utility.Extensions; - -namespace Contrib.Taxonomies.StandardQueries { - [UsedImplicitly] - public class TermFeedQuery : IFeedQueryProvider, IFeedQuery { - private readonly IContentManager _contentManager; - private readonly ITaxonomyService _taxonomyService; - - public TermFeedQuery( - IContentManager contentManager, - ITaxonomyService taxonomyService) - { - _contentManager = contentManager; - _taxonomyService = taxonomyService; - } - - public FeedQueryMatch Match(FeedContext context) { - var containerIdValue = context.ValueProvider.GetValue("term"); - if (containerIdValue == null) - return null; - - return new FeedQueryMatch { FeedQuery = this, Priority = -5 }; - } - - public void Execute(FeedContext context) { - var termParthId = context.ValueProvider.GetValue("term"); - if (termParthId == null) - return; - - var limitValue = context.ValueProvider.GetValue("limit"); - var limit = 20; - if (limitValue != null) - limit = (int)limitValue.ConvertTo(typeof(int)); - - var containerId = (int)termParthId.ConvertTo(typeof(int)); - var container = _contentManager.Get(containerId); - - if(container == null){ - return; - } - - var inspector = new ItemInspector(container, _contentManager.GetItemMetadata(container)); - if (context.Format == "rss") { - var link = new XElement("link"); - context.Response.Element.SetElementValue("title", inspector.Title); - context.Response.Element.Add(link); - context.Response.Element.SetElementValue("description", inspector.Description); - - context.Response.Contextualize(requestContext => { - var urlHelper = new UrlHelper(requestContext); - var uriBuilder = new UriBuilder(urlHelper.RequestContext.HttpContext.Request.ToRootUrlString()) { Path = urlHelper.RouteUrl(inspector.Link) }; - link.Add(uriBuilder.Uri.OriginalString); - }); - } - else { - context.Builder.AddProperty(context, null, "title", inspector.Title); - context.Builder.AddProperty(context, null, "description", inspector.Description); - context.Response.Contextualize(requestContext => { - var urlHelper = new UrlHelper(requestContext); - context.Builder.AddProperty(context, null, "link", urlHelper.RouteUrl(inspector.Link)); - }); - } - - var items = _taxonomyService.GetContentItems(container, 0, limit); - - foreach (var item in items) { - // call item.ContentItem to force a cast to ContentItem, and - // thus use CorePartsFeedItemBuilder - context.Builder.AddItem(context, item.ContentItem); - } - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Styles/Web.config b/src/Orchard.Web/Modules/Contrib.Taxonomies/Styles/Web.config deleted file mode 100644 index b4210f3e0..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Styles/Web.config +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Styles/admin-taxonomy.css b/src/Orchard.Web/Modules/Contrib.Taxonomies/Styles/admin-taxonomy.css deleted file mode 100644 index 47e65157a..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Styles/admin-taxonomy.css +++ /dev/null @@ -1,21 +0,0 @@ -.gap -{ - padding:1.5ex; -} - -div.taxonomy-widget -{ - padding: 0.5em; - background-color:rgb(246, 246, 242); -} - -div.taxonomy-widget ul -{ - margin-bottom:0; - list-style-type:circle; -} - -div.taxonomy-widget ul li -{ - padding-top:0.5em; -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/ImportViewModel.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/ImportViewModel.cs deleted file mode 100644 index ea49cd22c..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/ImportViewModel.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Contrib.Taxonomies.Models; - -namespace Contrib.Taxonomies.ViewModels { - public class ImportViewModel { - public TaxonomyPart Taxonomy { get; set; } - public string Terms { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/MoveTermViewModel.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/MoveTermViewModel.cs deleted file mode 100644 index fcfbd666f..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/MoveTermViewModel.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Contrib.Taxonomies.Models; -using System.Collections.Generic; - -namespace Contrib.Taxonomies.ViewModels { - public class MoveTermViewModel { - public IEnumerable Terms { get; set; } - public int SelectedTermId { get; set; } - public int TermId { get; set; } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/SelectTermViewModel.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/SelectTermViewModel.cs deleted file mode 100644 index cb529278c..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/SelectTermViewModel.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Contrib.Taxonomies.Models; -using System.Collections.Generic; - -namespace Contrib.Taxonomies.ViewModels { - public class SelectTermViewModel { - public IEnumerable Terms { get; set; } - public int SelectedTermId { get; set; } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TaxonomyAdminIndexViewModel.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TaxonomyAdminIndexViewModel.cs deleted file mode 100644 index 9d4a44ce7..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TaxonomyAdminIndexViewModel.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections.Generic; -using Contrib.Taxonomies.Models; - -namespace Contrib.Taxonomies.ViewModels { - public class TaxonomyAdminIndexViewModel { - public IList Taxonomies { get; set; } - public TaxonomiesAdminIndexBulkAction BulkAction { get; set; } - } - - public class TaxonomyEntry { - public TaxonomyPart Taxonomy { get; set; } - public bool IsChecked { get; set; } - } - - public enum TaxonomiesAdminIndexBulkAction { - None, - Delete, - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TaxonomyFieldViewModel.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TaxonomyFieldViewModel.cs deleted file mode 100644 index a7e14ef51..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TaxonomyFieldViewModel.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; -using Contrib.Taxonomies.Settings; - -namespace Contrib.Taxonomies.ViewModels { - public class TaxonomyFieldViewModel { - public string Name { get; set; } - public TaxonomyFieldSettings Settings { get; set; } - public IList Terms { get; set; } - public int SingleTermId { get; set; } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TaxonomyMenuViewModel.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TaxonomyMenuViewModel.cs deleted file mode 100644 index 1a58e9d0d..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TaxonomyMenuViewModel.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using System.Web.Mvc; - -namespace Contrib.Taxonomies.ViewModels { - public class TaxonomyMenuViewModel { - public SelectList AvailableTaxonomies { get; set; } - - [Required, Range(0, int.MaxValue, ErrorMessage = "You must select a taxonomy")] - public int SelectedTaxonomyId { get; set; } - public int SelectedTermId { get; set; } - - public bool DisplayTopMenuItem { get; set; } - [Required, Range(0, 99)] - public int LevelsToDisplay { get; set; } - public bool DisplayContentCount { get; set; } - public bool HideEmptyTerms { get; set; } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TermAdminIndexViewModel.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TermAdminIndexViewModel.cs deleted file mode 100644 index ab86bdc5f..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TermAdminIndexViewModel.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using Contrib.Taxonomies.Models; -using Orchard.ContentManagement; - -namespace Contrib.Taxonomies.ViewModels { - public class TermAdminIndexViewModel { - public IList Terms { get; set; } - public TermsAdminIndexBulkAction BulkAction { get; set; } - public TaxonomyPart Taxonomy { get; set; } - public int TaxonomyId { get; set; } - } - - public class TermEntry { - public int Id { get; set; } - public string Name { get; set; } - public string Path { get; set; } - public bool Selectable { get; set; } - public int Count { get; set; } - public int Weight { get; set; } - public bool IsChecked { get; set; } - public ContentItem ContentItem { get; set; } - } - - public enum TermsAdminIndexBulkAction { - None, - Delete, - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TermWidgetViewModel.cs b/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TermWidgetViewModel.cs deleted file mode 100644 index 7481e7c06..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/ViewModels/TermWidgetViewModel.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Web.Mvc; -using System.Web.UI.WebControls.WebParts; -using Contrib.Taxonomies.Models; - -namespace Contrib.Taxonomies.ViewModels { - public class TermWidgetViewModel { - public SelectList AvailableTaxonomies { get; set; } - - [Required, Range(0, int.MaxValue, ErrorMessage = "You must select a taxonomy")] - public int SelectedTaxonomyId { get; set; } - - [Required, Range(0, int.MaxValue, ErrorMessage = "You must select a term")] - public int SelectedTermId { get; set; } - - public bool Ascending { get; set; } - [Required, Range(0, int.MaxValue)] - public int Count { get; set; } - public string FieldName { get; set; } - public string OrderBy { get; set; } - - public TermWidgetPart Part { get; set; } - public IEnumerable ContentTypeNames { get; set; } - } -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Create.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Create.cshtml deleted file mode 100644 index 04897983c..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Create.cshtml +++ /dev/null @@ -1,8 +0,0 @@ -@{ - Layout.Title = T("Create New Taxonomy").Text; -} - -@using (Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() - @Display(Model) -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Edit.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Edit.cshtml deleted file mode 100644 index 4568363de..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Edit.cshtml +++ /dev/null @@ -1,8 +0,0 @@ -@{ - Layout.Title = T("Taxonomy Properties").Text; -} - -@using (Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() - @Display(Model) -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Import.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Import.cshtml deleted file mode 100644 index dece0b44e..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Import.cshtml +++ /dev/null @@ -1,71 +0,0 @@ -@model Contrib.Taxonomies.ViewModels.ImportViewModel -@{ - Layout.Title = T("Import Terms for {0}", Model.Taxonomy.Name).Text; -} - -@using(Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() -
- - - @T("One term per line, followed by a semi-colon and the slug") - @T("Hierarchies are defined using tabs (handled in this editor zone)") - @T("e.g,") -   @T("Red; red") -   @T("Blue; blue") -     @T("Light Blue; light-blue") -
- - -} - -@using(Script.Foot()){ - -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Index.cshtml deleted file mode 100644 index 1bd97cbd5..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Admin/Index.cshtml +++ /dev/null @@ -1,56 +0,0 @@ -@model TaxonomyAdminIndexViewModel -@using Contrib.Taxonomies.ViewModels; - -@{ - Layout.Title = T("Manage Taxonomies").ToString(); - - int taxonomyIndex = 0, ti; -} - -@using (Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() -
- - - -
-
@Html.ActionLink(T("Add a taxonomy").Text, "Create", new { Area = "Contents", Id = "Taxonomy", ReturnUrl = Request.RawUrl }, new { @class = "button primaryAction" })
-
- - - - - - - - - - - - - - @foreach (var taxonomyEntry in Model.Taxonomies) { - ti = taxonomyIndex; - - - - - - taxonomyIndex++; - } -
 ↓@T("Name")
- - - - @Html.ActionLink(taxonomyEntry.Taxonomy.Name, "Index", "TermAdmin", new { taxonomyId = taxonomyEntry.Taxonomy.Id }, new object { }) - - @Html.ItemEditLink(T("Edit").Text, taxonomyEntry.Taxonomy) | - @Html.ActionLink(T("Terms").Text, "Index", "TermAdmin", new { taxonomyId = taxonomyEntry.Taxonomy.Id }, new object { }) | - @Html.ActionLink(T("Delete").Text, "Delete", new { id = taxonomyEntry.Taxonomy.Id }, new object { }) | - @Html.ActionLink(T("Import").Text, "Import", new { id = taxonomyEntry.Taxonomy.Id }, new object { }) -
-
-} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/DefinitionTemplates/TaxonomyFieldSettings.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/DefinitionTemplates/TaxonomyFieldSettings.cshtml deleted file mode 100644 index de2acbd9e..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/DefinitionTemplates/TaxonomyFieldSettings.cshtml +++ /dev/null @@ -1,27 +0,0 @@ -@model Contrib.Taxonomies.Settings.TaxonomyFieldSettings - -
- - - @Html.ValidationMessageFor(m => m.Taxonomy) -
- -
- - @Html.CheckBoxFor(m => m.LeavesOnly) -
- @Html.CheckBoxFor(m => m.SingleChoice) -
- -
- - @Html.TextAreaFor(m => m.Hint, new { @class = "textMedium", rows = "5" } ) - @T("The help text is written under the field when authors are editing the content item.") - @Html.ValidationMessageFor(m => m.Hint) -
- diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Fields/Contrib.TaxonomyField.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Fields/Contrib.TaxonomyField.cshtml deleted file mode 100644 index 7046c46ec..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Fields/Contrib.TaxonomyField.cshtml +++ /dev/null @@ -1,38 +0,0 @@ -@model Contrib.Taxonomies.ViewModels.TaxonomyFieldViewModel -@using Contrib.Taxonomies.Helpers; -@using Orchard.Utility.Extensions; - -@{ - Style.Include("admin-taxonomy.css"); - Script.Include("~/Themes/TheAdmin/scripts/admin.js").AtFoot(); - Script.Include("admin-taxonomy-expando.js").AtFoot(); - int termIndex = 0, ti; -} - -
- @Model.Name.CamelFriendly() -
- @if (!String.IsNullOrWhiteSpace(Model.Settings.Hint)) { - @Model.Settings.Hint - } -
    - @foreach (var entry in Model.Terms) { - ti = termIndex; -
  • - @* Tabs for levels *@ @for ( var i = 1; i <= entry.GetLevels(); i++ ) {   } - @{ - var disabled = !entry.Selectable || (Model.Settings.LeavesOnly && Model.Terms.Any(t => t.Path.Contains(entry.Path + entry.Id))); - if(Model.Settings.SingleChoice) { - disabled="disabled" } type="radio" value="@Model.Terms[ti].Id" @if(entry.Id == Model.SingleTermId) { checked="checked" } name="@Html.FieldNameFor(m => m.SingleTermId)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)"/> - } else { - disabled="disabled" } type="checkbox" value="true" @if(entry.IsChecked) { checked="checked" } name="@Html.FieldNameFor(m => m.Terms[ti].IsChecked)" id="@Html.FieldIdFor(m => m.Terms[ti].IsChecked)"/> - } - } - @Html.HiddenFor(m => m.Terms[ti].Id) - -
  • - termIndex++; - } -
-
-
diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.Menu.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.Menu.cshtml deleted file mode 100644 index e3d4c9a97..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.Menu.cshtml +++ /dev/null @@ -1,64 +0,0 @@ -@model Contrib.Taxonomies.ViewModels.TaxonomyMenuViewModel -@{ - Script.Require("jQuery"); -} - -
- @Html.LabelFor(m => m.SelectedTaxonomyId, T("Taxonomy")) - @Html.DropDownListFor(m => m.SelectedTaxonomyId, Model.AvailableTaxonomies) - @T("Select the taxonomy whose terms will be rendered in the menu.") -
- -
- @Html.LabelFor(m => m.SelectedTermId, T("Root Term")) - - @T("Select the root term to display") -
- -
- @Html.LabelFor(m => m.LevelsToDisplay, T("Number of levels to display")) - @Html.TextBoxFor(m => m.LevelsToDisplay, new { @class = "text-small"}) - @T("Enter \"0\" to render all sub-levels.") -
- -
- @Html.CheckBoxFor(m => m.DisplayTopMenuItem) - - @T("When checked, the selected term to display will be rendered as a root element in the menu.") -
- -
- @Html.CheckBoxFor(m => m.HideEmptyTerms) - - @T("When checked, any term which has no content item associated to it won't be rendered.") -
- -
- @Html.CheckBoxFor(m => m.DisplayContentCount) - - @T("When checked, the number of content items is rendered following the term name.") -
- -@using (Script.Foot()) { - -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.TaxonomyMenuItem.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.TaxonomyMenuItem.cshtml deleted file mode 100644 index d9da687fa..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.TaxonomyMenuItem.cshtml +++ /dev/null @@ -1,13 +0,0 @@ -@model Contrib.Taxonomies.Models.TaxonomyMenuItemPart -@using Orchard.Core.Navigation.Models; - -
- @Html.EditorFor(m => m.RenderMenuItem) - -
- - @Html.TextBoxFor(m => m.Name, new { @class = "text-box single-line" }) - - @Html.TextBoxFor(m => m.Position, new { @class = "text-box single-line" }) -
-
diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.Term.Fields.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.Term.Fields.cshtml deleted file mode 100644 index ff46acd70..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.Term.Fields.cshtml +++ /dev/null @@ -1,13 +0,0 @@ -@model Contrib.Taxonomies.Models.TermPart -@using Contrib.Taxonomies.Helpers; - - @Html.ValidationSummary() -
- @Html.CheckBoxFor(m => m.Selectable, new { @class = "" }) - @T("Uncheck if users should not be able to select this term") -
-
- @Html.LabelFor(m => m.Weight) - @Html.TextBoxFor(m => m.Weight, new { @class = "text-small" }) - @T("If specified, will be used to sort terms at the same level") -
diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.TermWidget.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.TermWidget.cshtml deleted file mode 100644 index 55baae834..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/EditorTemplates/Parts/Taxonomies.TermWidget.cshtml +++ /dev/null @@ -1,76 +0,0 @@ -@model Contrib.Taxonomies.ViewModels.TermWidgetViewModel -@{ - Script.Require("jQuery"); -} - -
- @Html.LabelFor(m => m.SelectedTaxonomyId, T("Taxonomy")) - @Html.DropDownListFor(m => m.SelectedTaxonomyId, Model.AvailableTaxonomies) - @T("Select a taxonomy.") -
- -
- @Html.LabelFor(m => m.SelectedTermId, T("Term")) - - @T("Select the term whose content items will be displayed.") -
- -
- @Html.LabelFor(m => m.FieldName, T("Field")) - @Html.TextBoxFor(m => m.FieldName, new { @class = "text" }) - @T("Optional. You can specify which field name to use if several terms references are defined on the same content type.") -
- -
- @Html.LabelFor(m => m.Count, T("Number of items to display")) - @Html.TextBoxFor(m => m.Count, new { @class = "text-small"}) -
- -
-
- @Html.LabelFor(m => m.OrderBy, T("Order By")) - -
-
- -
-
- @Html.LabelFor(m => m.Part.ContentType, T("Content Type")) - - @T("Select which Content Type you want to display") -
-
- - -@using (Script.Foot()) { - -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Fields/Contrib.TaxonomyField.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Fields/Contrib.TaxonomyField.cshtml deleted file mode 100644 index f71638c3a..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Fields/Contrib.TaxonomyField.cshtml +++ /dev/null @@ -1,14 +0,0 @@ -@using Orchard.Utility.Extensions; -@using Orchard.ContentManagement; - -@{ - var terms = (IEnumerable)Model.Terms; - string name = @Model.ContentField.Name; -} - -@if (Model.Terms.Count > 0) { -

- @name.CamelFriendly(): - @(new HtmlString( string.Join(", ", terms.Select(t => Html.ItemDisplayLink(t.Name, t.ContentItem ).ToString()).ToArray()) )) -

-} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Home/List.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Home/List.cshtml deleted file mode 100644 index 7bf4f1c74..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Home/List.cshtml +++ /dev/null @@ -1 +0,0 @@ -@Display(Model) diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Items/Content-Term.Edit.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Items/Content-Term.Edit.cshtml deleted file mode 100644 index b18f344b7..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Items/Content-Term.Edit.cshtml +++ /dev/null @@ -1,7 +0,0 @@ -@using Orchard.Mvc.Html; -@{ - Html.AddTitleParts((string)Model.Title); -} -@Display(Model.Primary) -@Display(Model.Secondary) -
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Items/Taxonomies.Term.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Items/Taxonomies.Term.cshtml deleted file mode 100644 index ca4fc4084..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Items/Taxonomies.Term.cshtml +++ /dev/null @@ -1,5 +0,0 @@ -@model Contrib.Taxonomies.Models.TermPart - -@Html.Zone("primary"); -@Html.ZonesAny(); -
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Items/Taxonomy.List.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Items/Taxonomy.List.cshtml deleted file mode 100644 index b12d3e3c3..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Items/Taxonomy.List.cshtml +++ /dev/null @@ -1,15 +0,0 @@ -@* - Called when displaying a list of content items associated to a specific term. - Available objects: - Model.Term - Model.Taxonomy - Model.List -*@ - -@{ - Model.List.Classes.Add("content-items"); -} - -

@T("Contents associated with {0}", Html.Encode(Model.Term.Name))

-@Display(Model.List) -@Display(Model.Pager) \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Parts/Taxonomies.Menu.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Parts/Taxonomies.Menu.cshtml deleted file mode 100644 index 556aa82ab..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Parts/Taxonomies.Menu.cshtml +++ /dev/null @@ -1,38 +0,0 @@ -@using Orchard.Utility.Extensions; -@using Contrib.Taxonomies.Models; -@using Contrib.Taxonomies.Helpers; - -@{ - Style.Include("admin-taxonomy.css"); - int level=0; - int firstLevel = -1; -} - -
-
    - @foreach (TermPart term in Model.Terms) { - if(firstLevel == -1){ - firstLevel = term.GetLevels(); - } - var text = Model.ContentPart.DisplayContentCount ? (string)term.Name + T(" ({0})", term.Count).Text : (string)term.Name; - if(term.GetLevels() - firstLevel > level) { - level++; - @:
      - } - @: - - if(term.GetLevels() - firstLevel < level) { - level--; - @:
    - } - - @:
  • - @Html.ItemDisplayLink(text, term.ContentItem) - } - -
  • - @for (int i = 0; i < level; i++) { - @:
- } - -
\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Parts/TermWidget.List.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Parts/TermWidget.List.cshtml deleted file mode 100644 index 4f3bd82bd..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Parts/TermWidget.List.cshtml +++ /dev/null @@ -1,15 +0,0 @@ -@* - ContentPart: TermWidgetPart - ContentItems: List -*@ - -@{ - IEnumerable contentItems = Model.ContentItems; - Model.ContentItems.Classes.Add("content-items"); - Model.ContentItems.Classes.Add("term-widget"); -} - -@Display(Model.ContentItems) -@if (contentItems == null || contentItems.Count() == 0) { -

@T("There are no items for this term.")

-} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Taxonomies.TermContentItems.List.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Taxonomies.TermContentItems.List.cshtml deleted file mode 100644 index 93014b5ed..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Taxonomies.TermContentItems.List.cshtml +++ /dev/null @@ -1,9 +0,0 @@ -@{ - IEnumerable contentItems = Model.ContentItems; - Model.ContentItems.Classes.Add("content-items"); - Model.ContentItems.Classes.Add("term-content-items"); -} -@Display(Model.ContentItems) -@if (contentItems == null || contentItems.Count() < 1) { -

@T("There is no content associated to this term.")

-} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/Create.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/Create.cshtml deleted file mode 100644 index 87651bb21..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/Create.cshtml +++ /dev/null @@ -1,8 +0,0 @@ -@{ - Layout.Title = T("Create New Term").Text; -} - -@using (Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() - @Display(Model) -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/Edit.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/Edit.cshtml deleted file mode 100644 index a7ba89361..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/Edit.cshtml +++ /dev/null @@ -1,8 +0,0 @@ -@{ - Layout.Title = T("Term Properties").Text; -} - -@using (Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() - @Display(Model) -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/Index.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/Index.cshtml deleted file mode 100644 index 4a3949b4f..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/Index.cshtml +++ /dev/null @@ -1,54 +0,0 @@ -@model TermAdminIndexViewModel -@using Contrib.Taxonomies.Helpers; -@using Contrib.Taxonomies.ViewModels; - -@{ - Style.Include("admin-taxonomy.css"); - Layout.Title = T("Manage terms for {0}", Model.Taxonomy.Name).ToString(); - - int termIndex = 0, ti; -} - -@using(Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() - @Html.HiddenFor(m=>m.TaxonomyId) -
- - - -
-
@Html.ActionLink(T("Add a term").ToString(), "SelectTerm", new { taxonomyId = Model.Taxonomy.Id }, new { @class = "button primaryAction" })
-
- - - - - - - - - - - - @foreach ( var termEntry in Model.Terms) { - ti = termIndex; - - - - - termIndex++; - } -
@T("Name")
- - @* Tabs for levels *@ @for ( var i = 1; i <= termEntry.GetLevels(); i++ ) {   } - - @Html.ItemDisplayLink(termEntry.Name, termEntry.ContentItem) - - @Html.ItemEditLink(T("Edit").Text, termEntry.ContentItem, new { returnUrl = Url.Action("Index", "TermAdmin", new { taxonomyId = Model.Taxonomy.Id }) }) | - @Html.ActionLink(T("Move").ToString(), "MoveTerm", new { taxonomyId = Model.Taxonomy.Id, termId = termEntry.Id }) -
-
-} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/MoveTerm.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/MoveTerm.cshtml deleted file mode 100644 index f10ec982e..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/MoveTerm.cshtml +++ /dev/null @@ -1,21 +0,0 @@ -@model Contrib.Taxonomies.ViewModels.MoveTermViewModel -@using Contrib.Taxonomies.Helpers; - -@using (Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() -
- @Html.Hidden("TermId", Model.TermId) - - - @T("By selecting a parent term you can create hierarchies") - -
-
- -
-} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/RenderTermSelect.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/RenderTermSelect.cshtml deleted file mode 100644 index e38de320b..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/RenderTermSelect.cshtml +++ /dev/null @@ -1,6 +0,0 @@ -@model Contrib.Taxonomies.ViewModels.SelectTermViewModel -@using Contrib.Taxonomies.Helpers; - -@foreach (var term in Model.Terms) { - -} diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/SelectTerm.cshtml b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/SelectTerm.cshtml deleted file mode 100644 index fcd030d26..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/TermAdmin/SelectTerm.cshtml +++ /dev/null @@ -1,20 +0,0 @@ -@model Contrib.Taxonomies.ViewModels.SelectTermViewModel -@using Contrib.Taxonomies.Helpers; - -@using (Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() -
- - - @T("By selecting a parent term you can create hierarchies") - -
-
- -
-} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Web.config b/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Web.config deleted file mode 100644 index c91d018b2..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/Views/Web.config +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Orchard.Web/Modules/Contrib.Taxonomies/web.config b/src/Orchard.Web/Modules/Contrib.Taxonomies/web.config deleted file mode 100644 index 72ce060b6..000000000 --- a/src/Orchard.Web/Modules/Contrib.Taxonomies/web.config +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Orchard.Web/Modules/Orchard.Workflows.zip b/src/Orchard.Web/Modules/Orchard.Workflows.zip deleted file mode 100644 index eb65ece9fcd1deebd287f3086b032d355472da90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82712 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