--HG--
branch : dev
This commit is contained in:
khavas
2010-05-19 15:45:57 -07:00
53 changed files with 419 additions and 196 deletions

View File

@@ -109,6 +109,23 @@
<Copy SourceFiles="@(Stage-Modules)" DestinationFolder="$(CloudRootFolder)\Modules\%(RecursiveDir)" />
<Copy SourceFiles="@(Stage-Modules-Bin)" DestinationFolder="$(CloudRootFolder)\bin\" />
<!-- extra processing of the staged config files -->
<XmlUpdate XmlFileName="$(CloudRootFolder)\web.config"
XPath="/configuration/system.web/compilation/@debug"
Value="false" />
<XmlUpdate XmlFileName="$(CloudRootFolder)\Config\Diagnostics.config"
XPath="/system.diagnostics/trace/@autoflush"
Value="false" />
<XmlUpdate XmlFileName="$(CloudRootFolder)\Config\Diagnostics.config"
XPath="/system.diagnostics/sources/source/@switchValue"
Value="Error" />
<!-- move over extra non-content files the csproj referenced -->
<Copy SourceFiles="@(StageProjectAlteration-ExtraFiles->'$(SrcFolder)\Orchard.Web\%(Identity)')"
DestinationFolder="$(StageFolder)\%(RecursiveDir)"/>
<!-- use x64 sqlite for tests depending on build platform -->
<Copy
SourceFiles="$(LibFolder)\sqlite\x64\System.Data.SQLite.dll"

View File

@@ -118,6 +118,20 @@
<Output TaskParameter="ExtraFiles" ItemName="StageProjectAlteration-ExtraFiles"/>
</StageProjectAlteration>
<!-- extra processing of the staged config files -->
<XmlUpdate XmlFileName="$(StageFolder)\web.config"
XPath="/configuration/system.web/compilation/@debug"
Value="false" />
<XmlUpdate XmlFileName="$(StageFolder)\Config\Diagnostics.config"
XPath="/system.diagnostics/trace/@autoflush"
Value="false" />
<XmlUpdate XmlFileName="$(StageFolder)\Config\Diagnostics.config"
XPath="/system.diagnostics/sources/source/@switchValue"
Value="Error" />
<!-- move over extra non-content files the csproj referenced -->
<Copy SourceFiles="@(StageProjectAlteration-ExtraFiles->'$(SrcFolder)\Orchard.Web\%(Identity)')"
DestinationFolder="$(StageFolder)\%(RecursiveDir)"/>

View File

@@ -30,6 +30,7 @@ namespace Orchard.Tests.Modules.Users.Controllers {
public override void Register(ContainerBuilder builder) {
builder.RegisterType<AdminController>().SingleInstance();
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterType<DefaultContentQuery>().As<IContentQuery>().InstancePerDependency();
builder.RegisterType<MembershipService>().As<IMembershipService>();
builder.RegisterType<UserService>().As<IUserService>();

View File

@@ -55,6 +55,7 @@ namespace Orchard.Tests.Modules.Users.Services {
//builder.RegisterModule(new ImplicitCollectionSupportModule());
builder.RegisterType<MembershipService>().As<IMembershipService>();
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterType<UserHandler>().As<IContentHandler>();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
_session = _sessionFactory.OpenSession();

View File

@@ -9,4 +9,12 @@
</source>
</sources>
</system.diagnostics>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -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"));
}
}
}

View File

@@ -34,26 +34,12 @@ namespace Orchard.Tests.Environment.Extensions {
public IDictionary<string, string> Manifests { get; set; }
public IEnumerable<string> 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<ExtensionDescriptor> 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));

View File

@@ -1 +1 @@
This is another test.txt
name: This is another test.txt

View File

@@ -26,6 +26,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
var builder = new ContainerBuilder();
builder.RegisterType<ShellContainerFactory>().As<IShellContainerFactory>();
builder.RegisterType<ComponentForHostContainer>();
builder.RegisterType<ControllerActionInvoker>().As<IActionInvoker>();
_container = builder.Build();
}

