mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 03:25:23 +08:00
Merge
--HG-- branch : dev
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Autofac;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
@@ -11,6 +10,7 @@ using Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.FileSystems.VirtualPath;
|
||||
|
||||
namespace Orchard.Tests.DisplayManagement.Descriptors {
|
||||
[TestFixture]
|
||||
@@ -18,16 +18,19 @@ namespace Orchard.Tests.DisplayManagement.Descriptors {
|
||||
private ShellDescriptor _descriptor;
|
||||
private IList<FeatureDescriptor> _features;
|
||||
private TestViewEngine _testViewEngine;
|
||||
private TestVirtualPathProvider _testVirtualPathProvider;
|
||||
|
||||
|
||||
protected override void Register(Autofac.ContainerBuilder builder) {
|
||||
_descriptor = new ShellDescriptor { };
|
||||
_testViewEngine = new TestViewEngine();
|
||||
_testVirtualPathProvider = new TestVirtualPathProvider();
|
||||
|
||||
builder.Register(ctx => _descriptor);
|
||||
builder.RegisterType<ShapeTemplateBindingStrategy>().As<IShapeTableProvider>();
|
||||
builder.RegisterType<BasicShapeTemplateHarvester>().As<IShapeTemplateHarvester>();
|
||||
builder.RegisterInstance(_testViewEngine).As<IShapeTemplateViewEngine>();
|
||||
builder.RegisterInstance(_testVirtualPathProvider).As<IVirtualPathProvider>();
|
||||
|
||||
var extensionManager = new Mock<IExtensionManager>();
|
||||
builder.Register(ctx => extensionManager);
|
||||
@@ -35,20 +38,62 @@ namespace Orchard.Tests.DisplayManagement.Descriptors {
|
||||
}
|
||||
|
||||
public class TestViewEngine : Dictionary<string, object>, IShapeTemplateViewEngine {
|
||||
public IEnumerable<string> DetectTemplateFileNames(string virtualPath) {
|
||||
var virtualPathNorm = virtualPath.Replace("\\", "/");
|
||||
public IEnumerable<string> DetectTemplateFileNames(IEnumerable<string> fileNames) {
|
||||
return fileNames;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var key in Keys) {
|
||||
var keyNorm = key.Replace("\\", "/");
|
||||
public class TestVirtualPathProvider : IVirtualPathProvider {
|
||||
public string Combine(params string[] paths) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
if (keyNorm.StartsWith(virtualPathNorm, StringComparison.OrdinalIgnoreCase)) {
|
||||
var rest = keyNorm.Substring(virtualPathNorm.Length).TrimStart('/', '\\');
|
||||
if (rest.IndexOfAny(new[] { '/', '\\' }) != -1) {
|
||||
continue;
|
||||
}
|
||||
yield return Path.GetFileNameWithoutExtension(rest);
|
||||
}
|
||||
}
|
||||
public string ToAppRelative(string virtualPath) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string MapPath(string virtualPath) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool FileExists(string virtualPath) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Stream OpenFile(string virtualPath) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public StreamWriter CreateText(string virtualPath) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Stream CreateFile(string virtualPath) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public DateTime GetFileLastWriteTimeUtc(string virtualPath) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool DirectoryExists(string virtualPath) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void CreateDirectory(string virtualPath) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetDirectoryName(string virtualPath) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<string> ListFiles(string path) {
|
||||
return new List<string> {"~/Modules/Alpha/Views/AlphaShape.blah"};
|
||||
}
|
||||
|
||||
public IEnumerable<string> ListDirectories(string path) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2,13 +2,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.Data.Migration.Interpreters;
|
||||
using Orchard.Data.Migration.Records;
|
||||
using Orchard.Data.Migration.Schema;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.State;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Logging;
|
||||
|
||||
@@ -41,38 +39,17 @@ namespace Orchard.Data.Migration {
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public IEnumerable<string> GetFeaturesThatNeedUpdate() {
|
||||
var currentVersions = _dataMigrationRepository.Table.ToDictionary(r => r.DataMigrationClass);
|
||||
|
||||
var features = new List<string>();
|
||||
var outOfDateMigrations = _dataMigrations.Where(dataMigration => {
|
||||
DataMigrationRecord record;
|
||||
if (currentVersions.TryGetValue(dataMigration.GetType().FullName, out record))
|
||||
return CreateUpgradeLookupTable(dataMigration).ContainsKey(record.Version);
|
||||
|
||||
// compare current version and available migration methods for each migration class
|
||||
foreach ( var dataMigration in _dataMigrations ) {
|
||||
|
||||
// get current version for this migration
|
||||
var dataMigrationRecord = GetDataMigrationRecord(dataMigration);
|
||||
return (GetCreateMethod(dataMigration) != null);
|
||||
});
|
||||
|
||||
var current = 0;
|
||||
if (dataMigrationRecord != null) {
|
||||
current = dataMigrationRecord.Version;
|
||||
}
|
||||
|
||||
// do we need to call Create() ?
|
||||
if (current == 0) {
|
||||
|
||||
// try to resolve a Create method
|
||||
if ( GetCreateMethod(dataMigration) != null ) {
|
||||
features.Add(dataMigration.Feature.Descriptor.Id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var lookupTable = CreateUpgradeLookupTable(dataMigration);
|
||||
|
||||
if(lookupTable.ContainsKey(current)) {
|
||||
features.Add(dataMigration.Feature.Descriptor.Id);
|
||||
}
|
||||
}
|
||||
|
||||
return features;
|
||||
return outOfDateMigrations.Select(m => m.Feature.Descriptor.Id).ToList();
|
||||
}
|
||||
|
||||
public void Update(IEnumerable<string> features) {
|
||||
@@ -206,20 +183,26 @@ namespace Orchard.Data.Migration {
|
||||
/// Create a list of all available Update methods from a data migration class, indexed by the version number
|
||||
/// </summary>
|
||||
private static Dictionary<int, MethodInfo> CreateUpgradeLookupTable(IDataMigration dataMigration) {
|
||||
var updateMethodNameRegex = new Regex(@"^UpdateFrom(?<version>\d+)$", RegexOptions.Compiled);
|
||||
return dataMigration
|
||||
.GetType()
|
||||
.GetMethods(BindingFlags.Public | BindingFlags.Instance)
|
||||
.Select(mi => GetUpdateMethod(mi))
|
||||
.Where(tuple => tuple != null)
|
||||
.ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
|
||||
}
|
||||
|
||||
// update methods might also be called after Create()
|
||||
var lookupTable = new Dictionary<int, MethodInfo>();
|
||||
private static Tuple<int, MethodInfo> GetUpdateMethod(MethodInfo mi) {
|
||||
const string updatefromPrefix = "UpdateFrom";
|
||||
|
||||
// construct a lookup table with all managed initial versions
|
||||
foreach ( var methodInfo in dataMigration.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance) ) {
|
||||
var match = updateMethodNameRegex.Match(methodInfo.Name);
|
||||
if ( match.Success ) {
|
||||
lookupTable.Add(int.Parse(match.Groups["version"].Value), methodInfo);
|
||||
if (mi.Name.StartsWith(updatefromPrefix)) {
|
||||
var version = mi.Name.Substring(updatefromPrefix.Length);
|
||||
int versionValue;
|
||||
if (int.TryParse(version, out versionValue)) {
|
||||
return new Tuple<int, MethodInfo>(versionValue, mi);
|
||||
}
|
||||
}
|
||||
|
||||
return lookupTable;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Events;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy {
|
||||
/// <summary>
|
||||
@@ -70,7 +66,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy {
|
||||
}
|
||||
|
||||
public interface IShapeTemplateViewEngine : IDependency {
|
||||
IEnumerable<string> DetectTemplateFileNames(string virtualPath);
|
||||
IEnumerable<string> DetectTemplateFileNames(IEnumerable<string> fileNames);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -10,22 +9,27 @@ using Orchard.DisplayManagement.Implementation;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.FileSystems.VirtualPath;
|
||||
|
||||
namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy {
|
||||
public class ShapeTemplateBindingStrategy : IShapeTableProvider {
|
||||
private readonly ShellDescriptor _shellDescriptor;
|
||||
private readonly IExtensionManager _extensionManager;
|
||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||
private readonly IEnumerable<IShapeTemplateHarvester> _harvesters;
|
||||
private readonly IEnumerable<IShapeTemplateViewEngine> _shapeTemplateViewEngines;
|
||||
|
||||
|
||||
public ShapeTemplateBindingStrategy(
|
||||
IEnumerable<IShapeTemplateHarvester> harvesters,
|
||||
ShellDescriptor shellDescriptor,
|
||||
IExtensionManager extensionManager,
|
||||
IVirtualPathProvider virtualPathProvider,
|
||||
IEnumerable<IShapeTemplateViewEngine> shapeTemplateViewEngines) {
|
||||
_harvesters = harvesters;
|
||||
_shellDescriptor = shellDescriptor;
|
||||
_extensionManager = extensionManager;
|
||||
_virtualPathProvider = virtualPathProvider;
|
||||
_shapeTemplateViewEngines = shapeTemplateViewEngines;
|
||||
}
|
||||
|
||||
@@ -43,14 +47,15 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy {
|
||||
|
||||
var hits = activeExtensions.SelectMany(extensionDescriptor => {
|
||||
var pathContexts = harvesterInfos.SelectMany(harvesterInfo => harvesterInfo.subPaths.Select(subPath => {
|
||||
var basePath = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id);
|
||||
var virtualPath = Path.Combine(basePath, subPath);
|
||||
return new { harvesterInfo.harvester, basePath, subPath, virtualPath };
|
||||
var basePath = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/');
|
||||
var virtualPath = Path.Combine(basePath, subPath).Replace(Path.DirectorySeparatorChar, '/');
|
||||
var fileNames = _virtualPathProvider.ListFiles(virtualPath).Select(Path.GetFileName);
|
||||
return new { harvesterInfo.harvester, basePath, subPath, virtualPath, fileNames };
|
||||
}));
|
||||
|
||||
var fileContexts = pathContexts.SelectMany(pathContext => _shapeTemplateViewEngines.SelectMany(ve => {
|
||||
var fileNames = ve.DetectTemplateFileNames(pathContext.virtualPath);
|
||||
return fileNames.Select(fileName => new { fileName = Path.GetFileNameWithoutExtension(fileName), fileVirtualPath = Path.Combine(pathContext.virtualPath, fileName).Replace('\\', '/'), pathContext });
|
||||
var fileNames = ve.DetectTemplateFileNames(pathContext.fileNames);
|
||||
return fileNames.Select(fileName => new { fileName = Path.GetFileNameWithoutExtension(fileName), fileVirtualPath = Path.Combine(pathContext.virtualPath, fileName).Replace(Path.DirectorySeparatorChar, '/'), pathContext });
|
||||
}));
|
||||
|
||||
var shapeContexts = fileContexts.SelectMany(fileContext => {
|
||||
|
@@ -1,19 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy;
|
||||
using Orchard.FileSystems.VirtualPath;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Mvc.ViewEngines.WebForms;
|
||||
|
||||
namespace Orchard.Mvc.ViewEngines.Razor {
|
||||
public class RazorViewEngineProvider : IViewEngineProvider, IShapeTemplateViewEngine {
|
||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||
|
||||
public RazorViewEngineProvider(IVirtualPathProvider virtualPathProvider) {
|
||||
_virtualPathProvider = virtualPathProvider;
|
||||
public RazorViewEngineProvider() {
|
||||
Logger = NullLogger.Instance;
|
||||
RazorCompilationEventsShim.EnsureInitialized();
|
||||
}
|
||||
@@ -103,13 +98,8 @@ namespace Orchard.Mvc.ViewEngines.Razor {
|
||||
};
|
||||
}
|
||||
|
||||
public IEnumerable<string> DetectTemplateFileNames(string virtualPath) {
|
||||
var fileNames = _virtualPathProvider.ListFiles(virtualPath).Select(Path.GetFileName);
|
||||
foreach (var fileName in fileNames) {
|
||||
if (fileName.EndsWith(".cshtml", StringComparison.OrdinalIgnoreCase)) {
|
||||
yield return fileName;
|
||||
}
|
||||
}
|
||||
public IEnumerable<string> DetectTemplateFileNames(IEnumerable<string> fileNames) {
|
||||
return fileNames.Where(fileName => fileName.EndsWith(".cshtml", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,18 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy;
|
||||
using Orchard.FileSystems.VirtualPath;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Mvc.ViewEngines.WebForms {
|
||||
public class WebFormViewEngineProvider : IViewEngineProvider, IShapeTemplateViewEngine {
|
||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||
|
||||
public WebFormViewEngineProvider(IVirtualPathProvider virtualPathProvider) {
|
||||
_virtualPathProvider = virtualPathProvider;
|
||||
public WebFormViewEngineProvider() {
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
@@ -109,14 +104,9 @@ namespace Orchard.Mvc.ViewEngines.WebForms {
|
||||
};
|
||||
}
|
||||
|
||||
public IEnumerable<string> DetectTemplateFileNames(string virtualPath) {
|
||||
var fileNames = _virtualPathProvider.ListFiles(virtualPath).Select(Path.GetFileName);
|
||||
foreach (var fileName in fileNames) {
|
||||
if (fileName.EndsWith(".aspx", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.EndsWith(".ascx", StringComparison.OrdinalIgnoreCase)) {
|
||||
yield return fileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
public IEnumerable<string> DetectTemplateFileNames(IEnumerable<string> fileNames) {
|
||||
return fileNames.Where(fileName => fileName.EndsWith(".aspx", StringComparison.OrdinalIgnoreCase) ||
|
||||
fileName.EndsWith(".ascx", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user