mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-24 10:11:35 +08:00
Extensions are not enabled any more if they can't actually be loaded, fixes #2437
This commit is contained in:
@@ -194,6 +194,10 @@ Features:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool LoaderIsSuitable(ExtensionDescriptor descriptor) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,10 @@ namespace Orchard.Tests.Environment.Extensions {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool LoaderIsSuitable(ExtensionDescriptor descriptor) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
@@ -119,6 +119,10 @@ namespace Orchard.Tests.Environment.Extensions {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool LoaderIsSuitable(ExtensionDescriptor descriptor) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,7 @@ namespace Orchard.Modules.Controllers {
|
||||
IRecipeManager recipeManager,
|
||||
ShellDescriptor shellDescriptor,
|
||||
ShellSettings shellSettings,
|
||||
IShapeFactory shapeFactory)
|
||||
{
|
||||
IShapeFactory shapeFactory) {
|
||||
Services = services;
|
||||
_extensionDisplayEventHandler = extensionDisplayEventHandlers.FirstOrDefault();
|
||||
_moduleService = moduleService;
|
||||
@@ -158,7 +157,7 @@ namespace Orchard.Modules.Controllers {
|
||||
try {
|
||||
_recipeManager.Execute(recipe);
|
||||
}
|
||||
catch(Exception e) {
|
||||
catch (Exception e) {
|
||||
Logger.Error(e, "Error while executing recipe {0} in {1}", moduleId, name);
|
||||
Services.Notifier.Error(T("Recipes {0} contains unsupported module installation steps.", recipe.Name));
|
||||
}
|
||||
@@ -177,12 +176,12 @@ namespace Orchard.Modules.Controllers {
|
||||
IEnumerable<ModuleFeature> features = _featureManager.GetAvailableFeatures()
|
||||
.Where(f => !DefaultExtensionTypes.IsTheme(f.Extension.ExtensionType))
|
||||
.Select(f => new ModuleFeature {
|
||||
Descriptor = f,
|
||||
IsEnabled = _shellDescriptor.Features.Any(sf => sf.Name == f.Id),
|
||||
IsRecentlyInstalled = _moduleService.IsRecentlyInstalled(f.Extension),
|
||||
NeedsUpdate = featuresThatNeedUpdate.Contains(f.Id),
|
||||
DependentFeatures = _moduleService.GetDependentFeatures(f.Id).Where(x => x.Id != f.Id).ToList()
|
||||
})
|
||||
Descriptor = f,
|
||||
IsEnabled = _shellDescriptor.Features.Any(sf => sf.Name == f.Id),
|
||||
IsRecentlyInstalled = _moduleService.IsRecentlyInstalled(f.Extension),
|
||||
NeedsUpdate = featuresThatNeedUpdate.Contains(f.Id),
|
||||
DependentFeatures = _moduleService.GetDependentFeatures(f.Id).Where(x => x.Id != f.Id).ToList()
|
||||
})
|
||||
.ToList();
|
||||
|
||||
return View(new FeaturesViewModel {
|
||||
@@ -212,13 +211,13 @@ namespace Orchard.Modules.Controllers {
|
||||
case FeaturesBulkAction.None:
|
||||
break;
|
||||
case FeaturesBulkAction.Enable:
|
||||
_moduleService.EnableFeatures(disabledFeatures, force == true);
|
||||
EnableFeatures(disabledFeatures, force == true);
|
||||
break;
|
||||
case FeaturesBulkAction.Disable:
|
||||
_moduleService.DisableFeatures(enabledFeatures, force == true);
|
||||
break;
|
||||
case FeaturesBulkAction.Toggle:
|
||||
_moduleService.EnableFeatures(disabledFeatures, force == true);
|
||||
EnableFeatures(disabledFeatures, force == true);
|
||||
_moduleService.DisableFeatures(enabledFeatures, force == true);
|
||||
break;
|
||||
case FeaturesBulkAction.Update:
|
||||
@@ -250,5 +249,16 @@ namespace Orchard.Modules.Controllers {
|
||||
private bool ExtensionIsAllowed(ExtensionDescriptor extensionDescriptor) {
|
||||
return _shellSettings.Modules.Length == 0 || _shellSettings.Modules.Contains(extensionDescriptor.Id);
|
||||
}
|
||||
|
||||
private void EnableFeatures(List<string> disabledFeatures, bool force) {
|
||||
foreach (var feature in disabledFeatures) {
|
||||
if (_featureManager.HasLoader(feature)) {
|
||||
_moduleService.EnableFeatures(disabledFeatures, force);
|
||||
}
|
||||
else {
|
||||
Services.Notifier.Error(T("No loader found for feature's (\"{0}\") exension!", feature));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,12 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
public class CoreExtensionLoader : ExtensionLoaderBase {
|
||||
private const string CoreAssemblyName = "Orchard.Core";
|
||||
private readonly IAssemblyLoader _assemblyLoader;
|
||||
private readonly IDependenciesFolder _dependenciesFolder;
|
||||
|
||||
public CoreExtensionLoader(IDependenciesFolder dependenciesFolder, IAssemblyLoader assemblyLoader)
|
||||
public CoreExtensionLoader(IAssemblyLoader assemblyLoader, IDependenciesFolder dependenciesFolder)
|
||||
: base(dependenciesFolder) {
|
||||
_assemblyLoader = assemblyLoader;
|
||||
_dependenciesFolder = dependenciesFolder;
|
||||
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
@@ -59,6 +61,15 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
};
|
||||
}
|
||||
|
||||
public override bool LoaderIsSuitable(ExtensionDescriptor descriptor) {
|
||||
var dependency = _dependenciesFolder.GetDescriptor(descriptor.Id);
|
||||
if (dependency != null && dependency.LoaderName == this.Name) {
|
||||
return _assemblyLoader.Load(CoreAssemblyName) != null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsTypeFromModule(Type type, ExtensionDescriptor descriptor) {
|
||||
return (type.Namespace + ".").StartsWith(CoreAssemblyName + "." + descriptor.Id + ".");
|
||||
}
|
||||
|
||||
@@ -212,6 +212,20 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
public override bool LoaderIsSuitable(ExtensionDescriptor descriptor) {
|
||||
var dependency = _dependenciesFolder.GetDescriptor(descriptor.Id);
|
||||
if (dependency != null && dependency.LoaderName == this.Name) {
|
||||
var projectPath = GetProjectPath(descriptor);
|
||||
if (projectPath == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _buildManager.GetCompiledAssembly(projectPath) != null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void AddDependencies(string projectPath, HashSet<string> currentSet) {
|
||||
// Skip files from locations other than "~/Modules" and "~/Themes" etc.
|
||||
if (string.IsNullOrEmpty(PrefixMatch(projectPath, _extensionsVirtualPathPrefixes))) {
|
||||
|
||||
@@ -57,5 +57,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
public virtual IEnumerable<string> GetVirtualPathDependencies(DependencyDescriptor dependency) {
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
||||
public abstract bool LoaderIsSuitable(ExtensionDescriptor descriptor);
|
||||
}
|
||||
}
|
||||
@@ -59,5 +59,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
/// For example, Razor or WebForms views needs to be recompiled when a dependency of a module changes.
|
||||
/// </summary>
|
||||
IEnumerable<string> GetVirtualPathDependencies(DependencyDescriptor dependency);
|
||||
|
||||
bool LoaderIsSuitable(ExtensionDescriptor descriptor);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
private readonly IAssemblyProbingFolder _assemblyProbingFolder;
|
||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||
private readonly IVirtualPathMonitor _virtualPathMonitor;
|
||||
private readonly IDependenciesFolder _dependenciesFolder;
|
||||
|
||||
public PrecompiledExtensionLoader(
|
||||
IHostEnvironment hostEnvironment,
|
||||
@@ -31,6 +32,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
_assemblyProbingFolder = assemblyProbingFolder;
|
||||
_virtualPathProvider = virtualPathProvider;
|
||||
_virtualPathMonitor = virtualPathMonitor;
|
||||
_dependenciesFolder = dependenciesFolder;
|
||||
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
@@ -166,7 +168,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
Loader = this,
|
||||
Name = Path.GetFileNameWithoutExtension(path),
|
||||
VirtualPath = path
|
||||
} )
|
||||
})
|
||||
.ToList();
|
||||
|
||||
Logger.Information("Done probing references for module '{0}'", descriptor.Id);
|
||||
@@ -244,5 +246,14 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
|
||||
return assemblyPath;
|
||||
}
|
||||
|
||||
public override bool LoaderIsSuitable(ExtensionDescriptor descriptor) {
|
||||
var dependency = _dependenciesFolder.GetDescriptor(descriptor.Id);
|
||||
if (dependency != null && dependency.LoaderName == this.Name) {
|
||||
return _assemblyProbingFolder.AssemblyExists(descriptor.Id);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,12 @@ using Orchard.Logging;
|
||||
namespace Orchard.Environment.Extensions.Loaders {
|
||||
public class RawThemeExtensionLoader : ExtensionLoaderBase {
|
||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||
private readonly IDependenciesFolder _dependenciesFolder;
|
||||
|
||||
public RawThemeExtensionLoader(IDependenciesFolder dependenciesFolder, IVirtualPathProvider virtualPathProvider)
|
||||
: base(dependenciesFolder) {
|
||||
_virtualPathProvider = virtualPathProvider;
|
||||
_dependenciesFolder = dependenciesFolder;
|
||||
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
@@ -26,12 +28,12 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
return null;
|
||||
|
||||
// Temporary - theme without own project should be under ~/themes
|
||||
if (descriptor.Location.StartsWith("~/Themes",StringComparison.InvariantCultureIgnoreCase)) {
|
||||
if (descriptor.Location.StartsWith("~/Themes", StringComparison.InvariantCultureIgnoreCase)) {
|
||||
string projectPath = _virtualPathProvider.Combine(descriptor.Location, descriptor.Id,
|
||||
descriptor.Id + ".csproj");
|
||||
|
||||
// ignore themes including a .csproj in this loader
|
||||
if ( _virtualPathProvider.FileExists(projectPath) ) {
|
||||
if (_virtualPathProvider.FileExists(projectPath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -39,7 +41,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
descriptor.Id + ".dll");
|
||||
|
||||
// ignore themes with /bin in this loader
|
||||
if ( _virtualPathProvider.FileExists(assemblyPath) )
|
||||
if (_virtualPathProvider.FileExists(assemblyPath))
|
||||
return null;
|
||||
|
||||
return new ExtensionProbeEntry {
|
||||
@@ -64,5 +66,14 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
ExportedTypes = new Type[0]
|
||||
};
|
||||
}
|
||||
|
||||
public override bool LoaderIsSuitable(ExtensionDescriptor descriptor) {
|
||||
var dependency = _dependenciesFolder.GetDescriptor(descriptor.Id);
|
||||
if (dependency != null && dependency.LoaderName == this.Name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,12 +13,14 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
public class ReferencedExtensionLoader : ExtensionLoaderBase {
|
||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||
private readonly IBuildManager _buildManager;
|
||||
private readonly IDependenciesFolder _dependenciesFolder;
|
||||
|
||||
public ReferencedExtensionLoader(IDependenciesFolder dependenciesFolder, IVirtualPathProvider virtualPathProvider, IBuildManager buildManager)
|
||||
: base(dependenciesFolder) {
|
||||
|
||||
_virtualPathProvider = virtualPathProvider;
|
||||
_buildManager = buildManager;
|
||||
_dependenciesFolder = dependenciesFolder;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
@@ -82,5 +84,14 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
ExportedTypes = assembly.GetExportedTypes()
|
||||
};
|
||||
}
|
||||
|
||||
public override bool LoaderIsSuitable(ExtensionDescriptor descriptor) {
|
||||
var dependency = _dependenciesFolder.GetDescriptor(descriptor.Id);
|
||||
if (dependency != null && dependency.LoaderName == this.Name) {
|
||||
return _buildManager.GetReferencedAssembly(descriptor.Id) != null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Linq;
|
||||
using Orchard.Environment.Descriptor;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Helpers;
|
||||
using Orchard.Environment.Extensions.Loaders;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
@@ -13,6 +13,7 @@ namespace Orchard.Environment.Features {
|
||||
public class FeatureManager : IFeatureManager {
|
||||
private readonly IExtensionManager _extensionManager;
|
||||
private readonly IShellDescriptorManager _shellDescriptorManager;
|
||||
private readonly IEnumerable<IExtensionLoader> _loaders;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to notify about feature dependencies.
|
||||
@@ -21,10 +22,11 @@ namespace Orchard.Environment.Features {
|
||||
|
||||
public FeatureManager(
|
||||
IExtensionManager extensionManager,
|
||||
IShellDescriptorManager shellDescriptorManager) {
|
||||
IShellDescriptorManager shellDescriptorManager,
|
||||
IEnumerable<IExtensionLoader> loaders) {
|
||||
_extensionManager = extensionManager;
|
||||
_shellDescriptorManager = shellDescriptorManager;
|
||||
|
||||
_loaders = loaders;
|
||||
T = NullLocalizer.Instance;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
@@ -161,6 +163,22 @@ namespace Orchard.Environment.Features {
|
||||
return GetAffectedFeatures(featureId, availableFeatures, getEnabledDependants);
|
||||
}
|
||||
|
||||
public bool HasLoader(string featureId) {
|
||||
var descriptor = _extensionManager
|
||||
.AvailableExtensions()
|
||||
.Where(d => DefaultExtensionTypes.IsModule(d.ExtensionType) || DefaultExtensionTypes.IsTheme(d.ExtensionType))
|
||||
.OrderBy(d => d.Id)
|
||||
.FirstOrDefault(e => e.Id == featureId || e.Features.Select(f => f.Id).Contains(featureId));
|
||||
|
||||
foreach (var loader in _loaders) {
|
||||
if (loader.LoaderIsSuitable(descriptor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables a feature.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Environment.Extensions;
|
||||
|
||||
namespace Orchard.Environment.Features {
|
||||
public delegate void FeatureDependencyNotificationHandler(string messageFormat, string featureId, IEnumerable<string> featureIds);
|
||||
@@ -61,5 +62,12 @@ namespace Orchard.Environment.Features {
|
||||
/// <param name="featureId">ID of the feature to check.</param>
|
||||
/// <returns>An enumeration with dependent feature IDs.</returns>
|
||||
IEnumerable<string> GetDependentFeatures(string featureId);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the feature's extension has a loadee, i.e. a suitable <see cref="IExtensionLoader"/> can be found.
|
||||
/// </summary>
|
||||
/// <param name="featureId">ID of the feature to check.</param>
|
||||
/// <returns><c>True</c> if a suitable <see cref="IExtensionLoader"/> can be found.</returns>
|
||||
bool HasLoader(string featureId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user