mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-27 04:19:04 +08:00
Refactor extension folder harvesting
Use composition over inheritance. This will be useful later to improve performance of module/theme manifest harvesting. --HG-- branch : 1.x rename : src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs => src/Orchard/Environment/Extensions/Folders/ExtensionHarvester.cs
This commit is contained in:
@@ -125,7 +125,7 @@ Features:
|
||||
public IEnumerable<ExtensionDescriptor> AvailableExtensions() {
|
||||
foreach (var e in Manifests) {
|
||||
string name = e.Key;
|
||||
yield return ExtensionFolders.GetDescriptorForExtension("~/", name, DefaultExtensionTypes.Module, Manifests[name]);
|
||||
yield return ExtensionHarvester.GetDescriptorForExtension("~/", name, DefaultExtensionTypes.Module, Manifests[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,8 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
}
|
||||
|
||||
var builder = new ContainerBuilder();
|
||||
_folders = new ModuleFolders(new[] { _tempFolderName }, new StubCacheManager(), new StubWebSiteFolder());
|
||||
var harvester = new ExtensionHarvester(new StubCacheManager(), new StubWebSiteFolder());
|
||||
_folders = new ModuleFolders(new[] { _tempFolderName }, harvester);
|
||||
builder.RegisterType<RecipeManager>().As<IRecipeManager>();
|
||||
builder.RegisterType<RecipeHarvester>().As<IRecipeHarvester>();
|
||||
builder.RegisterType<RecipeStepExecutor>().As<IRecipeStepExecutor>();
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Orchard.Tests.DataMigration {
|
||||
public IEnumerable<ExtensionDescriptor> AvailableExtensions() {
|
||||
foreach (var e in Manifests) {
|
||||
string name = e.Key;
|
||||
yield return ExtensionFolders.GetDescriptorForExtension("~/", name, DefaultExtensionTypes.Module, Manifests[name]);
|
||||
yield return ExtensionHarvester.GetDescriptorForExtension("~/", name, DefaultExtensionTypes.Module, Manifests[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ namespace Orchard.Tests.Environment.Extensions {
|
||||
|
||||
[Test]
|
||||
public void IdsFromFoldersWithModuleTxtShouldBeListed() {
|
||||
IExtensionFolders folders = new ModuleFolders(new[] { _tempFolderName }, new StubCacheManager(), new StubWebSiteFolder());
|
||||
var harvester = new ExtensionHarvester(new StubCacheManager(), new StubWebSiteFolder());
|
||||
IExtensionFolders folders = new ModuleFolders(new[] { _tempFolderName }, harvester);
|
||||
var ids = folders.AvailableExtensions().Select(d => d.Id);
|
||||
Assert.That(ids.Count(), Is.EqualTo(5));
|
||||
Assert.That(ids, Has.Some.EqualTo("Sample1")); // Sample1 - obviously
|
||||
@@ -61,7 +62,8 @@ namespace Orchard.Tests.Environment.Extensions {
|
||||
|
||||
[Test]
|
||||
public void ModuleTxtShouldBeParsedAndReturnedAsYamlDocument() {
|
||||
IExtensionFolders folders = new ModuleFolders(new[] { _tempFolderName }, new StubCacheManager(), new StubWebSiteFolder());
|
||||
var harvester = new ExtensionHarvester(new StubCacheManager(), new StubWebSiteFolder());
|
||||
IExtensionFolders folders = new ModuleFolders(new[] { _tempFolderName }, harvester);
|
||||
var sample1 = folders.AvailableExtensions().Single(d => d.Id == "Sample1");
|
||||
Assert.That(sample1.Id, Is.Not.Empty);
|
||||
Assert.That(sample1.Author, Is.EqualTo("Bertrand Le Roy")); // Sample1
|
||||
@@ -69,7 +71,8 @@ namespace Orchard.Tests.Environment.Extensions {
|
||||
|
||||
[Test]
|
||||
public void NamesFromFoldersWithModuleTxtShouldFallBackToIdIfNotGiven() {
|
||||
IExtensionFolders folders = new ModuleFolders(new[] { _tempFolderName }, new StubCacheManager(), new StubWebSiteFolder());
|
||||
var harvester = new ExtensionHarvester(new StubCacheManager(), new StubWebSiteFolder());
|
||||
IExtensionFolders folders = new ModuleFolders(new[] { _tempFolderName }, harvester);
|
||||
var names = folders.AvailableExtensions().Select(d => d.Name);
|
||||
Assert.That(names.Count(), Is.EqualTo(5));
|
||||
Assert.That(names, Has.Some.EqualTo("Le plug-in français")); // Sample1
|
||||
@@ -81,7 +84,8 @@ namespace Orchard.Tests.Environment.Extensions {
|
||||
|
||||
[Test]
|
||||
public void PathsFromFoldersWithModuleTxtShouldFallBackAppropriatelyIfNotGiven() {
|
||||
IExtensionFolders folders = new ModuleFolders(new[] { _tempFolderName }, new StubCacheManager(), new StubWebSiteFolder());
|
||||
var harvester = new ExtensionHarvester(new StubCacheManager(), new StubWebSiteFolder());
|
||||
IExtensionFolders folders = new ModuleFolders(new[] { _tempFolderName }, harvester);
|
||||
var paths = folders.AvailableExtensions().Select(d => d.Path);
|
||||
Assert.That(paths.Count(), Is.EqualTo(5));
|
||||
Assert.That(paths, Has.Some.EqualTo("Sample1")); // Sample1 - Id, Name invalid URL segment
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Orchard.Tests.Environment.Extensions {
|
||||
public IEnumerable<ExtensionDescriptor> AvailableExtensions() {
|
||||
foreach (var e in Manifests) {
|
||||
string name = e.Key;
|
||||
yield return ExtensionFolders.GetDescriptorForExtension("~/", name, _extensionType, Manifests[name]);
|
||||
yield return ExtensionHarvester.GetDescriptorForExtension("~/", name, _extensionType, Manifests[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Orchard.Tests.Environment.Extensions {
|
||||
public IEnumerable<ExtensionDescriptor> AvailableExtensions() {
|
||||
foreach (var e in Manifests) {
|
||||
string name = e.Key;
|
||||
yield return ExtensionFolders.GetDescriptorForExtension("~/", name, _extensionType, Manifests[name]);
|
||||
yield return ExtensionHarvester.GetDescriptorForExtension("~/", name, _extensionType, Manifests[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Orchard.Packaging.Services {
|
||||
if (packageFile != null) {
|
||||
string extensionId = Path.GetFileName(Path.GetDirectoryName(packageFile.Path).TrimEnd('/', '\\'));
|
||||
using (StreamReader streamReader = new StreamReader(packageFile.GetStream())) {
|
||||
return ExtensionFolders.GetDescriptorForExtension("", extensionId, extensionType, streamReader.ReadToEnd());
|
||||
return ExtensionHarvester.GetDescriptorForExtension("", extensionId, extensionType, streamReader.ReadToEnd());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ using Orchard.Logging;
|
||||
using Orchard.Utility.Extensions;
|
||||
|
||||
namespace Orchard.Environment.Extensions.Folders {
|
||||
public class ExtensionFolders : IExtensionFolders {
|
||||
public class ExtensionHarvester : IExtensionHarvester {
|
||||
private const string NameSection = "name";
|
||||
private const string PathSection = "path";
|
||||
private const string DescriptionSection = "description";
|
||||
@@ -29,23 +29,10 @@ namespace Orchard.Environment.Extensions.Folders {
|
||||
private const string PrioritySection = "priority";
|
||||
private const string FeaturesSection = "features";
|
||||
|
||||
private readonly IEnumerable<string> _paths;
|
||||
private readonly string _manifestName;
|
||||
private readonly string _extensionType;
|
||||
private readonly bool _manifestIsOptional;
|
||||
private readonly ICacheManager _cacheManager;
|
||||
private readonly IWebSiteFolder _webSiteFolder;
|
||||
|
||||
protected ExtensionFolders(
|
||||
IEnumerable<string> paths,
|
||||
string manifestName,
|
||||
bool manifestIsOptional,
|
||||
ICacheManager cacheManager,
|
||||
IWebSiteFolder webSiteFolder) {
|
||||
_paths = paths;
|
||||
_manifestName = manifestName;
|
||||
_extensionType = manifestName == "Theme.txt" ? DefaultExtensionTypes.Theme : DefaultExtensionTypes.Module;
|
||||
_manifestIsOptional = manifestIsOptional;
|
||||
public ExtensionHarvester(ICacheManager cacheManager, IWebSiteFolder webSiteFolder) {
|
||||
_cacheManager = cacheManager;
|
||||
_webSiteFolder = webSiteFolder;
|
||||
Logger = NullLogger.Instance;
|
||||
@@ -55,24 +42,30 @@ namespace Orchard.Environment.Extensions.Folders {
|
||||
public Localizer T { get; set; }
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public IEnumerable<ExtensionDescriptor> AvailableExtensions() {
|
||||
return _paths
|
||||
.SelectMany(path => _cacheManager.Get(path, ctx => {
|
||||
ctx.Monitor(_webSiteFolder.WhenPathChanges(ctx.Key));
|
||||
return AvailableExtensionsInFolder(ctx.Key);
|
||||
}))
|
||||
public IEnumerable<ExtensionDescriptor> HarvestExtensions(IEnumerable<string> paths, string extensionType, string manifestName, bool manifestIsOptional) {
|
||||
return paths
|
||||
.SelectMany(path => HarvestExtensions(path, extensionType, manifestName, manifestIsOptional))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private List<ExtensionDescriptor> AvailableExtensionsInFolder(string path) {
|
||||
private IEnumerable<ExtensionDescriptor> HarvestExtensions(string path, string extensionType, string manifestName, bool manifestIsOptional) {
|
||||
string key = string.Format("{0}-{1}-{2}", path, manifestName, extensionType);
|
||||
|
||||
return _cacheManager.Get(key, ctx => {
|
||||
ctx.Monitor(_webSiteFolder.WhenPathChanges(path));
|
||||
return AvailableExtensionsInFolder(path, extensionType, manifestName, manifestIsOptional);
|
||||
});
|
||||
}
|
||||
|
||||
private List<ExtensionDescriptor> AvailableExtensionsInFolder(string path, string extensionType, string manifestName, bool manifestIsOptional) {
|
||||
Logger.Information("Start looking for extensions in '{0}'...", path);
|
||||
var subfolderPaths = _webSiteFolder.ListDirectories(path);
|
||||
var localList = new List<ExtensionDescriptor>();
|
||||
foreach (var subfolderPath in subfolderPaths) {
|
||||
var extensionId = Path.GetFileName(subfolderPath.TrimEnd('/', '\\'));
|
||||
var manifestPath = Path.Combine(subfolderPath, _manifestName);
|
||||
var manifestPath = Path.Combine(subfolderPath, manifestName);
|
||||
try {
|
||||
var descriptor = GetExtensionDescriptor(path, extensionId, manifestPath);
|
||||
var descriptor = GetExtensionDescriptor(path, extensionId, extensionType, manifestPath, manifestIsOptional);
|
||||
|
||||
if (descriptor == null)
|
||||
continue;
|
||||
@@ -124,12 +117,12 @@ namespace Orchard.Environment.Extensions.Folders {
|
||||
return extensionDescriptor;
|
||||
}
|
||||
|
||||
private ExtensionDescriptor GetExtensionDescriptor(string locationPath, string extensionId, string manifestPath) {
|
||||
private ExtensionDescriptor GetExtensionDescriptor(string locationPath, string extensionId, string extensionType, string manifestPath, bool manifestIsOptional) {
|
||||
return _cacheManager.Get(manifestPath, context => {
|
||||
context.Monitor(_webSiteFolder.WhenPathChanges(manifestPath));
|
||||
var manifestText = _webSiteFolder.ReadFile(manifestPath);
|
||||
if (manifestText == null) {
|
||||
if (_manifestIsOptional) {
|
||||
if (manifestIsOptional) {
|
||||
manifestText = string.Format("Id: {0}", extensionId);
|
||||
}
|
||||
else {
|
||||
@@ -137,14 +130,10 @@ namespace Orchard.Environment.Extensions.Folders {
|
||||
}
|
||||
}
|
||||
|
||||
return GetDescriptorForExtension(locationPath, extensionId, manifestText);
|
||||
return GetDescriptorForExtension(locationPath, extensionId, extensionType, manifestText);
|
||||
});
|
||||
}
|
||||
|
||||
private ExtensionDescriptor GetDescriptorForExtension(string locationPath, string extensionId, string manifestText) {
|
||||
return GetDescriptorForExtension(locationPath, extensionId, _extensionType, manifestText);
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> ParseManifest(string manifestText) {
|
||||
var manifest = new Dictionary<string, string>();
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
|
||||
namespace Orchard.Environment.Extensions.Folders {
|
||||
public interface IExtensionHarvester {
|
||||
IEnumerable<ExtensionDescriptor> HarvestExtensions(IEnumerable<string> paths, string extensionType, string manifestName, bool manifestIsOptional);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Caching;
|
||||
using Orchard.FileSystems.WebSite;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
|
||||
namespace Orchard.Environment.Extensions.Folders {
|
||||
public class ModuleFolders : ExtensionFolders {
|
||||
public ModuleFolders(IEnumerable<string> paths, ICacheManager cacheManager, IWebSiteFolder webSiteFolder) :
|
||||
base(paths, "Module.txt", false/*isManifestOptional*/, cacheManager, webSiteFolder) {
|
||||
public class ModuleFolders : IExtensionFolders {
|
||||
private readonly IEnumerable<string> _paths;
|
||||
private readonly IExtensionHarvester _extensionHarvester;
|
||||
|
||||
public ModuleFolders(IEnumerable<string> paths, IExtensionHarvester extensionHarvester) {
|
||||
_paths = paths;
|
||||
_extensionHarvester = extensionHarvester;
|
||||
}
|
||||
|
||||
public IEnumerable<ExtensionDescriptor> AvailableExtensions() {
|
||||
return _extensionHarvester.HarvestExtensions(_paths, DefaultExtensionTypes.Module, "Module.txt", false/*isManifestOptional*/);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Caching;
|
||||
using Orchard.FileSystems.WebSite;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
|
||||
namespace Orchard.Environment.Extensions.Folders {
|
||||
public class ThemeFolders : ExtensionFolders {
|
||||
public ThemeFolders(IEnumerable<string> paths, ICacheManager cacheManager, IWebSiteFolder webSiteFolder) :
|
||||
base(paths, "Theme.txt", false/*manifestIsOptional*/, cacheManager, webSiteFolder) {
|
||||
public class ThemeFolders : IExtensionFolders {
|
||||
private readonly IEnumerable<string> _paths;
|
||||
private readonly IExtensionHarvester _extensionHarvester;
|
||||
|
||||
public ThemeFolders(IEnumerable<string> paths, IExtensionHarvester extensionHarvester) {
|
||||
_paths = paths;
|
||||
_extensionHarvester = extensionHarvester;
|
||||
}
|
||||
|
||||
public IEnumerable<ExtensionDescriptor> AvailableExtensions() {
|
||||
return _extensionHarvester.HarvestExtensions(_paths, DefaultExtensionTypes.Theme, "Theme.txt", false/*isManifestOptional*/);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,7 @@ namespace Orchard.Environment {
|
||||
builder.RegisterType<ExtensionMonitoringCoordinator>().As<IExtensionMonitoringCoordinator>().SingleInstance();
|
||||
builder.RegisterType<ExtensionManager>().As<IExtensionManager>().SingleInstance();
|
||||
{
|
||||
builder.RegisterType<ExtensionHarvester>().As<IExtensionHarvester>().SingleInstance();
|
||||
builder.RegisterType<ModuleFolders>().As<IExtensionFolders>().SingleInstance()
|
||||
.WithParameter(new NamedParameter("paths", new[] { "~/Core", "~/Modules" }));
|
||||
builder.RegisterType<ThemeFolders>().As<IExtensionFolders>().SingleInstance()
|
||||
|
||||
@@ -178,6 +178,7 @@
|
||||
<Compile Include="Caching\DefaultAsyncTokenProvider.cs" />
|
||||
<Compile Include="Environment\Extensions\ExtensionMonitoringCoordinator.cs" />
|
||||
<Compile Include="Caching\IAsyncTokenProvider.cs" />
|
||||
<Compile Include="Environment\Extensions\Folders\IExtensionHarvester.cs" />
|
||||
<Compile Include="Environment\Extensions\IExtensionMonitoringCoordinator.cs" />
|
||||
<Compile Include="Environment\Extensions\OrchardSuppressDependencyAttribute.cs" />
|
||||
<Compile Include="Environment\Features\IFeatureManager.cs" />
|
||||
@@ -710,7 +711,7 @@
|
||||
<Compile Include="Events\EventsRegistrationSource.cs" />
|
||||
<Compile Include="Environment\Configuration\IShellSettingsManagerEventHandler.cs" />
|
||||
<Compile Include="Events\IEventBus.cs" />
|
||||
<Compile Include="Environment\Extensions\Folders\ExtensionFolders.cs" />
|
||||
<Compile Include="Environment\Extensions\Folders\ExtensionHarvester.cs" />
|
||||
<Compile Include="Environment\Extensions\Models\Feature.cs" />
|
||||
<Compile Include="Environment\Extensions\Models\FeatureDescriptor.cs" />
|
||||
<Compile Include="Environment\Extensions\OrchardFeatureAttribute.cs" />
|
||||
|
||||
Reference in New Issue
Block a user