View File

@@ -180,6 +180,8 @@
<Compile Include="Environment\ShellBuilders\DefaultShellContextFactoryTests.cs" />
<Compile Include="Mvc\Routes\ShellRouteTests.cs" />
<Compile Include="Mvc\Routes\UrlPrefixTests.cs" />
<Compile Include="Stubs\StubCacheManager.cs" />
<Compile Include="Stubs\StubWebSiteFolder.cs" />
<Compile Include="Utility\ContainerExtensions.cs" />
<Compile Include="Environment\TestDependencies\TestDependency.cs" />
<Compile Include="Environment\Topology\DefaultShellDescriptorCacheTests.cs" />

View File

@@ -0,0 +1,15 @@
using System;
using Orchard.Caching;
namespace Orchard.Tests.Stubs {
public class StubCacheManager : ICacheManager {
public TResult Get<TKey, TResult>(TKey key, Func<AcquireContext<TKey>, TResult> acquire) {
var cache = new Cache<TKey, TResult>();
return cache.Get(key, acquire);
}
public ICache<TKey, TResult> GetCache<TKey, TResult>() {
throw new NotImplementedException();
}
}
}

View File

@@ -16,6 +16,5 @@ namespace Orchard.Tests.Stubs {
public DateTime FutureMoment(TimeSpan span) {
return UtcNow.Add(span);
}
}
}

View File

@@ -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<string> ListDirectories(string path) {
if (!Directory.Exists(path))
return Enumerable.Empty<string>();
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);
}
}
}

View File

@@ -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\]");

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Dashboard:
Description: Standard admin dashboard.
Dependencies: Common
Category: Core

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Feeds:
Description: RSS feeds for content items.
Dependencies: Common
Category: Syndication

View File

@@ -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

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Navigation:
Description: Menu management.
Dependencies: Common
Category: Core

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Scheduling:
Description: Scheduled background tasks.
Dependencies: Common
Category: Core

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Settings:
Description: Site settings.
Dependencies: Common
Category: Core

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
XmlRpc:
Description: XML-RPC opt-in implementation.
Dependencies: Common
Category: Core
Category: Content Publishing

View File

@@ -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

View File

@@ -7,5 +7,8 @@ orchardversion: 0.1.2010.0312
features:
Orchard.Blogs:
Description: A simple web log.
Dependencies: Common, XmlRpc
Category: Content
Remote Blog Publishing:
Description: Blog easier using a dedicated MetaWeblogAPI-compatible publishing tool.
Dependencies: XmlRpc
Category: Content Publishing

View File

@@ -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;

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Orchard.Comments:
Description: Standard content item comments.
Dependencies: Common
Category: Social

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Orchard.DevTools:
Description: An assortment of debuging tools.
Dependencies: Common
Category: Developer

View File

@@ -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

View File

@@ -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);
}
}
}
}

View File

@@ -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<string, LocalizedString> localize) {
return string.IsNullOrEmpty(text)
? ""
: string.Format(localize("{0} feature").ToString(), text).HtmlClassify();
}
}
}

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Orchard.Modules:
Description: Standard module and feature management.
Dependencies: Common
Category: Core

View File

@@ -64,6 +64,7 @@
<Compile Include="AdminMenu.cs" />
<Compile Include="Commands\FeatureCommand.cs" />
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Models\ModuleFeature.cs" />
<Compile Include="ViewModels\FeaturesViewModel.cs" />
<Compile Include="Models\Module.cs" />
@@ -89,7 +90,6 @@
<Content Include="Content\Admin\images\enabled.gif" />
<Content Include="styles\admin.css" />
<Content Include="Views\Admin\Features.ascx" />
<Content Include="Views\Admin\Edit.ascx" />
<Content Include="Views\Web.config" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

View File

