diff --git a/AzurePackage.proj b/AzurePackage.proj index ad02d137d..0dade831c 100644 --- a/AzurePackage.proj +++ b/AzurePackage.proj @@ -109,6 +109,23 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Tests.Modules/Users/Controllers/AdminControllerTests.cs b/src/Orchard.Tests.Modules/Users/Controllers/AdminControllerTests.cs index 78ad1eaab..67e7fa800 100644 --- a/src/Orchard.Tests.Modules/Users/Controllers/AdminControllerTests.cs +++ b/src/Orchard.Tests.Modules/Users/Controllers/AdminControllerTests.cs @@ -30,6 +30,7 @@ namespace Orchard.Tests.Modules.Users.Controllers { public override void Register(ContainerBuilder builder) { builder.RegisterType().SingleInstance(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As().InstancePerDependency(); builder.RegisterType().As(); builder.RegisterType().As(); diff --git a/src/Orchard.Tests.Modules/Users/Services/MembershipServiceTests.cs b/src/Orchard.Tests.Modules/Users/Services/MembershipServiceTests.cs index 1b928a7c3..ea7ee2f3d 100644 --- a/src/Orchard.Tests.Modules/Users/Services/MembershipServiceTests.cs +++ b/src/Orchard.Tests.Modules/Users/Services/MembershipServiceTests.cs @@ -55,6 +55,7 @@ namespace Orchard.Tests.Modules.Users.Services { //builder.RegisterModule(new ImplicitCollectionSupportModule()); builder.RegisterType().As(); builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)); _session = _sessionFactory.OpenSession(); diff --git a/src/Orchard.Tests/App.config b/src/Orchard.Tests/App.config index 5a9770697..718d9c26f 100644 --- a/src/Orchard.Tests/App.config +++ b/src/Orchard.Tests/App.config @@ -9,4 +9,12 @@ + + + + + + + + diff --git a/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs b/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs index 1ea84731c..c80d090f6 100644 --- a/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs +++ b/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs @@ -1,7 +1,12 @@ -using System.IO; +using System; +using System.Collections.Generic; +using System.IO; using System.Linq; using NUnit.Framework; +using Orchard.Caching; using Orchard.Environment.Extensions.Folders; +using Orchard.FileSystems.WebSite; +using Orchard.Tests.Stubs; using Yaml.Grammar; namespace Orchard.Tests.Environment.Extensions { @@ -49,8 +54,8 @@ namespace Orchard.Tests.Environment.Extensions { [Test] public void NamesFromFoldersWithModuleTxtShouldBeListed() { - var folders = new ModuleFolders(new[] { _tempFolderName },null,null); - var names = folders.ListNames(); + IExtensionFolders folders = new ModuleFolders(new[] { _tempFolderName }, new StubCacheManager(), new StubWebSiteFolder()); + var names = folders.AvailableExtensions().Select(d => d.Name); Assert.That(names.Count(), Is.EqualTo(2)); Assert.That(names, Has.Some.EqualTo("Sample1")); Assert.That(names, Has.Some.EqualTo("Sample3")); @@ -58,14 +63,10 @@ namespace Orchard.Tests.Environment.Extensions { [Test] public void ModuleTxtShouldBeParsedAndReturnedAsYamlDocument() { - var folders = new ModuleFolders(new[] { _tempFolderName },null,null); - var sample1 = folders.ParseManifest("Sample1"); - var mapping = (Mapping)sample1.YamlDocument.Root; - var entities = mapping.Entities - .Where(x => x.Key is Scalar) - .ToDictionary(x => ((Scalar)x.Key).Text, x => x.Value); - Assert.That(entities.Keys, Has.Some.EqualTo("name")); - Assert.That(entities.Keys, Has.Some.EqualTo("author")); + IExtensionFolders folders = new ModuleFolders(new[] { _tempFolderName }, new StubCacheManager(), new StubWebSiteFolder()); + var sample1 = folders.AvailableExtensions().Single(d => d.Name == "Sample1"); + Assert.That(sample1.Name, Is.Not.Empty); + Assert.That(sample1.Author, Is.EqualTo("Bertrand Le Roy")); } - } + } } \ No newline at end of file diff --git a/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs b/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs index 5852c1028..8e1b0aa1a 100644 --- a/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs +++ b/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs @@ -34,26 +34,12 @@ namespace Orchard.Tests.Environment.Extensions { public IDictionary Manifests { get; set; } - public IEnumerable ListNames() { - return Manifests.Keys; - } - - public ParseResult ParseManifest(string name) { - var parser = new YamlParser(); - bool success; - var stream = parser.ParseYamlStream(new TextInput(Manifests[name]), out success); - if (success) { - return new ParseResult { - Location = "~/InMemory", - Name = name, - YamlDocument = stream.Documents.Single() - }; - } - return null; - } - public IEnumerable AvailableExtensions() { - throw new NotImplementedException(); + foreach(var e in Manifests) { + string name = e.Key; + var parseResult = ExtensionFolders.ParseManifest(Manifests[name]); + yield return ExtensionFolders.GetDescriptorForExtension("~/", name, "Module", parseResult); + } } } @@ -218,7 +204,7 @@ features: Description: Contains the Phi type. "); - ExtensionManager extensionManager = new ExtensionManager(new[] { extensionFolder }, new[] { extensionLoader }); + IExtensionManager extensionManager = new ExtensionManager(new[] { extensionFolder }, new[] { extensionLoader }); var testFeature = extensionManager.AvailableExtensions() .SelectMany(x => x.Features); @@ -244,7 +230,7 @@ features: Description: Contains the Phi type. "); - ExtensionManager extensionManager = new ExtensionManager(new[] { extensionFolder }, new[] { extensionLoader }); + IExtensionManager extensionManager = new ExtensionManager(new[] { extensionFolder }, new[] { extensionLoader }); var testFeature = extensionManager.AvailableExtensions() .SelectMany(x => x.Features); @@ -301,7 +287,7 @@ features: Description: Contains the Phi type. "); - ExtensionManager extensionManager = new ExtensionManager(new[] { extensionFolder }, new[] { extensionLoader }); + IExtensionManager extensionManager = new ExtensionManager(new[] { extensionFolder }, new[] { extensionLoader }); var testFeature = extensionManager.AvailableExtensions() .SelectMany(x => x.Features) .Single(x => x.Name == "TestFeature"); @@ -329,7 +315,7 @@ features: Description: Contains the Phi type. "); - ExtensionManager extensionManager = new ExtensionManager(new[] { extensionFolder }, new[] { extensionLoader }); + IExtensionManager extensionManager = new ExtensionManager(new[] { extensionFolder }, new[] { extensionLoader }); var testModule = extensionManager.AvailableExtensions() .SelectMany(x => x.Features) .Single(x => x.Name == "TestModule"); @@ -353,7 +339,7 @@ version: 1.0.3 orchardversion: 1 "); - ExtensionManager extensionManager = new ExtensionManager(new[] { extensionFolder }, new[] { extensionLoader }); + IExtensionManager extensionManager = new ExtensionManager(new[] { extensionFolder }, new[] { extensionLoader }); var minimalisticModule = extensionManager.AvailableExtensions().Single(x => x.Name == "Minimalistic"); Assert.That(minimalisticModule.Features.Count(), Is.EqualTo(1)); diff --git a/src/Orchard.Tests/Environment/Extensions/FoldersData/Sample3/Module.txt b/src/Orchard.Tests/Environment/Extensions/FoldersData/Sample3/Module.txt index 44bbc569e..dab08c839 100644 --- a/src/Orchard.Tests/Environment/Extensions/FoldersData/Sample3/Module.txt +++ b/src/Orchard.Tests/Environment/Extensions/FoldersData/Sample3/Module.txt @@ -1 +1 @@ -This is another test.txt +name: This is another test.txt diff --git a/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContainerFactoryTests.cs b/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContainerFactoryTests.cs index bbf204a10..d32d3a3cb 100644 --- a/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContainerFactoryTests.cs +++ b/src/Orchard.Tests/Environment/ShellBuilders/DefaultShellContainerFactoryTests.cs @@ -26,6 +26,7 @@ namespace Orchard.Tests.Environment.ShellBuilders { var builder = new ContainerBuilder(); builder.RegisterType().As(); builder.RegisterType(); + builder.RegisterType().As(); _container = builder.Build(); } diff --git a/src/Orchard.Tests/Orchard.Framework.Tests.csproj b/src/Orchard.Tests/Orchard.Framework.Tests.csproj index 5eda30e2e..c3caa0aa0 100644 --- a/src/Orchard.Tests/Orchard.Framework.Tests.csproj +++ b/src/Orchard.Tests/Orchard.Framework.Tests.csproj @@ -180,6 +180,8 @@ + + diff --git a/src/Orchard.Tests/Stubs/StubCacheManager.cs b/src/Orchard.Tests/Stubs/StubCacheManager.cs new file mode 100644 index 000000000..fd28e5083 --- /dev/null +++ b/src/Orchard.Tests/Stubs/StubCacheManager.cs @@ -0,0 +1,15 @@ +using System; +using Orchard.Caching; + +namespace Orchard.Tests.Stubs { + public class StubCacheManager : ICacheManager { + public TResult Get(TKey key, Func, TResult> acquire) { + var cache = new Cache(); + return cache.Get(key, acquire); + } + + public ICache GetCache() { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Tests/Stubs/StubClock.cs b/src/Orchard.Tests/Stubs/StubClock.cs index 55a247d47..e5c60bb5a 100644 --- a/src/Orchard.Tests/Stubs/StubClock.cs +++ b/src/Orchard.Tests/Stubs/StubClock.cs @@ -16,6 +16,5 @@ namespace Orchard.Tests.Stubs { public DateTime FutureMoment(TimeSpan span) { return UtcNow.Add(span); } - } } diff --git a/src/Orchard.Tests/Stubs/StubWebSiteFolder.cs b/src/Orchard.Tests/Stubs/StubWebSiteFolder.cs new file mode 100644 index 000000000..82e0446ee --- /dev/null +++ b/src/Orchard.Tests/Stubs/StubWebSiteFolder.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Orchard.Caching; +using Orchard.FileSystems.WebSite; + +namespace Orchard.Tests.Stubs { + public class StubWebSiteFolder : IWebSiteFolder { + public IEnumerable ListDirectories(string path) { + if (!Directory.Exists(path)) + return Enumerable.Empty(); + + return Directory.GetDirectories(path); + } + + public string ReadFile(string path) { + if (!File.Exists(path)) + return null; + + return File.ReadAllText(path); + } + + public IVolatileToken WhenPathChanges(string path) { + return new WebSiteFolder.Token(path); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Common/Drivers/BodyDriver.cs b/src/Orchard.Web/Core/Common/Drivers/BodyDriver.cs index 04d56dc88..f7a0a0264 100644 --- a/src/Orchard.Web/Core/Common/Drivers/BodyDriver.cs +++ b/src/Orchard.Web/Core/Common/Drivers/BodyDriver.cs @@ -104,6 +104,10 @@ namespace Orchard.Core.Common.Drivers { // Can be moved somewhere else once we have IoC enabled body text filters. private static string BbcodeReplace(string bodyText) { + + if ( string.IsNullOrEmpty(bodyText) ) + return string.Empty; + Regex urlRegex = new Regex(@"\[url\]([^\]]+)\[\/url\]"); Regex urlRegexWithLink = new Regex(@"\[url=([^\]]+)\]([^\]]+)\[\/url\]"); Regex imgRegex = new Regex(@"\[img\]([^\]]+)\[\/img\]"); diff --git a/src/Orchard.Web/Core/Dashboard/Module.txt b/src/Orchard.Web/Core/Dashboard/Module.txt index e646ae5c2..1fb19522a 100644 --- a/src/Orchard.Web/Core/Dashboard/Module.txt +++ b/src/Orchard.Web/Core/Dashboard/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Dashboard: Description: Standard admin dashboard. - Dependencies: Common Category: Core \ No newline at end of file diff --git a/src/Orchard.Web/Core/Feeds/Module.txt b/src/Orchard.Web/Core/Feeds/Module.txt index 1b2ba39c1..eb1f5b157 100644 --- a/src/Orchard.Web/Core/Feeds/Module.txt +++ b/src/Orchard.Web/Core/Feeds/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Feeds: Description: RSS feeds for content items. - Dependencies: Common Category: Syndication \ No newline at end of file diff --git a/src/Orchard.Web/Core/HomePage/Module.txt b/src/Orchard.Web/Core/HomePage/Module.txt index b4a95af7e..63404f28d 100644 --- a/src/Orchard.Web/Core/HomePage/Module.txt +++ b/src/Orchard.Web/Core/HomePage/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: HomePage: Description: Standard site home page that allows a specified content type or container to *be* the home page. - Dependencies: Common Category: Core \ No newline at end of file diff --git a/src/Orchard.Web/Core/Navigation/Module.txt b/src/Orchard.Web/Core/Navigation/Module.txt index adbfd4438..31ec9b758 100644 --- a/src/Orchard.Web/Core/Navigation/Module.txt +++ b/src/Orchard.Web/Core/Navigation/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Navigation: Description: Menu management. - Dependencies: Common Category: Core \ No newline at end of file diff --git a/src/Orchard.Web/Core/Scheduling/Module.txt b/src/Orchard.Web/Core/Scheduling/Module.txt index 848b44124..e5026374d 100644 --- a/src/Orchard.Web/Core/Scheduling/Module.txt +++ b/src/Orchard.Web/Core/Scheduling/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Scheduling: Description: Scheduled background tasks. - Dependencies: Common Category: Core \ No newline at end of file diff --git a/src/Orchard.Web/Core/Settings/Module.txt b/src/Orchard.Web/Core/Settings/Module.txt index b5cd0527d..5e4f413c7 100644 --- a/src/Orchard.Web/Core/Settings/Module.txt +++ b/src/Orchard.Web/Core/Settings/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Settings: Description: Site settings. - Dependencies: Common Category: Core \ No newline at end of file diff --git a/src/Orchard.Web/Core/XmlRpc/Module.txt b/src/Orchard.Web/Core/XmlRpc/Module.txt index 5db3d574c..6ab5a799d 100644 --- a/src/Orchard.Web/Core/XmlRpc/Module.txt +++ b/src/Orchard.Web/Core/XmlRpc/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: XmlRpc: Description: XML-RPC opt-in implementation. - Dependencies: Common - Category: Core \ No newline at end of file + Category: Content Publishing \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Futures.Widgets/Module.txt b/src/Orchard.Web/Modules/Futures.Widgets/Module.txt index ccc415c58..827ac7017 100644 --- a/src/Orchard.Web/Modules/Futures.Widgets/Module.txt +++ b/src/Orchard.Web/Modules/Futures.Widgets/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Futures.Widgets: Description: Widgets container with simple inline content editing widget. - Dependencies: Common Category: Widget \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt b/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt index 52f596e33..f1e73406c 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt @@ -7,5 +7,8 @@ orchardversion: 0.1.2010.0312 features: Orchard.Blogs: Description: A simple web log. - Dependencies: Common, XmlRpc - Category: Content \ No newline at end of file + Category: Content + Remote Blog Publishing: + Description: Blog easier using a dedicated MetaWeblogAPI-compatible publishing tool. + Dependencies: XmlRpc + Category: Content Publishing \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs index da6094ea8..2c14b76de 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Services/XmlRpcHandler.cs @@ -8,6 +8,7 @@ using Orchard.Blogs.Models; using Orchard.ContentManagement; using Orchard.Core.XmlRpc; using Orchard.Core.XmlRpc.Models; +using Orchard.Environment.Extensions; using Orchard.Logging; using Orchard.Mvc.Extensions; using Orchard.Security; @@ -15,6 +16,7 @@ using Orchard.Blogs.Extensions; namespace Orchard.Blogs.Services { [UsedImplicitly] + [OrchardFeature("Remote Blog Publishing")] public class XmlRpcHandler : IXmlRpcHandler { private readonly IBlogService _blogService; private readonly IBlogPostService _blogPostService; diff --git a/src/Orchard.Web/Modules/Orchard.Comments/Module.txt b/src/Orchard.Web/Modules/Orchard.Comments/Module.txt index 37fe5a54a..d863f49bb 100644 --- a/src/Orchard.Web/Modules/Orchard.Comments/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Comments/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Orchard.Comments: Description: Standard content item comments. - Dependencies: Common Category: Social \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Module.txt b/src/Orchard.Web/Modules/Orchard.DevTools/Module.txt index 0d8dbccc9..9d886eed2 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Orchard.DevTools: Description: An assortment of debuging tools. - Dependencies: Common Category: Developer \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Media/Module.txt b/src/Orchard.Web/Modules/Orchard.Media/Module.txt index 4f96e9b36..7a2730d9a 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Media/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Orchard.Media: Description: File system based media upload, storage and management. - Dependencies: Common Category: Media \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs index 3a577894b..a45979b33 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs @@ -1,11 +1,8 @@ using System.Linq; -using System.Reflection; using System.Web.Mvc; using Orchard.Localization; using Orchard.Modules.ViewModels; -using Orchard.Mvc.AntiForgery; using Orchard.Mvc.Results; -using Orchard.UI.Notify; namespace Orchard.Modules.Controllers { public class AdminController : Controller { @@ -28,20 +25,6 @@ namespace Orchard.Modules.Controllers { return View(new ModulesIndexViewModel {Modules = modules}); } - public ActionResult Edit(string id) { - if (!Services.Authorizer.Authorize(Permissions.ManageModules, T("Not allowed to edit module"))) - return new HttpUnauthorizedResult(); - - var module = _moduleService.GetModuleByName(id); - - if (module == null) - return new NotFoundResult(); - - return View(new ModuleEditViewModel { - Name = module.DisplayName - }); - } - public ActionResult Features() { if (!Services.Authorizer.Authorize(Permissions.ManageFeatures, T("Not allowed to manage features"))) return new HttpUnauthorizedResult(); @@ -50,45 +33,30 @@ namespace Orchard.Modules.Controllers { return View(new FeaturesViewModel {Features = features}); } - [ValidateAntiForgeryTokenOrchard] - public ActionResult Enable(string id) { + [HttpPost] + public ActionResult Enable(string id, bool? force) { if (!Services.Authorizer.Authorize(Permissions.ManageFeatures, T("Not allowed to manage features"))) return new HttpUnauthorizedResult(); if (string.IsNullOrEmpty(id)) return new NotFoundResult(); - _moduleService.EnableFeatures(new [] {id}); - Services.Notifier.Information(T("{0} was enabled", id)); + _moduleService.EnableFeatures(new[] {id}, force != null && (bool) force); return RedirectToAction("Features"); } - [ValidateAntiForgeryTokenOrchard] - public ActionResult Disable(string id) { + [HttpPost] + public ActionResult Disable(string id, bool? force) { if (!Services.Authorizer.Authorize(Permissions.ManageFeatures, T("Not allowed to manage features"))) return new HttpUnauthorizedResult(); if (string.IsNullOrEmpty(id)) return new NotFoundResult(); - _moduleService.DisableFeatures(new[] { id }); - //Services.Notifier.Information(T("{0} was disabled", featureName)); + _moduleService.DisableFeatures(new[] {id}, force != null && (bool) force); return RedirectToAction("Features"); } - - private class FormValueRequiredAttribute : ActionMethodSelectorAttribute { - private readonly string _submitButtonName; - - public FormValueRequiredAttribute(string submitButtonName) { - _submitButtonName = submitButtonName; - } - - public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) { - var value = controllerContext.HttpContext.Request.Form[_submitButtonName]; - return !string.IsNullOrEmpty(value); - } - } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Extensions/StringExtensions.cs b/src/Orchard.Web/Modules/Orchard.Modules/Extensions/StringExtensions.cs new file mode 100644 index 000000000..69ce06cf9 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Modules/Extensions/StringExtensions.cs @@ -0,0 +1,13 @@ +using System; +using Orchard.Localization; +using Orchard.Utility.Extensions; + +namespace Orchard.Modules.Extensions { + public static class StringExtensions { + public static string AsFeatureId(this string text, Func localize) { + return string.IsNullOrEmpty(text) + ? "" + : string.Format(localize("{0} feature").ToString(), text).HtmlClassify(); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Module.txt b/src/Orchard.Web/Modules/Orchard.Modules/Module.txt index 8414688c6..d644877cf 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Modules/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Orchard.Modules: Description: Standard module and feature management. - Dependencies: Common Category: Core \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Orchard.Modules.csproj b/src/Orchard.Web/Modules/Orchard.Modules/Orchard.Modules.csproj index 8fd09dac4..f13d12acc 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Orchard.Modules.csproj +++ b/src/Orchard.Web/Modules/Orchard.Modules/Orchard.Modules.csproj @@ -64,6 +64,7 @@ + @@ -89,7 +90,6 @@ - diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs b/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs index 67307b434..917d318ae 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs @@ -6,7 +6,9 @@ using Orchard.Environment.Extensions; using Orchard.Environment.Extensions.Models; using Orchard.Environment.Topology; using Orchard.Environment.Topology.Models; +using Orchard.Localization; using Orchard.Modules.Models; +using Orchard.UI.Notify; namespace Orchard.Modules.Services { public class ModuleService : IModuleService { @@ -14,21 +16,32 @@ namespace Orchard.Modules.Services { private readonly IExtensionManager _extensionManager; private readonly IShellDescriptorManager _shellDescriptorManager; - public ModuleService(IExtensionManager extensionManager, IShellDescriptorManager shellDescriptorManager) { + public ModuleService(IOrchardServices orchardServices, IExtensionManager extensionManager, + IShellDescriptorManager shellDescriptorManager) { + Services = orchardServices; _extensionManager = extensionManager; _shellDescriptorManager = shellDescriptorManager; + T = NullLocalizer.Instance; } + private Localizer T { get; set; } + public IOrchardServices Services { get; set; } + public IModule GetModuleByName(string moduleName) { - return _extensionManager.AvailableExtensions().Where(e => string.Equals(e.Name, moduleName, StringComparison.OrdinalIgnoreCase) && string.Equals(e.ExtensionType, ModuleExtensionType, StringComparison.OrdinalIgnoreCase)).Select( - descriptor => AssembleModuleFromDescriptor(descriptor)).FirstOrDefault(); + return + _extensionManager.AvailableExtensions().Where( + e => + string.Equals(e.Name, moduleName, StringComparison.OrdinalIgnoreCase) && + string.Equals(e.ExtensionType, ModuleExtensionType, StringComparison.OrdinalIgnoreCase)).Select( + descriptor => AssembleModuleFromDescriptor(descriptor)).FirstOrDefault(); } public IEnumerable GetInstalledModules() { return _extensionManager.AvailableExtensions().Where( - e => String.Equals(e.ExtensionType, ModuleExtensionType, StringComparison.OrdinalIgnoreCase)).Select( - descriptor => AssembleModuleFromDescriptor(descriptor)); + e => String.Equals(e.ExtensionType, ModuleExtensionType, StringComparison.OrdinalIgnoreCase)).Select + ( + descriptor => AssembleModuleFromDescriptor(descriptor)); } public void InstallModule(HttpPostedFileBase file) { @@ -39,52 +52,145 @@ namespace Orchard.Modules.Services { _extensionManager.UninstallExtension(ModuleExtensionType, moduleName); } - public IModule GetModuleByFeatureName(string featureName) { - return GetInstalledModules() - .Where( - m => - m.Features.FirstOrDefault(f => string.Equals(f.Name, featureName, StringComparison.OrdinalIgnoreCase)) != - null).FirstOrDefault(); - } - public IEnumerable GetAvailableFeatures() { var enabledFeatures = _shellDescriptorManager.GetShellDescriptor().EnabledFeatures; return GetInstalledModules() .SelectMany(m => _extensionManager.LoadFeatures(m.Features)) - .Select(f => AssembleModuleFromDescriptor(f, enabledFeatures.FirstOrDefault(sf => string.Equals(sf.Name, f.Descriptor.Name, StringComparison.OrdinalIgnoreCase)) != null)); - } - - public IEnumerable GetAvailableFeaturesByModule(string moduleName) { - throw new NotImplementedException(); + .Select( + f => + AssembleModuleFromDescriptor(f, + enabledFeatures.FirstOrDefault( + sf => + string.Equals(sf.Name, f.Descriptor.Name, + StringComparison.OrdinalIgnoreCase)) != null)); } public void EnableFeatures(IEnumerable featureNames) { + EnableFeatures(featureNames, false); + } + + public void EnableFeatures(IEnumerable features, bool force) { var shellDescriptor = _shellDescriptorManager.GetShellDescriptor(); + var enabledFeatures = shellDescriptor.EnabledFeatures.ToList(); - var enabledFeatures = shellDescriptor.EnabledFeatures - .Union(featureNames.Select(s => new ShellFeature {Name = s})); + var featuresToEnable = + features.Select(s => EnableFeature(s, GetAvailableFeatures(), force)). + SelectMany(ies => ies.Select(s => s)); - _shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures, shellDescriptor.Parameters); + if (featuresToEnable.Count() == 0) + return; + + foreach (var featureToEnable in featuresToEnable) { + enabledFeatures.Add(new ShellFeature {Name = featureToEnable}); + Services.Notifier.Information(T("{0} was enabled", featureToEnable)); + } + + _shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures, + shellDescriptor.Parameters); } public void DisableFeatures(IEnumerable featureNames) { + DisableFeatures(featureNames, false); + } + + public void DisableFeatures(IEnumerable features, bool force) { var shellDescriptor = _shellDescriptorManager.GetShellDescriptor(); var enabledFeatures = shellDescriptor.EnabledFeatures.ToList(); - var features = GetAvailableFeatures().ToList(); - foreach (var featureName in featureNames) { - var feature = featureName; - var dependants = features.Where(f => f.IsEnabled && f.Descriptor.Dependencies != null && f.Descriptor.Dependencies.Contains(feature)); + var featuresToDisable = + features.Select(s => DisableFeature(s, GetAvailableFeatures(), force)).SelectMany( + ies => ies.Select(s => s)); - if (dependants.Count() == 0) { - enabledFeatures.RemoveAll(f => f.Name == feature); - } - else { - // list what else will be disabled with ok/cancel - } + if (featuresToDisable.Count() == 0) + return; + + foreach (var featureToDisable in featuresToDisable) { + var feature = featureToDisable; + enabledFeatures.RemoveAll(f => f.Name == feature); + Services.Notifier.Information(T("{0} was disabled", feature)); } - _shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures, shellDescriptor.Parameters); + _shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures, + shellDescriptor.Parameters); + } + + public IModule GetModuleByFeatureName(string featureName) { + return GetInstalledModules() + .Where( + m => + m.Features.FirstOrDefault( + f => string.Equals(f.Name, featureName, StringComparison.OrdinalIgnoreCase)) != + null).FirstOrDefault(); + } + + private IEnumerable EnableFeature(string featureName, IEnumerable features, bool force) { + var featuresList = features.ToList(); + var getDisabledDependencies = + new Func, IEnumerable>( + (n, fs) => { + var feature = fs.Single(f => f.Descriptor.Name == n); + return feature.Descriptor.Dependencies != null + ? feature.Descriptor.Dependencies.Select( + fn => fs.Single(f => f.Descriptor.Name == fn)).Where(f => !f.IsEnabled) + : Enumerable.Empty(); + }); + + var featuresToEnable = GetAffectedFeatures(featureName, featuresList, getDisabledDependencies); + + if (featuresToEnable.Count() > 1 && !force) { + GenerateWarning("If you want {0} enabled, then you'll also need to enable {1}.", + featureName, + featuresToEnable.Where(fn => fn != featureName)); + return Enumerable.Empty(); + } + + return featuresToEnable; + } + + private IEnumerable DisableFeature(string featureName, IEnumerable features, bool force) { + var featuresList = features.ToList(); + var getEnabledDependants = + new Func, IEnumerable>( + (n, fs) => fs.Where(f => f.IsEnabled && f.Descriptor.Dependencies != null && f.Descriptor.Dependencies.Contains(n))); + + var featuresToDisable = GetAffectedFeatures(featureName, featuresList, getEnabledDependants); + + if (featuresToDisable.Count() > 1 && !force) { + GenerateWarning("If {0} is disabled, then you'll also lose {1}.", + featureName, + featuresToDisable.Where(fn => fn != featureName)); + return Enumerable.Empty(); + } + + return featuresToDisable; + } + + private static IEnumerable GetAffectedFeatures(string featureName, IEnumerable features, Func, IEnumerable> getAffectedDependencies) { + var dependencies = new List {featureName}; + + foreach (var dependency in getAffectedDependencies(featureName, features)) + dependencies.AddRange(GetAffectedFeatures(dependency.Descriptor.Name, features, getAffectedDependencies)); + + return dependencies; + } + + private void GenerateWarning(string messageFormat, string featureName, IEnumerable featuresInQuestion) { + if (featuresInQuestion.Count() < 1) + return; + + Services.Notifier.Warning(T( + messageFormat, + featureName, + featuresInQuestion.Count() > 1 + ? string.Join("", + featuresInQuestion.Select( + (fn, i) => + T(i == featuresInQuestion.Count() - 1 + ? "{0}" + : (i == featuresInQuestion.Count() - 2 + ? "{0} and " + : "{0}, "), fn).ToString()).ToArray()) + : featuresInQuestion.First())); } private static IModule AssembleModuleFromDescriptor(ExtensionDescriptor extensionDescriptor) { diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Edit.ascx b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Edit.ascx deleted file mode 100644 index 303004ee2..000000000 --- a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Edit.ascx +++ /dev/null @@ -1,5 +0,0 @@ -<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> -<%@ Import Namespace="Orchard.Mvc.Html"%> -<%@ Import Namespace="Orchard.Modules.ViewModels"%> -

<%=Html.TitleForPage(T("Edit Module: {0}", Model.Name).ToString()) %>

-

<%=_Encoded("Edit the module. Maybe show module's features.") %>

\ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx index ed2e6fd75..47dda8aae 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx +++ b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx @@ -1,4 +1,5 @@ <%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> +<%@ Import Namespace="Orchard.Modules.Extensions" %> <%@ Import Namespace="Orchard.Mvc.Html"%> <%@ Import Namespace="Orchard.Modules.ViewModels"%> <%@ Import Namespace="Orchard.Utility.Extensions" %><% @@ -13,14 +14,17 @@ if (featureGroup == featureGroups.First()) categoryClassName += " first"; if (featureGroup == featureGroups.Last()) - categoryClassName += " last"; %> + categoryClassName += " last"; + + //temporarily "disable" actions on core features + var showActions = categoryName.ToString() != "Core"; %>
  • <%=Html.Encode(categoryName) %>

      <% var features = featureGroup.OrderBy(f => f.Descriptor.Name); foreach (var feature in features) { //hmmm...I feel like I've done this before... - var featureId = string.Format("{0} feature", feature.Descriptor.Name).HtmlClassify(); + var featureId = feature.Descriptor.Name.AsFeatureId(n => T(n)); var featureState = feature.IsEnabled ? "enabled" : "disabled"; var featureClassName = string.Format("feature {0}", featureState); if (feature == features.First()) @@ -36,26 +40,30 @@

      <%=_Encoded("Depends on:")%>

      <%=Html.UnorderedList( feature.Descriptor.Dependencies.OrderBy(s => s), - (s, i) => Html.Link(s, string.Format("#{0}", string.Format("{0} feature", s).HtmlClassify())), + (s, i) => Html.Link(s, string.Format("#{0}", s.AsFeatureId(n => T(n)))), "", "dependency", "") %> <% } %> - + <% + if (showActions) { %>
      <% if (feature.IsEnabled) { - using (Html.BeginFormAntiForgeryPost(string.Format("{0}#{1}", Url.Action("Disable", new { area = "Orchard.Modules" }), featureId), FormMethod.Post, new {@class = "inline link"})) { %> + using (Html.BeginFormAntiForgeryPost(string.Format("{0}", Url.Action("Disable", new { area = "Orchard.Modules" })), FormMethod.Post, new {@class = "inline link"})) { %> <%=Html.Hidden("id", feature.Descriptor.Name, new { id = "" })%> + <%=Html.Hidden("force", true)%> <% } } else { - using (Html.BeginFormAntiForgeryPost(string.Format("{0}#{1}", Url.Action("Enable", new { area = "Orchard.Modules" }), featureId), FormMethod.Post, new {@class = "inline link"})) { %> + using (Html.BeginFormAntiForgeryPost(string.Format("{0}", Url.Action("Enable", new { area = "Orchard.Modules" })), FormMethod.Post, new {@class = "inline link"})) { %> <%=Html.Hidden("id", feature.Descriptor.Name, new { id = "" })%> + <%=Html.Hidden("force", true)%> <% } } %> -
      + <% + } %> <% } %> diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Index.ascx b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Index.ascx index c54567b93..14f21e480 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Index.ascx +++ b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Index.ascx @@ -1,4 +1,5 @@ <%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> +<%@ Import Namespace="Orchard.Modules.Extensions" %> <%@ Import Namespace="Orchard.Mvc.Html"%> <%@ Import Namespace="Orchard.Modules.ViewModels"%>

      <%=Html.TitleForPage(T("Installed Modules").ToString()) %>

      @@ -14,15 +15,11 @@

      <%=Html.Encode(module.DisplayName) %>

      • <%=T("Version: {0}", !string.IsNullOrEmpty(module.Version) ? Html.Encode(module.Version) : T("1.0")) %>
      • -
      •  | <%=T("Features: {0}", string.Join(", ", module.Features.Select(f => Html.Link(Html.Encode(f.Name), string.Format("{0}#{1}", Url.Action("features", new { area = "Orchard.Modules" }), Html.Encode(f.Name)) )).OrderBy(s => s).ToArray())) %>
      • +
      •  | <%=T("Features: {0}", string.Join(", ", module.Features.Select(f => Html.Link(Html.Encode(f.Name), string.Format("{0}#{1}", Url.Action("features", new { area = "Orchard.Modules" }), f.Name.AsFeatureId(n => T(n))) )).OrderBy(s => s).ToArray())) %>
      •  | <%=T("Author: {0}", !string.IsNullOrEmpty(module.Author) ? Html.Encode(module.Author) : (new []{"Bradley", "Bertrand", "Renaud", "Suha", "Sebastien", "Jon", "Nathan", "Erik"})[(module.DisplayName.Length + (new Random()).Next()) % 7]) %>
      • <%-- very efficient, I know --%>
      •  | <%=T("Website: {0}", !string.IsNullOrEmpty(module.HomePage) ? Html.Encode(module.HomePage) : T("http://orchardproject.net"))%>
      - <%----%> <% if (!string.IsNullOrEmpty(module.Description)) { %>

      <%=Html.Encode(module.Description) %>

      <% diff --git a/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css b/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css index 0da79a4e4..3041b4688 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css +++ b/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css @@ -1,14 +1,18 @@ -.features .category { +.orchard-modules #main h2 { + border:0; + margin-bottom:.2em; +} + +.features .category { overflow:hidden; } .features .feature { border:1px solid #EAEAEA; - -moz-border-radius:3px; - -webkit-border-radius:3px; display:block; float:left; - height:10em; + height:5em; margin:0 .5% 1% .5%; + position:relative; width:32.1%; } .features .feature:nth-child(3n+1), @@ -29,10 +33,53 @@ } .features .enabled.feature { - background:#D1F2A5; - border-color:#BCD994; + background:#FFF; + border-color:#CFE493;cfe493 } .features .disabled.feature { background:#EAEAEA; border-color:#CCC; +} +.features .feature .summary { + overflow:hidden; + padding:.4em .5em; +} +.features .dependencies li, +.features .actions { + font-size:1.4em; +} +.features .dependencies { + font-size:.9em; + margin:.44em 0 0; +} +.features .dependencies>* { + display:inline; +} +.features .dependencies li { + display:inline; + margin-left:.5em; +} +.features .dependencies li::after { + content:", "; +} +.features .dependencies li:last-child::after { + content:""; +} +.features .feature .actions { + position:absolute; + right:.4em; + top:.6em; +} + +.cathedral { + bottom:0; + font-size:.8em; + position:absolute; + right:3px; +} +.cathedral a, +.cathedral a:link, +.cathedral a:visited, +.cathedral form.inline.link button { + color:#aeaeae; } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MultiTenancy/Module.txt b/src/Orchard.Web/Modules/Orchard.MultiTenancy/Module.txt index 53c124af0..fd00b570b 100644 --- a/src/Orchard.Web/Modules/Orchard.MultiTenancy/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.MultiTenancy/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Orchard.MultiTenancy: Description: Configure multiple site tenants. - Dependencies: Common - Category: Core \ No newline at end of file + Category: Hosting \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Pages/Module.txt b/src/Orchard.Web/Modules/Orchard.Pages/Module.txt index 1ade81120..f7100c9c9 100644 --- a/src/Orchard.Web/Modules/Orchard.Pages/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Pages/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Orchard.Pages: Description: Simple pages. - Dependencies: Common Category: Content \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Roles/Module.txt b/src/Orchard.Web/Modules/Orchard.Roles/Module.txt index 32fd2408d..30653aa79 100644 --- a/src/Orchard.Web/Modules/Orchard.Roles/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Roles/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Orchard.Roles: Description: Standard user roles. - Dependencies: Common Category: Core \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Roles/Services/RolesBasedAuthorizationService.cs b/src/Orchard.Web/Modules/Orchard.Roles/Services/RolesBasedAuthorizationService.cs index d7a84b18d..a74ed21d0 100644 --- a/src/Orchard.Web/Modules/Orchard.Roles/Services/RolesBasedAuthorizationService.cs +++ b/src/Orchard.Web/Modules/Orchard.Roles/Services/RolesBasedAuthorizationService.cs @@ -84,6 +84,8 @@ namespace Orchard.Roles.Services { context.Adjusted = false; _authorizationServiceEventHandler.Adjust(context); + if (!context.Adjusted) + break; } _authorizationServiceEventHandler.Complete(context); diff --git a/src/Orchard.Web/Modules/Orchard.Sandbox/Module.txt b/src/Orchard.Web/Modules/Orchard.Sandbox/Module.txt index 488adb7de..81a3967b7 100644 --- a/src/Orchard.Web/Modules/Orchard.Sandbox/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Sandbox/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Orchard.Sandbox: Description: A module to mess around with. Currently wiki-like. - Dependencies: Common Category: Developer \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Module.txt b/src/Orchard.Web/Modules/Orchard.Setup/Module.txt index 1d87f1edd..069cdb7e3 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Setup/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Orchard.Setup: Description: Standard site setup. - Dependencies: Common Category: Core \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Tags/Module.txt b/src/Orchard.Web/Modules/Orchard.Tags/Module.txt index 490dc5654..b7bf7e204 100644 --- a/src/Orchard.Web/Modules/Orchard.Tags/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Tags/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Orchard.Tags: Description: Tag a content item. - Dependencies: Common Category: Navigation \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Themes/Module.txt b/src/Orchard.Web/Modules/Orchard.Themes/Module.txt index f2c729ec6..393b530ec 100644 --- a/src/Orchard.Web/Modules/Orchard.Themes/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Themes/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Orchard.Themes: Description: Basic theming capability. - Dependencies: Common Category: Display \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Users/Module.txt b/src/Orchard.Web/Modules/Orchard.Users/Module.txt index 7cf61082f..ad2f24f64 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Users/Module.txt @@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312 features: Orchard.Users: Description: Standard users. - Dependencies: Common Category: Core \ No newline at end of file diff --git a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css index af33ef011..96a7c5011 100644 --- a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css +++ b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css @@ -320,8 +320,8 @@ span.message { } .confirmation.message { - background:#e6f1c9; /* green */ - border:1px solid #cfe493; + background:#D1F2A5; /* green */ + border:1px solid #BCD994; } .warning.message { background:#fdf5bc; /* yellow */ @@ -337,8 +337,8 @@ span.message { color:#fff; } .info.message { - background:#e6f1c9; /* green*/ - border:1px solid #d4deb9; + background:#e6f1c9; /* green */ + border:1px solid #cfe493; color:#062232; } .debug.message { diff --git a/src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs b/src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs index cac09fef5..c8dd79a7e 100644 --- a/src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs +++ b/src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs @@ -2,9 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Web.Hosting; using Orchard.Caching; -using Orchard.Environment.Extensions.Helpers; using Orchard.Environment.Extensions.Models; using Orchard.FileSystems.WebSite; using Yaml.Grammar; @@ -56,7 +54,7 @@ namespace Orchard.Environment.Extensions.Folders { return list; } - ExtensionDescriptor GetExtensionDescriptor(string locationPath, string extensionName, string manifestPath) { + private ExtensionDescriptor GetExtensionDescriptor(string locationPath, string extensionName, string manifestPath) { return _cacheManager.Get(manifestPath, context => { context.Monitor(_webSiteFolder.WhenPathChanges(manifestPath)); @@ -75,33 +73,23 @@ namespace Orchard.Environment.Extensions.Folders { }); } - public IEnumerable ListNames() { - foreach (var path in _paths) { - if (!Directory.Exists(PathHelpers.GetPhysicalPath(path))) - continue; - - foreach (var directoryName in Directory.GetDirectories(PathHelpers.GetPhysicalPath(path))) { - if (_manifestIsOptional || File.Exists(Path.Combine(directoryName, _manifestName))) { - yield return Path.GetFileName(directoryName); - } - } - } + private ExtensionDescriptor GetDescriptorForExtension(string locationPath, string extensionName, ParseResult parseResult) { + return GetDescriptorForExtension(locationPath, extensionName, _extensionType, parseResult); } - public ParseResult ParseManifest(string name) { + public static ParseResult ParseManifest(string manifestText) { bool success; - var yamlStream = new YamlParser().ParseYamlStream(new TextInput(name), out success); + var yamlStream = new YamlParser().ParseYamlStream(new TextInput(manifestText), out success); if (yamlStream == null || !success) { return null; } return new ParseResult { - Name = name, + Name = manifestText, YamlDocument = yamlStream.Documents.Single() }; } - - private ExtensionDescriptor GetDescriptorForExtension(string locationPath, string extensionName, ParseResult parseResult) { + public static ExtensionDescriptor GetDescriptorForExtension(string locationPath, string extensionName, string extensionType, ParseResult parseResult) { var mapping = (Mapping)parseResult.YamlDocument.Root; var fields = mapping.Entities .Where(x => x.Key is Scalar) @@ -110,7 +98,7 @@ namespace Orchard.Environment.Extensions.Folders { var extensionDescriptor = new ExtensionDescriptor { Location = locationPath, Name = extensionName, - ExtensionType = _extensionType, + ExtensionType = extensionType, DisplayName = GetValue(fields, "name") ?? extensionName, Description = GetValue(fields, "description"), Version = GetValue(fields, "version"), @@ -125,14 +113,14 @@ namespace Orchard.Environment.Extensions.Folders { } private static IEnumerable GetFeaturesForExtension(Mapping features, ExtensionDescriptor extensionDescriptor) { - List featureDescriptors = new List(); + var featureDescriptors = new List(); if (features != null) { foreach (var entity in features.Entities) { - FeatureDescriptor featureDescriptor = new FeatureDescriptor { + var featureDescriptor = new FeatureDescriptor { Extension = extensionDescriptor, Name = entity.Key.ToString(), }; - Mapping featureMapping = (Mapping)entity.Value; + var featureMapping = (Mapping)entity.Value; foreach (var featureEntity in featureMapping.Entities) { if (String.Equals(featureEntity.Key.ToString(), "description", StringComparison.OrdinalIgnoreCase)) { featureDescriptor.Description = featureEntity.Value.ToString(); @@ -158,25 +146,19 @@ namespace Orchard.Environment.Extensions.Folders { } private static string[] ParseFeatureDependenciesEntry(string dependenciesEntry) { - List dependencies = new List(); + var dependencies = new List(); foreach (var s in dependenciesEntry.Split(',')) { dependencies.Add(s.Trim()); } return dependencies.ToArray(); } - private static Mapping GetMapping( - IDictionary fields, - string key) { - + private static Mapping GetMapping(IDictionary fields, string key) { DataItem value; return fields.TryGetValue(key, out value) ? (Mapping)value : null; } - private static string GetValue( - IDictionary fields, - string key) { - + private static string GetValue(IDictionary fields, string key) { DataItem value; return fields.TryGetValue(key, out value) ? value.ToString() : null; } diff --git a/src/Orchard/Environment/Extensions/Folders/IExtensionFolders.cs b/src/Orchard/Environment/Extensions/Folders/IExtensionFolders.cs index 527a3a024..94612540a 100644 --- a/src/Orchard/Environment/Extensions/Folders/IExtensionFolders.cs +++ b/src/Orchard/Environment/Extensions/Folders/IExtensionFolders.cs @@ -6,6 +6,4 @@ namespace Orchard.Environment.Extensions.Folders { public interface IExtensionFolders { IEnumerable AvailableExtensions(); } - - } \ No newline at end of file diff --git a/src/Orchard/Modules/IModuleService.cs b/src/Orchard/Modules/IModuleService.cs index d2792315e..a4033bb84 100644 --- a/src/Orchard/Modules/IModuleService.cs +++ b/src/Orchard/Modules/IModuleService.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Web; -using Orchard.Environment.Extensions.Models; namespace Orchard.Modules { public interface IModuleService : IDependency { @@ -8,9 +7,10 @@ namespace Orchard.Modules { IEnumerable GetInstalledModules(); void InstallModule(HttpPostedFileBase file); void UninstallModule(string moduleName); - IModule GetModuleByFeatureName(string featureName); IEnumerable GetAvailableFeatures(); void EnableFeatures(IEnumerable featureNames); + void EnableFeatures(IEnumerable featureNames, bool force); void DisableFeatures(IEnumerable featureNames); + void DisableFeatures(IEnumerable featureNames, bool force); } } \ No newline at end of file diff --git a/src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs b/src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs new file mode 100644 index 000000000..a5a39f1eb --- /dev/null +++ b/src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web.Mvc; +using System.Web.Caching; +using System.Web; +using System.Web.Hosting; + +namespace Orchard.Mvc.ViewEngines { + public class ThemeViewLocationCache : IViewLocationCache { + private readonly string _requestTheme; + + public ThemeViewLocationCache(string requestTheme) { + _requestTheme = requestTheme; + } + + private string AlterKey(string key) { + return key + ":" + _requestTheme; + } + + public string GetViewLocation(HttpContextBase httpContext, string key) { + if (httpContext == null) { + throw new ArgumentNullException("httpContext"); + } + + return (string)httpContext.Cache[AlterKey(key)]; + } + + public void InsertViewLocation(HttpContextBase httpContext, string key, string virtualPath) { + if (httpContext == null) { + throw new ArgumentNullException("httpContext"); + } + + httpContext.Cache.Insert(AlterKey(key), virtualPath, new CacheDependency(HostingEnvironment.MapPath("~/Themes"))); + } + } +} diff --git a/src/Orchard/Mvc/ViewEngines/WebFormsViewEngineProvider.cs b/src/Orchard/Mvc/ViewEngines/WebFormsViewEngineProvider.cs index 24a425b44..6192160fb 100644 --- a/src/Orchard/Mvc/ViewEngines/WebFormsViewEngineProvider.cs +++ b/src/Orchard/Mvc/ViewEngines/WebFormsViewEngineProvider.cs @@ -31,6 +31,8 @@ namespace Orchard.Mvc.ViewEngines { AreaPartialViewLocationFormats = DisabledFormats, }; + viewEngine.ViewLocationCache = new ThemeViewLocationCache(parameters.VirtualPath); + // enable /Views/{partialName} // enable /Views/"DisplayTemplates/"+{templateName} // enable /Views/"EditorTemplates/+{templateName} diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 17d230cb7..56bc24cd4 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -241,6 +241,7 @@ + ASPXCodeBehind diff --git a/src/Orchard/Security/IAuthorizationServiceEventHandler.cs b/src/Orchard/Security/IAuthorizationServiceEventHandler.cs index 60b0e05e4..84acaec5d 100644 --- a/src/Orchard/Security/IAuthorizationServiceEventHandler.cs +++ b/src/Orchard/Security/IAuthorizationServiceEventHandler.cs @@ -13,7 +13,12 @@ namespace Orchard.Security { public Permission Permission { get; set; } public IUser User { get; set; } public IContent Content { get; set; } + + // true if the permission has been granted to the user. public bool Granted { get; set; } + + // if context.Permission was modified during an Adjust(context) in an event handler, Adjusted should be set to true. + // It means that the permission check will be done again by the framework. public bool Adjusted { get; set; } } }