From e00dd3d34c1c2798afb99413e8496c51a77fb00d Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Tue, 18 May 2010 07:26:29 -0700 Subject: [PATCH 01/17] Tightening up the feature management UI a bit --HG-- branch : dev --- .../Modules/Orchard.Modules/styles/admin.css | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css b/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css index 0da79a4e4..bed7b7169 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css +++ b/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css @@ -3,12 +3,11 @@ } .features .feature { border:1px solid #EAEAEA; - -moz-border-radius:3px; - -webkit-border-radius:3px; display:block; float:left; - height:10em; + height:6.8em; margin:0 .5% 1% .5%; + position:relative; width:32.1%; } .features .feature:nth-child(3n+1), @@ -35,4 +34,34 @@ .features .disabled.feature { background:#EAEAEA; border-color:#CCC; -} \ No newline at end of file +} +.features .feature .summary { + overflow:hidden; + padding:.4em .5em; +} +.features .dependencies li, +.features .actions a { + font-size:1.4em; +} +.features .dependencies { + font-size:.9em; + margin:.44em 0 0; +} +.features .dependencies>* { + display:inline; +} +.features .dependencies li { + display:inline; + margin-left:.5ex; +} +.features .dependencies li::after { + content:", "; +} +.features .dependencies li:last-child::after { + content:""; +} +.features .feature .actions { + position:absolute; + right:.8em; + top:.6em; +} From 0f5d4923331a1eebf0a28064accf00dbcd55bdf8 Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Tue, 18 May 2010 10:04:14 -0700 Subject: [PATCH 02/17] Hooked up dependeny checks and messages for unsatisified feature dependencies on enable/disable --HG-- branch : dev --- .../Controllers/AdminController.cs | 2 - .../Orchard.Modules/Services/ModuleService.cs | 59 ++++++++++++++++--- .../Orchard.Modules/Views/Admin/Features.ascx | 4 +- .../Themes/TheAdmin/Styles/site.css | 8 +-- 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs index 3a577894b..84060a88f 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs @@ -59,7 +59,6 @@ namespace Orchard.Modules.Controllers { return new NotFoundResult(); _moduleService.EnableFeatures(new [] {id}); - Services.Notifier.Information(T("{0} was enabled", id)); return RedirectToAction("Features"); } @@ -73,7 +72,6 @@ namespace Orchard.Modules.Controllers { return new NotFoundResult(); _moduleService.DisableFeatures(new[] { id }); - //Services.Notifier.Information(T("{0} was disabled", featureName)); return RedirectToAction("Features"); } diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs b/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs index 67307b434..cfd21bee2 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,11 +16,16 @@ 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(); @@ -60,9 +67,32 @@ namespace Orchard.Modules.Services { public void EnableFeatures(IEnumerable featureNames) { var shellDescriptor = _shellDescriptorManager.GetShellDescriptor(); + var enabledFeatures = shellDescriptor.EnabledFeatures.ToList(); + var features = GetAvailableFeatures().ToList(); - var enabledFeatures = shellDescriptor.EnabledFeatures - .Union(featureNames.Select(s => new ShellFeature {Name = s})); + foreach (var name in featureNames) { + var featureName = name; + var feature = features.Single(f => f.Descriptor.Name == featureName); + var sleepingDependencies = + feature.Descriptor.Dependencies.Where(s => enabledFeatures.FirstOrDefault(sf => sf.Name == s) == null); + + if (sleepingDependencies.Count() != 0) { + Services.Notifier.Warning(T( + "If you want to enable {0}, then you'll also need {1} (and I won't let you flip everything on in one go yet).", + featureName, + sleepingDependencies.Count() > 1 + ? string.Join("", + sleepingDependencies.Select( + (s, i) => + i == sleepingDependencies.Count() - 2 + ? T("{0} and ", s).ToString() + : T("{0}, ", s).ToString()).ToArray()) + : sleepingDependencies.First())); + } else if (enabledFeatures.FirstOrDefault(f => f.Name == featureName) == null) { + enabledFeatures.Add(new ShellFeature {Name = featureName}); + Services.Notifier.Information(T("{0} was enabled", featureName)); + } + } _shellDescriptorManager.UpdateShellDescriptor(shellDescriptor.SerialNumber, enabledFeatures, shellDescriptor.Parameters); } @@ -72,15 +102,26 @@ namespace Orchard.Modules.Services { 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)); + foreach (var name in featureNames) { + var featureName = name; + var dependants = features.Where(f => f.IsEnabled && f.Descriptor.Dependencies != null && f.Descriptor.Dependencies.Contains(featureName)); - if (dependants.Count() == 0) { - enabledFeatures.RemoveAll(f => f.Name == feature); + if (dependants.Count() != 0) { + Services.Notifier.Warning(T( + "If you want to disable {0}, then you'll also lose {1} (and I won't let you do that yet).", + featureName, + dependants.Count() > 0 + ? string.Join("", + dependants.Select( + (f, i) => + i == dependants.Count() - 2 + ? T("{0} and ", f.Descriptor.Name).ToString() + : T("{0}, ", f.Descriptor.Name).ToString()).ToArray()) + : dependants.First().Descriptor.Name)); } else { - // list what else will be disabled with ok/cancel + enabledFeatures.RemoveAll(f => f.Name == featureName); + Services.Notifier.Information(T("{0} was disabled", featureName)); } } 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..0aa3f2a9d 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx +++ b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx @@ -45,12 +45,12 @@
<% 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 = "" })%> <% } } 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 = "" })%> <% } diff --git a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css index af33ef011..7cdee089c 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:#D1F2A5; /* green*/ + border:1px solid #BCD994; color:#062232; } .debug.message { From ba5fd588d15a3d709db1a00b6868510361fd3cad Mon Sep 17 00:00:00 2001 From: Suha Can Date: Tue, 18 May 2010 13:25:53 -0700 Subject: [PATCH 03/17] - PERF: Fix the role based auth service to not recalculate permission checks again and again. - Adding some comments to the authorization event handler interface. --HG-- branch : dev --- .../Orchard.Roles/Services/RolesBasedAuthorizationService.cs | 2 ++ src/Orchard/Security/IAuthorizationServiceEventHandler.cs | 5 +++++ 2 files changed, 7 insertions(+) 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/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; } } } From ee48ab7aee8ad6e9e0da2f181fb61b6740459ebe Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Tue, 18 May 2010 14:05:11 -0700 Subject: [PATCH 04/17] Adjust config files for deployment debug=false, log errors only, Azure and on premise versions --HG-- branch : dev --- AzurePackage.proj | 17 +++++++++++++++++ Orchard.proj | 14 ++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/AzurePackage.proj b/AzurePackage.proj index ad02d137d..0dade831c 100644 --- a/AzurePackage.proj +++ b/AzurePackage.proj @@ -109,6 +109,23 @@ + + + + + + + + + + + + + + + + + + From 803d0407323d64dcbdb35756b5e2176e906c7c63 Mon Sep 17 00:00:00 2001 From: Renaud Paquay Date: Tue, 18 May 2010 14:32:05 -0700 Subject: [PATCH 05/17] Fix unit test --HG-- branch : dev --- .../Extensions/ExtensionFoldersTests.cs | 21 ++++++++------- .../Extensions/FoldersData/Sample3/Module.txt | 2 +- .../Orchard.Framework.Tests.csproj | 2 ++ src/Orchard.Tests/Stubs/StubCacheManager.cs | 15 +++++++++++ src/Orchard.Tests/Stubs/StubClock.cs | 1 - src/Orchard.Tests/Stubs/StubWebSiteFolder.cs | 27 +++++++++++++++++++ .../Extensions/Folders/ExtensionFolders.cs | 12 ++++----- 7 files changed, 62 insertions(+), 18 deletions(-) create mode 100644 src/Orchard.Tests/Stubs/StubCacheManager.cs create mode 100644 src/Orchard.Tests/Stubs/StubWebSiteFolder.cs diff --git a/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs b/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs index 1ea84731c..929538161 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 { @@ -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")); + var 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/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/Orchard.Framework.Tests.csproj b/src/Orchard.Tests/Orchard.Framework.Tests.csproj index f36cac6bf..8d74a9917 100644 --- a/src/Orchard.Tests/Orchard.Framework.Tests.csproj +++ b/src/Orchard.Tests/Orchard.Framework.Tests.csproj @@ -179,6 +179,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/Environment/Extensions/Folders/ExtensionFolders.cs b/src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs index cac09fef5..3f2203a19 100644 --- a/src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs +++ b/src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs @@ -88,14 +88,14 @@ namespace Orchard.Environment.Extensions.Folders { } } - public ParseResult ParseManifest(string name) { + public 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() }; } @@ -125,14 +125,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(); From c97244c62498c47e437c7244bca08e3c75640b54 Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Wed, 19 May 2010 00:00:56 -0700 Subject: [PATCH 06/17] More work around the feature management UI and hooked a little force enable/disable --HG-- branch : dev --- .../Controllers/AdminController.cs | 32 +-- .../Orchard.Modules/Services/ModuleService.cs | 191 ++++++++++++------ .../Orchard.Modules/Views/Admin/Features.ascx | 16 ++ .../Modules/Orchard.Modules/styles/admin.css | 26 ++- .../Themes/TheAdmin/Styles/site.css | 4 +- src/Orchard/Modules/IModuleService.cs | 4 +- 6 files changed, 177 insertions(+), 96 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs index 84060a88f..490bb121f 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 { @@ -37,9 +34,7 @@ namespace Orchard.Modules.Controllers { if (module == null) return new NotFoundResult(); - return View(new ModuleEditViewModel { - Name = module.DisplayName - }); + return View(new ModuleEditViewModel {Name = module.DisplayName}); } public ActionResult Features() { @@ -50,43 +45,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}); + _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 }); + _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/Services/ModuleService.cs b/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs index cfd21bee2..917d318ae 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Services/ModuleService.cs @@ -16,7 +16,8 @@ namespace Orchard.Modules.Services { private readonly IExtensionManager _extensionManager; private readonly IShellDescriptorManager _shellDescriptorManager; - public ModuleService(IOrchardServices orchardServices,IExtensionManager extensionManager, IShellDescriptorManager shellDescriptorManager) { + public ModuleService(IOrchardServices orchardServices, IExtensionManager extensionManager, + IShellDescriptorManager shellDescriptorManager) { Services = orchardServices; _extensionManager = extensionManager; _shellDescriptorManager = shellDescriptorManager; @@ -27,15 +28,20 @@ namespace Orchard.Modules.Services { 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) { @@ -46,86 +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 features = GetAvailableFeatures().ToList(); - foreach (var name in featureNames) { - var featureName = name; - var feature = features.Single(f => f.Descriptor.Name == featureName); - var sleepingDependencies = - feature.Descriptor.Dependencies.Where(s => enabledFeatures.FirstOrDefault(sf => sf.Name == s) == null); + var featuresToEnable = + features.Select(s => EnableFeature(s, GetAvailableFeatures(), force)). + SelectMany(ies => ies.Select(s => s)); - if (sleepingDependencies.Count() != 0) { - Services.Notifier.Warning(T( - "If you want to enable {0}, then you'll also need {1} (and I won't let you flip everything on in one go yet).", - featureName, - sleepingDependencies.Count() > 1 - ? string.Join("", - sleepingDependencies.Select( - (s, i) => - i == sleepingDependencies.Count() - 2 - ? T("{0} and ", s).ToString() - : T("{0}, ", s).ToString()).ToArray()) - : sleepingDependencies.First())); - } else if (enabledFeatures.FirstOrDefault(f => f.Name == featureName) == null) { - enabledFeatures.Add(new ShellFeature {Name = featureName}); - Services.Notifier.Information(T("{0} was enabled", featureName)); - } + 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); + _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 name in featureNames) { - var featureName = name; - var dependants = features.Where(f => f.IsEnabled && f.Descriptor.Dependencies != null && f.Descriptor.Dependencies.Contains(featureName)); + var featuresToDisable = + features.Select(s => DisableFeature(s, GetAvailableFeatures(), force)).SelectMany( + ies => ies.Select(s => s)); - if (dependants.Count() != 0) { - Services.Notifier.Warning(T( - "If you want to disable {0}, then you'll also lose {1} (and I won't let you do that yet).", - featureName, - dependants.Count() > 0 - ? string.Join("", - dependants.Select( - (f, i) => - i == dependants.Count() - 2 - ? T("{0} and ", f.Descriptor.Name).ToString() - : T("{0}, ", f.Descriptor.Name).ToString()).ToArray()) - : dependants.First().Descriptor.Name)); - } - else { - enabledFeatures.RemoveAll(f => f.Name == featureName); - Services.Notifier.Information(T("{0} was disabled", featureName)); - } + 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/Features.ascx b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx index 0aa3f2a9d..c8e348d1b 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx +++ b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx @@ -56,6 +56,22 @@ } } %>
+
<% + //temporary forceful feature actions + if (feature.IsEnabled) { + 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}", 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/styles/admin.css b/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css index bed7b7169..f6afd126a 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css +++ b/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css @@ -1,4 +1,9 @@ -.features .category { +.orchard-modules #main h2 { + border:0; + margin-bottom:.2em; +} + +.features .category { overflow:hidden; } .features .feature { @@ -28,8 +33,8 @@ } .features .enabled.feature { - background:#D1F2A5; - border-color:#BCD994; + background:#FFF; + border-color:#CFE493;cfe493 } .features .disabled.feature { background:#EAEAEA; @@ -40,7 +45,7 @@ padding:.4em .5em; } .features .dependencies li, -.features .actions a { +.features .actions { font-size:1.4em; } .features .dependencies { @@ -65,3 +70,16 @@ right:.8em; 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/Themes/TheAdmin/Styles/site.css b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css index 7cdee089c..96a7c5011 100644 --- a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css +++ b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css @@ -337,8 +337,8 @@ span.message { color:#fff; } .info.message { - background:#D1F2A5; /* green*/ - border:1px solid #BCD994; + background:#e6f1c9; /* green */ + border:1px solid #cfe493; color:#062232; } .debug.message { 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 From 2727dab5baaa441663cf0ddbff57428b4fd07f24 Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Wed, 19 May 2010 10:02:47 -0700 Subject: [PATCH 07/17] Dropping the Common features dependency and messing with the UI a bit more --HG-- branch : dev --- src/Orchard.Web/Core/Dashboard/Module.txt | 1 - src/Orchard.Web/Core/Feeds/Module.txt | 1 - src/Orchard.Web/Core/HomePage/Module.txt | 1 - src/Orchard.Web/Core/Navigation/Module.txt | 1 - src/Orchard.Web/Core/Scheduling/Module.txt | 1 - src/Orchard.Web/Core/Settings/Module.txt | 1 - src/Orchard.Web/Core/XmlRpc/Module.txt | 3 +-- src/Orchard.Web/Modules/Futures.Widgets/Module.txt | 1 - src/Orchard.Web/Modules/Orchard.Blogs/Module.txt | 2 +- src/Orchard.Web/Modules/Orchard.Comments/Module.txt | 1 - src/Orchard.Web/Modules/Orchard.DevTools/Module.txt | 1 - src/Orchard.Web/Modules/Orchard.Media/Module.txt | 1 - src/Orchard.Web/Modules/Orchard.Modules/Module.txt | 1 - .../Modules/Orchard.Modules/Views/Admin/Features.ascx | 11 ++++++++--- .../Modules/Orchard.Modules/styles/admin.css | 6 +++--- .../Modules/Orchard.MultiTenancy/Module.txt | 3 +-- src/Orchard.Web/Modules/Orchard.Pages/Module.txt | 1 - src/Orchard.Web/Modules/Orchard.Roles/Module.txt | 1 - src/Orchard.Web/Modules/Orchard.Sandbox/Module.txt | 1 - src/Orchard.Web/Modules/Orchard.Setup/Module.txt | 1 - src/Orchard.Web/Modules/Orchard.Tags/Module.txt | 1 - src/Orchard.Web/Modules/Orchard.Themes/Module.txt | 1 - src/Orchard.Web/Modules/Orchard.Users/Module.txt | 1 - 23 files changed, 14 insertions(+), 29 deletions(-) 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..ef43ff281 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 Management \ 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..5ba70c807 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Module.txt @@ -7,5 +7,5 @@ orchardversion: 0.1.2010.0312 features: Orchard.Blogs: Description: A simple web log. - Dependencies: Common, XmlRpc + Dependencies: XmlRpc Category: Content \ No newline at end of file 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/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/Views/Admin/Features.ascx b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx index c8e348d1b..2c9065d21 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx +++ b/src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Features.ascx @@ -13,7 +13,10 @@ 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) %>

      <% @@ -42,7 +45,8 @@ "") %> <% } %> - + <% + if (showActions) { %>
      <% if (feature.IsEnabled) { using (Html.BeginFormAntiForgeryPost(string.Format("{0}", Url.Action("Disable", new { area = "Orchard.Modules" })), FormMethod.Post, new {@class = "inline link"})) { %> @@ -71,7 +75,8 @@ <% } } %> -
      + <% + } %> <% } %> diff --git a/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css b/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css index f6afd126a..3041b4688 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css +++ b/src/Orchard.Web/Modules/Orchard.Modules/styles/admin.css @@ -10,7 +10,7 @@ border:1px solid #EAEAEA; display:block; float:left; - height:6.8em; + height:5em; margin:0 .5% 1% .5%; position:relative; width:32.1%; @@ -57,7 +57,7 @@ } .features .dependencies li { display:inline; - margin-left:.5ex; + margin-left:.5em; } .features .dependencies li::after { content:", "; @@ -67,7 +67,7 @@ } .features .feature .actions { position:absolute; - right:.8em; + right:.4em; top:.6em; } 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.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 From d6e1440d9b7bff0a528fc473ef826ce1b30afc44 Mon Sep 17 00:00:00 2001 From: Renaud Paquay Date: Wed, 19 May 2010 10:05:01 -0700 Subject: [PATCH 08/17] Fix unit test Change app config to rebind mvc 1.0 to mvc 2.0 assembly, the same way we do in web.config. --HG-- branch : dev --- src/Orchard.Tests/App.config | 8 ++++++++ .../ShellBuilders/DefaultShellContainerFactoryTests.cs | 1 + 2 files changed, 9 insertions(+) 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/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(); } From 559a94af73843c421312975af818fbe77453bf6c Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 19 May 2010 10:29:55 -0700 Subject: [PATCH 09/17] Corrected internal exception when a Page content is empty --HG-- branch : dev --- src/Orchard.Web/Core/Common/Drivers/BodyDriver.cs | 4 ++++ 1 file changed, 4 insertions(+) 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\]"); From 19396e4f0c2bbe8fe4e9eb0dff15cbe2c7f9fc36 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 19 May 2010 11:33:43 -0700 Subject: [PATCH 10/17] New view engines cache implementation for tenant compatibility with themes --HG-- branch : dev --- .../Mvc/ViewEngines/ThemeViewLocationCache.cs | 38 +++++++++++++++++++ .../ViewEngines/WebFormsViewEngineProvider.cs | 2 + src/Orchard/Orchard.Framework.csproj | 1 + 3 files changed, 41 insertions(+) create mode 100644 src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs diff --git a/src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs b/src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs new file mode 100644 index 000000000..356ebc78d --- /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")), Cache.NoAbsoluteExpiration, TimeSpan); + } + } +} 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 62227f8d3..fdd5a5a5e 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -235,6 +235,7 @@ + ASPXCodeBehind From c4a4d183030cf96210abf377e08fa9d4a2afa751 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Wed, 19 May 2010 12:11:09 -0700 Subject: [PATCH 11/17] Corrected compilation error --HG-- branch : dev --- src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs b/src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs index 356ebc78d..a5a39f1eb 100644 --- a/src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs +++ b/src/Orchard/Mvc/ViewEngines/ThemeViewLocationCache.cs @@ -32,7 +32,7 @@ namespace Orchard.Mvc.ViewEngines { throw new ArgumentNullException("httpContext"); } - httpContext.Cache.Insert(AlterKey(key), virtualPath, new CacheDependency(HostingEnvironment.MapPath("~/Themes")), Cache.NoAbsoluteExpiration, TimeSpan); + httpContext.Cache.Insert(AlterKey(key), virtualPath, new CacheDependency(HostingEnvironment.MapPath("~/Themes"))); } } } From 98e6ae9c76a790049972f6f6023ad95e04b438b2 Mon Sep 17 00:00:00 2001 From: Renaud Paquay Date: Wed, 19 May 2010 13:42:01 -0700 Subject: [PATCH 12/17] Fix unit tests --HG-- branch : dev --- .../Extensions/ExtensionFoldersTests.cs | 6 ++-- .../Extensions/ExtensionManagerTests.cs | 34 ++++++------------ .../Extensions/Folders/ExtensionFolders.cs | 36 +++++-------------- .../Extensions/Folders/IExtensionFolders.cs | 2 -- 4 files changed, 22 insertions(+), 56 deletions(-) diff --git a/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs b/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs index 929538161..2983743f5 100644 --- a/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs +++ b/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs @@ -54,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 }, null, null); + 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")); @@ -63,7 +63,7 @@ namespace Orchard.Tests.Environment.Extensions { [Test] public void ModuleTxtShouldBeParsedAndReturnedAsYamlDocument() { - var folders = new ModuleFolders(new[] { _tempFolderName }, new StubCacheManager(), new StubWebSiteFolder()); + 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")); diff --git a/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs b/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs index 5852c1028..2e4601202 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, "InMemory", 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/Environment/Extensions/Folders/ExtensionFolders.cs b/src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs index 3f2203a19..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,20 +73,11 @@ 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 manifestText) { + public static ParseResult ParseManifest(string manifestText) { bool success; var yamlStream = new YamlParser().ParseYamlStream(new TextInput(manifestText), out success); if (yamlStream == null || !success) { @@ -100,8 +89,7 @@ namespace Orchard.Environment.Extensions.Folders { }; } - - 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"), @@ -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 From bbb3363519ce7437f301454df9f2167b901e30d1 Mon Sep 17 00:00:00 2001 From: Renaud Paquay Date: Wed, 19 May 2010 13:44:53 -0700 Subject: [PATCH 13/17] Fix unit tests --HG-- branch : dev --- .../Environment/Extensions/ExtensionManagerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs b/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs index 2e4601202..8e1b0aa1a 100644 --- a/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs +++ b/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs @@ -38,7 +38,7 @@ namespace Orchard.Tests.Environment.Extensions { foreach(var e in Manifests) { string name = e.Key; var parseResult = ExtensionFolders.ParseManifest(Manifests[name]); - yield return ExtensionFolders.GetDescriptorForExtension("~/", name, "InMemory", parseResult); + yield return ExtensionFolders.GetDescriptorForExtension("~/", name, "Module", parseResult); } } } From 445f164b86af8ed608182f1db514b5621c6da22d Mon Sep 17 00:00:00 2001 From: Renaud Paquay Date: Wed, 19 May 2010 13:49:53 -0700 Subject: [PATCH 14/17] Fix unit tests --HG-- branch : dev --- .../Users/Controllers/AdminControllerTests.cs | 1 + .../Users/Services/MembershipServiceTests.cs | 1 + 2 files changed, 2 insertions(+) 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(); From 98e676800d6ff3f163af33fc8f79b8aaef1e77ab Mon Sep 17 00:00:00 2001 From: Renaud Paquay Date: Wed, 19 May 2010 13:56:00 -0700 Subject: [PATCH 15/17] Fix unit test --HG-- branch : dev --- .../Environment/Extensions/ExtensionFoldersTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs b/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs index 2983743f5..c80d090f6 100644 --- a/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs +++ b/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs @@ -54,7 +54,7 @@ namespace Orchard.Tests.Environment.Extensions { [Test] public void NamesFromFoldersWithModuleTxtShouldBeListed() { - IExtensionFolders folders = new ModuleFolders(new[] { _tempFolderName }, null, null); + 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")); From 871ace9d3376fcb02f04e7273659d7c841283d8e Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Wed, 19 May 2010 14:09:13 -0700 Subject: [PATCH 16/17] More feature/module management UI updates and some cleanup - removed unused edit page & action - remvoed super sekret force actions on functions and defaulting enable/disable to force for now (until a dialog solution is in place) - standarized on a feature ID format and threw in a string extension to gen it for good measure --HG-- branch : dev --- .../Controllers/AdminController.cs | 12 ---------- .../Extensions/StringExtensions.cs | 13 +++++++++++ .../Orchard.Modules/Orchard.Modules.csproj | 2 +- .../Orchard.Modules/Views/Admin/Edit.ascx | 5 ---- .../Orchard.Modules/Views/Admin/Features.ascx | 23 ++++--------------- .../Orchard.Modules/Views/Admin/Index.ascx | 7 ++---- 6 files changed, 21 insertions(+), 41 deletions(-) create mode 100644 src/Orchard.Web/Modules/Orchard.Modules/Extensions/StringExtensions.cs delete mode 100644 src/Orchard.Web/Modules/Orchard.Modules/Views/Admin/Edit.ascx diff --git a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs index 490bb121f..a45979b33 100644 --- a/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Modules/Controllers/AdminController.cs @@ -25,18 +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(); 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/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/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 2c9065d21..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" %><% @@ -23,7 +24,7 @@ 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()) @@ -39,7 +40,7 @@

      <%=_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", "") %> @@ -51,30 +52,16 @@ if (feature.IsEnabled) { 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}", 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)%> <% } } %> - -
      <% - //temporary forceful feature actions - if (feature.IsEnabled) { - 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}", 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) %>

      <% From d0851610544f9d68e8dea31326acc1789f633ca2 Mon Sep 17 00:00:00 2001 From: Nathan Heskew Date: Wed, 19 May 2010 14:33:51 -0700 Subject: [PATCH 17/17] Split the xmlrpc functionality of the blog out into its own feature, dependant on the xmlrpc feature --HG-- branch : dev --- src/Orchard.Web/Core/XmlRpc/Module.txt | 2 +- src/Orchard.Web/Modules/Orchard.Blogs/Module.txt | 5 ++++- .../Modules/Orchard.Blogs/Services/XmlRpcHandler.cs | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Orchard.Web/Core/XmlRpc/Module.txt b/src/Orchard.Web/Core/XmlRpc/Module.txt index ef43ff281..6ab5a799d 100644 --- a/src/Orchard.Web/Core/XmlRpc/Module.txt +++ b/src/Orchard.Web/Core/XmlRpc/Module.txt @@ -7,4 +7,4 @@ orchardversion: 0.1.2010.0312 features: XmlRpc: Description: XML-RPC opt-in implementation. - Category: Content Management \ No newline at end of file + Category: Content Publishing \ 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 5ba70c807..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. + Category: Content + Remote Blog Publishing: + Description: Blog easier using a dedicated MetaWeblogAPI-compatible publishing tool. Dependencies: XmlRpc - Category: Content \ No newline at end of file + 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;