@@ -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,20 +16,31 @@ 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(
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<IModule> GetInstalledModules() {
return
_extensionManager.AvailableExtensions().Where(
e => String.Equals(e.ExtensionType, ModuleExtensionType, StringComparison.OrdinalIgnoreCase)).Select(
e => String.Equals(e.ExtensionType, ModuleExtensionType, StringComparison.OrdinalIgnoreCase)).Select
(
descriptor => AssembleModuleFromDescriptor(descriptor));
}
@@ -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<IModuleFeature> 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<Feature> 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<string> featureNames) {
EnableFeatures(featureNames, false);
}
public void EnableFeatures(IEnumerable<string> 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<string> featureNames) {
DisableFeatures(featureNames, false);
}
public void DisableFeatures(IEnumerable<string> 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) {
if (featuresToDisable.Count() == 0)
return;
foreach (var featureToDisable in featuresToDisable) {
var feature = featureToDisable;
enabledFeatures.RemoveAll(f => f.Name == feature);
}
else {
// list what else will be disabled with ok/cancel
}
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<string> EnableFeature(string featureName, IEnumerable<IModuleFeature> features, bool force) {
var featuresList = features.ToList();
var getDisabledDependencies =
new Func<string, IEnumerable<IModuleFeature>, IEnumerable<IModuleFeature>>(
(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<IModuleFeature>();
});
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<string>();
}
return featuresToEnable;
}
private IEnumerable<string> DisableFeature(string featureName, IEnumerable<IModuleFeature> features, bool force) {
var featuresList = features.ToList();
var getEnabledDependants =
new Func<string, IEnumerable<IModuleFeature>, IEnumerable<IModuleFeature>>(
(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<string>();
}
return featuresToDisable;
}
private static IEnumerable<string> GetAffectedFeatures(string featureName, IEnumerable<IModuleFeature> features, Func<string, IEnumerable<IModuleFeature>, IEnumerable<IModuleFeature>> getAffectedDependencies) {
var dependencies = new List<string> {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<string> 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) {

View File

@@ -1,5 +0,0 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<ModuleEditViewModel>" %>
<%@ Import Namespace="Orchard.Mvc.Html"%>
<%@ Import Namespace="Orchard.Modules.ViewModels"%>
<h1><%=Html.TitleForPage(T("Edit Module: {0}", Model.Name).ToString()) %></h1>
<p><%=_Encoded("Edit the module. Maybe show module's features.") %></p>

View File

@@ -1,4 +1,5 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<FeaturesViewModel>" %>
<%@ 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"; %>
<li class="<%=categoryClassName %>">
<h2><%=Html.Encode(categoryName) %></h2>
<ul><%
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 @@
<h4><%=_Encoded("Depends on:")%></h4>
<%=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",
"") %>
</div><%
} %>
</div>
</div><%
if (showActions) { %>
<div class="actions"><%
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)%>
<button type="submit"><%=_Encoded("Disable") %></button><%
}
} 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)%>
<button type="submit"><%=_Encoded("Enable") %></button><%
}
} %>
</div>
</div><%
} %>
</div>
</li><%
} %>

View File

@@ -1,4 +1,5 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<ModulesIndexViewModel>" %>
<%@ Import Namespace="Orchard.Modules.Extensions" %>
<%@ Import Namespace="Orchard.Mvc.Html"%>
<%@ Import Namespace="Orchard.Modules.ViewModels"%>
<h1><%=Html.TitleForPage(T("Installed Modules").ToString()) %></h1>
@@ -14,15 +15,11 @@
<h3><%=Html.Encode(module.DisplayName) %></h3>
<ul class="pageStatus" style="color:#666">
<li><%=T("Version: {0}", !string.IsNullOrEmpty(module.Version) ? Html.Encode(module.Version) : T("1.0")) %></li>
<li>&nbsp;&#124;&nbsp;<%=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())) %></li>
<li>&nbsp;&#124;&nbsp;<%=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())) %></li>
<li>&nbsp;&#124;&nbsp;<%=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]) %></li><%-- very efficient, I know --%>
<li>&nbsp;&#124;&nbsp;<%=T("Website: {0}", !string.IsNullOrEmpty(module.HomePage) ? Html.Encode(module.HomePage) : T("<a href=\"http://orchardproject.net\">http://orchardproject.net</a>"))%></li>
</ul>
</div>
<%--<div class="related">
<%=Html.ActionLink(T("Edit").ToString(), "edit", new {moduleName = module.ModuleName, area = "Orchard.Modules"}) %><%=_Encoded(" | ")%>
<a href="#">Delete</a>
</div>--%>
</div><%
if (!string.IsNullOrEmpty(module.Description)) { %>
<p><%=Html.Encode(module.Description) %></p><%

View File

@@ -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;
}

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Orchard.MultiTenancy:
Description: Configure multiple site tenants.
Dependencies: Common
Category: Core
Category: Hosting

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Orchard.Pages:
Description: Simple pages.
Dependencies: Common
Category: Content

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Orchard.Roles:
Description: Standard user roles.
Dependencies: Common
Category: Core

