diff --git a/src/Orchard.Tests/DisplayManagement/Descriptors/ShapeTemplateBindingStrategyTests.cs b/src/Orchard.Tests/DisplayManagement/Descriptors/ShapeTemplateBindingStrategyTests.cs index d842d9bda..4663a30de 100644 --- a/src/Orchard.Tests/DisplayManagement/Descriptors/ShapeTemplateBindingStrategyTests.cs +++ b/src/Orchard.Tests/DisplayManagement/Descriptors/ShapeTemplateBindingStrategyTests.cs @@ -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 _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().As(); builder.RegisterType().As(); builder.RegisterInstance(_testViewEngine).As(); + builder.RegisterInstance(_testVirtualPathProvider).As(); var extensionManager = new Mock(); builder.Register(ctx => extensionManager); @@ -35,20 +38,62 @@ namespace Orchard.Tests.DisplayManagement.Descriptors { } public class TestViewEngine : Dictionary, IShapeTemplateViewEngine { - public IEnumerable DetectTemplateFileNames(string virtualPath) { - var virtualPathNorm = virtualPath.Replace("\\", "/"); + public IEnumerable DetectTemplateFileNames(IEnumerable 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 ListFiles(string path) { + return new List {"~/Modules/Alpha/Views/AlphaShape.blah"}; + } + + public IEnumerable ListDirectories(string path) { + throw new NotImplementedException(); } } diff --git a/src/Orchard/Data/Migration/DataMigrationManager.cs b/src/Orchard/Data/Migration/DataMigrationManager.cs index 8ef96a517..b416e1bf3 100644 --- a/src/Orchard/Data/Migration/DataMigrationManager.cs +++ b/src/Orchard/Data/Migration/DataMigrationManager.cs @@ -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 GetFeaturesThatNeedUpdate() { + var currentVersions = _dataMigrationRepository.Table.ToDictionary(r => r.DataMigrationClass); - var features = new List(); + 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 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 /// private static Dictionary CreateUpgradeLookupTable(IDataMigration dataMigration) { - var updateMethodNameRegex = new Regex(@"^UpdateFrom(?\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(); + private static Tuple 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(versionValue, mi); } } - return lookupTable; + return null; } /// diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/IShapeTemplateHarvester.cs b/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/IShapeTemplateHarvester.cs index 3bbcd92d7..d9b4e2026 100644 --- a/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/IShapeTemplateHarvester.cs +++ b/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/IShapeTemplateHarvester.cs @@ -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 { /// @@ -70,7 +66,7 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy { } public interface IShapeTemplateViewEngine : IDependency { - IEnumerable DetectTemplateFileNames(string virtualPath); + IEnumerable DetectTemplateFileNames(IEnumerable fileNames); } } diff --git a/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/ShapeTemplateBindingStrategy.cs b/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/ShapeTemplateBindingStrategy.cs index f0c5cf868..f6270427d 100644 --- a/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/ShapeTemplateBindingStrategy.cs +++ b/src/Orchard/DisplayManagement/Descriptors/ShapeTemplateStrategy/ShapeTemplateBindingStrategy.cs @@ -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 _harvesters; private readonly IEnumerable _shapeTemplateViewEngines; + public ShapeTemplateBindingStrategy( IEnumerable harvesters, ShellDescriptor shellDescriptor, IExtensionManager extensionManager, + IVirtualPathProvider virtualPathProvider, IEnumerable 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 => { diff --git a/src/Orchard/Mvc/ViewEngines/Razor/RazorViewEngineProvider.cs b/src/Orchard/Mvc/ViewEngines/Razor/RazorViewEngineProvider.cs index 953c7e8ab..6d103b490 100644 --- a/src/Orchard/Mvc/ViewEngines/Razor/RazorViewEngineProvider.cs +++ b/src/Orchard/Mvc/ViewEngines/Razor/RazorViewEngineProvider.cs @@ -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 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 DetectTemplateFileNames(IEnumerable fileNames) { + return fileNames.Where(fileName => fileName.EndsWith(".cshtml", StringComparison.OrdinalIgnoreCase)); } } } diff --git a/src/Orchard/Mvc/ViewEngines/WebForms/WebFormViewEngineProvider.cs b/src/Orchard/Mvc/ViewEngines/WebForms/WebFormViewEngineProvider.cs index dd9eeae73..8b6d0f04b 100644 --- a/src/Orchard/Mvc/ViewEngines/WebForms/WebFormViewEngineProvider.cs +++ b/src/Orchard/Mvc/ViewEngines/WebForms/WebFormViewEngineProvider.cs @@ -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 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 DetectTemplateFileNames(IEnumerable fileNames) { + return fileNames.Where(fileName => fileName.EndsWith(".aspx", StringComparison.OrdinalIgnoreCase) || + fileName.EndsWith(".ascx", StringComparison.OrdinalIgnoreCase)); + } } }