View File

@@ -84,6 +84,8 @@ namespace Orchard.Roles.Services {
context.Adjusted = false;
_authorizationServiceEventHandler.Adjust(context);
if (!context.Adjusted)
break;
}
_authorizationServiceEventHandler.Complete(context);

View File

@@ -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

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Orchard.Setup:
Description: Standard site setup.
Dependencies: Common
Category: Core

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Orchard.Tags:
Description: Tag a content item.
Dependencies: Common
Category: Navigation

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Orchard.Themes:
Description: Basic theming capability.
Dependencies: Common
Category: Display

View File

@@ -7,5 +7,4 @@ orchardversion: 0.1.2010.0312
features:
Orchard.Users:
Description: Standard users.
Dependencies: Common
Category: Core

View File

@@ -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 {

View File

@@ -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<string> 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<FeatureDescriptor> GetFeaturesForExtension(Mapping features, ExtensionDescriptor extensionDescriptor) {
List<FeatureDescriptor> featureDescriptors = new List<FeatureDescriptor>();
var featureDescriptors = new List<FeatureDescriptor>();
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<string> dependencies = new List<string>();
var dependencies = new List<string>();
foreach (var s in dependenciesEntry.Split(',')) {
dependencies.Add(s.Trim());
}
return dependencies.ToArray();
}
private static Mapping GetMapping(
IDictionary<string, DataItem> fields,
string key) {
private static Mapping GetMapping(IDictionary<string, DataItem> fields, string key) {
DataItem value;
return fields.TryGetValue(key, out value) ? (Mapping)value : null;
}
private static string GetValue(
IDictionary<string, DataItem> fields,
string key) {
private static string GetValue(IDictionary<string, DataItem> fields, string key) {
DataItem value;
return fields.TryGetValue(key, out value) ? value.ToString() : null;
}

View File

@@ -6,6 +6,4 @@ namespace Orchard.Environment.Extensions.Folders {
public interface IExtensionFolders {
IEnumerable<ExtensionDescriptor> AvailableExtensions();
}
}

View File

@@ -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<IModule> GetInstalledModules();
void InstallModule(HttpPostedFileBase file);
void UninstallModule(string moduleName);
IModule GetModuleByFeatureName(string featureName);
IEnumerable<IModuleFeature> GetAvailableFeatures();
void EnableFeatures(IEnumerable<string> featureNames);
void EnableFeatures(IEnumerable<string> featureNames, bool force);
void DisableFeatures(IEnumerable<string> featureNames);
void DisableFeatures(IEnumerable<string> featureNames, bool force);
}
}

View File

@@ -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")));
}
}
}

View File

@@ -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}

View File

@@ -241,6 +241,7 @@
<Compile Include="Mvc\Routes\UrlPrefix.cs" />
<Compile Include="Mvc\Routes\UrlPrefixAdjustedHttpContext.cs" />
<Compile Include="Mvc\Routes\ShellRoute.cs" />
<Compile Include="Mvc\ViewEngines\ThemeViewLocationCache.cs" />
<Compile Include="Mvc\ViewModels\AdaptedViewModel.cs" />
<Compile Include="Mvc\ViewUserControl.cs">
<SubType>ASPXCodeBehind</SubType>

View File

@@ -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; }
}
}