diff --git a/src/Orchard.Profile/Tests/HttpClient.cs b/src/Orchard.Profile/Tests/HttpClient.cs index 363e3b9a3..ec89c114d 100644 --- a/src/Orchard.Profile/Tests/HttpClient.cs +++ b/src/Orchard.Profile/Tests/HttpClient.cs @@ -18,7 +18,18 @@ namespace Orchard.Profile.Tests { [Given(@"I am logged in")] public void GivenIAmLoggedIn() { - DoRequest("/Users/Account/LogOn", "userNameOrEmail=admin&password=profiling-secret&rememberMe=false"); + DoRequest("/Users/Account/LogOn"); + + const string requestVerificationTokenName = "__RequestVerificationToken"; + const string valueMarker = "value=\""; + + var tokenIndex = _text.IndexOf(requestVerificationTokenName); + var valueIndex = _text.IndexOf(valueMarker, tokenIndex); + var valueStart = valueIndex + valueMarker.Length; + var valueEnd = _text.IndexOf("\"", valueStart); + var requestVerificationTokenValue = _text.Substring(valueStart, valueEnd - valueStart); + + DoRequest("/Users/Account/LogOn", "userNameOrEmail=admin&password=profiling-secret&rememberMe=false&" + requestVerificationTokenName + "=" + requestVerificationTokenValue); } [When(@"I go to ""(.*)""")] diff --git a/src/Orchard.Profile/Tests/Profiling.feature b/src/Orchard.Profile/Tests/Profiling.feature index 741abe6d5..352c133c1 100644 --- a/src/Orchard.Profile/Tests/Profiling.feature +++ b/src/Orchard.Profile/Tests/Profiling.feature @@ -3,6 +3,12 @@ As a developer I want to generate a fixed number of repeatable requests +Scenario: Warmup + Given I am logged in + When I go to "/admin" + When I go to "/blog0" + When I go to "/" + Scenario: Dashboard Given I am logged in When I go to "/admin" 40 times diff --git a/src/Orchard.Profile/Tests/Profiling.feature.cs b/src/Orchard.Profile/Tests/Profiling.feature.cs index b986aaa0e..8673be112 100644 --- a/src/Orchard.Profile/Tests/Profiling.feature.cs +++ b/src/Orchard.Profile/Tests/Profiling.feature.cs @@ -2,7 +2,7 @@ // // This code was generated by SpecFlow (http://www.specflow.org/). // SpecFlow Version:1.2.0.0 -// Runtime Version:2.0.50727.3603 +// Runtime Version:2.0.50727.4927 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -51,15 +51,34 @@ namespace Orchard.Profile.Tests } [NUnit.Framework.TestAttribute()] - [NUnit.Framework.DescriptionAttribute("Dashboard")] - public virtual void Dashboard() + [NUnit.Framework.DescriptionAttribute("Warmup")] + public virtual void Warmup() { - TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Dashboard", ((string[])(null))); + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Warmup", ((string[])(null))); #line 6 this.ScenarioSetup(scenarioInfo); #line 7 testRunner.Given("I am logged in"); #line 8 + testRunner.When("I go to \"/admin\""); +#line 9 + testRunner.When("I go to \"/blog0\""); +#line 10 + testRunner.When("I go to \"/\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Dashboard")] + public virtual void Dashboard() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Dashboard", ((string[])(null))); +#line 12 +this.ScenarioSetup(scenarioInfo); +#line 13 + testRunner.Given("I am logged in"); +#line 14 testRunner.When("I go to \"/admin\" 40 times"); #line hidden testRunner.CollectScenarioErrors(); @@ -70,19 +89,19 @@ this.ScenarioSetup(scenarioInfo); public virtual void HittingBlogs() { TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Hitting blogs", ((string[])(null))); -#line 10 -this.ScenarioSetup(scenarioInfo); -#line 11 - testRunner.Given("I am logged in"); -#line 12 - testRunner.When("I go to \"/blog0\" 10 times"); -#line 13 - testRunner.When("I go to \"/blog1\" 10 times"); -#line 14 - testRunner.When("I go to \"/blog2\" 10 times"); -#line 15 - testRunner.When("I go to \"/blog3\" 10 times"); #line 16 +this.ScenarioSetup(scenarioInfo); +#line 17 + testRunner.Given("I am logged in"); +#line 18 + testRunner.When("I go to \"/blog0\" 10 times"); +#line 19 + testRunner.When("I go to \"/blog1\" 10 times"); +#line 20 + testRunner.When("I go to \"/blog2\" 10 times"); +#line 21 + testRunner.When("I go to \"/blog3\" 10 times"); +#line 22 testRunner.When("I go to \"/blog4\" 10 times"); #line hidden testRunner.CollectScenarioErrors(); @@ -93,11 +112,11 @@ this.ScenarioSetup(scenarioInfo); public virtual void HittingHomePage() { TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Hitting home page", ((string[])(null))); -#line 18 +#line 24 this.ScenarioSetup(scenarioInfo); -#line 19 +#line 25 testRunner.Given("I am logged in"); -#line 20 +#line 26 testRunner.When("I go to \"/\" 40 times"); #line hidden testRunner.CollectScenarioErrors(); diff --git a/src/Orchard.Profile/profiling-setup-commands.txt b/src/Orchard.Profile/profiling-setup-commands.txt index 15f7607eb..f839517bc 100644 --- a/src/Orchard.Profile/profiling-setup-commands.txt +++ b/src/Orchard.Profile/profiling-setup-commands.txt @@ -1,6 +1,3 @@ -help commands -setup /SiteName:Profiling /AdminUsername:admin /AdminPassword:profiling-secret /DatabaseProvider:SQLite /EnabledFeatures:Orchard.Framework,Common,Dashboard,Feeds,HomePage,Navigation,Scheduling,Settings,XmlRpc,Orchard.Users,Orchard.Roles,TinyMce,Orchard.Modules,Orchard.Themes,Orchard.MultiTenancy,Orchard.Pages,Orchard.Blogs,Orchard.Comments,Futures.Widgets,Orchard.Media,Orchard.Tags,Orchard.DevTools -help commands -tenant list -feature list +setup /SiteName:Profiling /AdminUsername:admin /AdminPassword:profiling-secret /DatabaseProvider:SQLite /EnabledFeatures:Orchard.Framework,Common,Dashboard,Feeds,HomePage,Navigation,Scheduling,Settings,XmlRpc,Orchard.Users,Orchard.Roles,TinyMce,Orchard.Modules,Orchard.Themes,Orchard.MultiTenancy,Orchard.Pages,Orchard.Blogs,Orchard.Comments,Futures.Widgets,Orchard.Media,Orchard.Tags,Orchard.DevTools add profiling data +feature disable Orchard.DevTools diff --git a/src/Orchard.Tests/Environment/Configuration/AppDataFolderTests.cs b/src/Orchard.Tests/Environment/Configuration/AppDataFolderTests.cs index 5790f5820..745761ae6 100644 --- a/src/Orchard.Tests/Environment/Configuration/AppDataFolderTests.cs +++ b/src/Orchard.Tests/Environment/Configuration/AppDataFolderTests.cs @@ -2,6 +2,7 @@ using System.Linq; using NUnit.Framework; using Orchard.Environment.Configuration; +using Orchard.Environment.FileSystems; namespace Orchard.Tests.Environment.Configuration { [TestFixture] diff --git a/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs b/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs index 3c0814f86..9fda5a2e5 100644 --- a/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs +++ b/src/Orchard.Tests/Environment/DefaultOrchardHostTests.cs @@ -15,6 +15,7 @@ using Orchard.Environment.Configuration; using Orchard.Environment.Extensions; using Orchard.Environment.Extensions.Folders; using Orchard.Environment.Extensions.Models; +using Orchard.Environment.FileSystems; using Orchard.Environment.ShellBuilders; using Orchard.Environment.Topology; using Orchard.Environment.Topology.Models; diff --git a/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs b/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs index b023f2dd8..1ea84731c 100644 --- a/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs +++ b/src/Orchard.Tests/Environment/Extensions/ExtensionFoldersTests.cs @@ -49,7 +49,7 @@ namespace Orchard.Tests.Environment.Extensions { [Test] public void NamesFromFoldersWithModuleTxtShouldBeListed() { - var folders = new ModuleFolders(new[] { _tempFolderName }); + var folders = new ModuleFolders(new[] { _tempFolderName },null,null); var names = folders.ListNames(); Assert.That(names.Count(), Is.EqualTo(2)); Assert.That(names, Has.Some.EqualTo("Sample1")); @@ -58,7 +58,7 @@ namespace Orchard.Tests.Environment.Extensions { [Test] public void ModuleTxtShouldBeParsedAndReturnedAsYamlDocument() { - var folders = new ModuleFolders(new[] { _tempFolderName }); + var folders = new ModuleFolders(new[] { _tempFolderName },null,null); var sample1 = folders.ParseManifest("Sample1"); var mapping = (Mapping)sample1.YamlDocument.Root; var entities = mapping.Entities diff --git a/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs b/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs index 0e5026b09..5852c1028 100644 --- a/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs +++ b/src/Orchard.Tests/Environment/Extensions/ExtensionManagerTests.cs @@ -51,6 +51,10 @@ namespace Orchard.Tests.Environment.Extensions { } return null; } + + public IEnumerable AvailableExtensions() { + throw new NotImplementedException(); + } } public class StubLoaders : IExtensionLoader { diff --git a/src/Orchard.Tests/Environment/Topology/DefaultShellDescriptorCacheTests.cs b/src/Orchard.Tests/Environment/Topology/DefaultShellDescriptorCacheTests.cs index 426d919a4..7f24183fe 100644 --- a/src/Orchard.Tests/Environment/Topology/DefaultShellDescriptorCacheTests.cs +++ b/src/Orchard.Tests/Environment/Topology/DefaultShellDescriptorCacheTests.cs @@ -4,6 +4,7 @@ using System.Xml; using Autofac; using NUnit.Framework; using Orchard.Environment.Configuration; +using Orchard.Environment.FileSystems; using Orchard.Environment.Topology; using Orchard.Environment.Topology.Models; diff --git a/src/Orchard.Tests/Orchard.Framework.Tests.csproj b/src/Orchard.Tests/Orchard.Framework.Tests.csproj index 7eb159c9c..cf8427eeb 100644 --- a/src/Orchard.Tests/Orchard.Framework.Tests.csproj +++ b/src/Orchard.Tests/Orchard.Framework.Tests.csproj @@ -56,6 +56,14 @@ False ..\..\lib\fluentnhibernate\FluentNHibernate.dll + + False + ..\..\lib\machine.migrations\Machine.Migrations.dll + + + False + ..\..\lib\machine.migrations\Machine.Migrations.NHibernate.dll + False ..\..\lib\moq\Moq.dll diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj b/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj index 95f2292c8..cad2b20a0 100644 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj +++ b/src/Orchard.Web/Modules/Orchard.DevTools/Orchard.DevTools.csproj @@ -73,7 +73,6 @@ - diff --git a/src/Orchard.Web/Modules/Orchard.DevTools/Profiler.cs b/src/Orchard.Web/Modules/Orchard.DevTools/Profiler.cs deleted file mode 100644 index 2f58cc27f..000000000 --- a/src/Orchard.Web/Modules/Orchard.DevTools/Profiler.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Orchard.Environment; - -namespace Orchard.DevTools { - public class Profiler : IOrchardShellEvents { - public void Activated() { - HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize(); - } - - public void Terminating() { - - } - } -} diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs b/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs index 3b89d2121..f651f689e 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs @@ -8,8 +8,8 @@ using Orchard.Core.Navigation.Models; using Orchard.Core.Settings.Models; using Orchard.Data; using Orchard.Environment; -using Orchard.Environment.Configuration; using Orchard.Environment.Extensions; +using Orchard.Environment.FileSystems; using Orchard.Environment.ShellBuilders; using Orchard.Environment.Topology; using Orchard.Environment.Topology.Models; diff --git a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs index e7e9effb2..7bc7ef29a 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AccountController.cs @@ -57,7 +57,7 @@ namespace Orchard.Users.Controllers { [HttpPost] [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", Justification = "Needs to take same parameter type as Controller.Redirect()")] - public ActionResult LogOn(string userNameOrEmail, string password, bool rememberMe) { + public ActionResult LogOn(string userNameOrEmail, string password, bool rememberMe, string returnUrl) { var user = ValidateLogOn(userNameOrEmail, password); if (!ModelState.IsValid) { return View("LogOn", new LogOnViewModel {Title = "Log On"}); @@ -65,13 +65,19 @@ namespace Orchard.Users.Controllers { _authenticationService.SignIn(user, rememberMe); - return this.ReturnUrlRedirect(); + if (string.IsNullOrEmpty(returnUrl)) + return new RedirectResult("~/"); + + return new RedirectResult(returnUrl); } - public ActionResult LogOff() { + public ActionResult LogOff(string returnUrl) { _authenticationService.SignOut(); - return this.ReturnUrlRedirect(); + if (string.IsNullOrEmpty(returnUrl)) + return new RedirectResult("~/"); + + return new RedirectResult(returnUrl); } int MinPasswordLength { diff --git a/src/Orchard.Web/Orchard.Web.csproj b/src/Orchard.Web/Orchard.Web.csproj index 5f74ca391..30c78ce44 100644 --- a/src/Orchard.Web/Orchard.Web.csproj +++ b/src/Orchard.Web/Orchard.Web.csproj @@ -393,7 +393,7 @@ False False - 30320 + 80 / diff --git a/src/Orchard/Caching/AcquireContext.cs b/src/Orchard/Caching/AcquireContext.cs index 8af2a750c..5c6cc5404 100644 --- a/src/Orchard/Caching/AcquireContext.cs +++ b/src/Orchard/Caching/AcquireContext.cs @@ -1,4 +1,14 @@ -namespace Orchard.Caching { - public class AcquireContext { +using System; +using Orchard.Caching.Providers; + +namespace Orchard.Caching { + public class AcquireContext { + public AcquireContext(TKey key, Action monitor) { + Key = key; + IsInvalid = monitor; + } + + public TKey Key { get; private set; } + public Action IsInvalid { get; private set; } } } diff --git a/src/Orchard/Caching/Cache.cs b/src/Orchard/Caching/Cache.cs index 4f8dc73ab..ea0bfcf32 100644 --- a/src/Orchard/Caching/Cache.cs +++ b/src/Orchard/Caching/Cache.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Orchard.Caching.Providers; namespace Orchard.Caching { public class Cache : ICache { @@ -9,22 +10,21 @@ namespace Orchard.Caching { _entries = new Dictionary(); } - #region Implementation of ICache - - public TResult Get(TKey key, Func acquire) { + public TResult Get(TKey key, Func, TResult> acquire) { CacheEntry entry; if (!_entries.TryGetValue(key, out entry)) { - AcquireContext context = new AcquireContext(); - entry = new CacheEntry {Result = acquire(context)}; + entry = new CacheEntry { VolatileItems = new List() }; + + var context = new AcquireContext(key, volatileItem => entry.VolatileItems.Add(volatileItem)); + entry.Result = acquire(context); _entries.Add(key, entry); } return entry.Result; } - #endregion - - public class CacheEntry { + private class CacheEntry { public TResult Result { get; set; } + public IList VolatileItems { get; set; } } } diff --git a/src/Orchard/Caching/DefaultCacheManager.cs b/src/Orchard/Caching/DefaultCacheManager.cs index 1535bf852..8bfc60c89 100644 --- a/src/Orchard/Caching/DefaultCacheManager.cs +++ b/src/Orchard/Caching/DefaultCacheManager.cs @@ -12,7 +12,7 @@ namespace Orchard.Caching { #region Implementation of ICacheManager - public TResult Get(TKey key, Func acquire) { + public TResult Get(TKey key, Func, TResult> acquire) { return GetCache().Get(key, acquire); } diff --git a/src/Orchard/Caching/ICache.cs b/src/Orchard/Caching/ICache.cs index 98eff848c..691484d95 100644 --- a/src/Orchard/Caching/ICache.cs +++ b/src/Orchard/Caching/ICache.cs @@ -2,6 +2,6 @@ namespace Orchard.Caching { public interface ICache { - TResult Get(TKey key, Func acquire); + TResult Get(TKey key, Func, TResult> acquire); } } diff --git a/src/Orchard/Caching/ICacheManager.cs b/src/Orchard/Caching/ICacheManager.cs index 29d643d9e..5e39a46c3 100644 --- a/src/Orchard/Caching/ICacheManager.cs +++ b/src/Orchard/Caching/ICacheManager.cs @@ -2,7 +2,7 @@ namespace Orchard.Caching { public interface ICacheManager : ISingletonDependency { - TResult Get(TKey key, Func acquire); + TResult Get(TKey key, Func, TResult> acquire); ICache GetCache(); } } diff --git a/src/Orchard/Caching/Providers/IVolatileProvider.cs b/src/Orchard/Caching/Providers/IVolatileProvider.cs new file mode 100644 index 000000000..d2c79deeb --- /dev/null +++ b/src/Orchard/Caching/Providers/IVolatileProvider.cs @@ -0,0 +1,5 @@ +namespace Orchard.Caching.Providers { + public interface IVolatileProvider : IDependency { + void Enlist(IVolatileSink sink); + } +} diff --git a/src/Orchard/Caching/Providers/IVolatileSignal.cs b/src/Orchard/Caching/Providers/IVolatileSignal.cs new file mode 100644 index 000000000..68ded43ea --- /dev/null +++ b/src/Orchard/Caching/Providers/IVolatileSignal.cs @@ -0,0 +1,5 @@ +namespace Orchard.Caching.Providers { + public interface IVolatileSignal { + IVolatileProvider Provider { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard/Caching/Providers/IVolatileSink.cs b/src/Orchard/Caching/Providers/IVolatileSink.cs new file mode 100644 index 000000000..8104fe4d9 --- /dev/null +++ b/src/Orchard/Caching/Providers/IVolatileSink.cs @@ -0,0 +1,5 @@ +namespace Orchard.Caching.Providers { + public interface IVolatileSink { + + } +} \ No newline at end of file diff --git a/src/Orchard/Data/SessionFactoryHolder.cs b/src/Orchard/Data/SessionFactoryHolder.cs index e072559c2..cfbe60c30 100644 --- a/src/Orchard/Data/SessionFactoryHolder.cs +++ b/src/Orchard/Data/SessionFactoryHolder.cs @@ -3,6 +3,7 @@ using System.IO; using NHibernate; using Orchard.Data.Builders; using Orchard.Environment.Configuration; +using Orchard.Environment.FileSystems; using Orchard.Environment.Topology; using Orchard.Environment.Topology.Models; using Orchard.Logging; diff --git a/src/Orchard/Environment/Configuration/ShellSettingsManager.cs b/src/Orchard/Environment/Configuration/ShellSettingsManager.cs index 9604f4855..245138823 100644 --- a/src/Orchard/Environment/Configuration/ShellSettingsManager.cs +++ b/src/Orchard/Environment/Configuration/ShellSettingsManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Yaml.Serialization; +using Orchard.Environment.FileSystems; using Orchard.Localization; namespace Orchard.Environment.Configuration { diff --git a/src/Orchard/Environment/Extensions/ExtensionManager.cs b/src/Orchard/Environment/Extensions/ExtensionManager.cs index 99821ae0a..8f8737b09 100644 --- a/src/Orchard/Environment/Extensions/ExtensionManager.cs +++ b/src/Orchard/Environment/Extensions/ExtensionManager.cs @@ -34,13 +34,7 @@ namespace Orchard.Environment.Extensions { // This method does not load extension types, simply parses extension manifests from // the filesystem. public IEnumerable AvailableExtensions() { - var availableExtensions = new List(); - foreach (var folder in _folders) { - foreach (var name in folder.ListNames()) { - availableExtensions.Add(GetDescriptorForExtension(name, folder)); - } - } - return availableExtensions; + return _folders.SelectMany(folder=>folder.AvailableExtensions()); } public IEnumerable LoadFeatures(IEnumerable featureDescriptors) { @@ -57,65 +51,6 @@ namespace Orchard.Environment.Extensions { return _activeExtensions; } - - private static ExtensionDescriptor GetDescriptorForExtension(string name, IExtensionFolders folder) { - string extensionType = folder is ThemeFolders ? "Theme" : "Module"; - var parseResult = folder.ParseManifest(name); - var mapping = (Mapping)parseResult.YamlDocument.Root; - var fields = mapping.Entities - .Where(x => x.Key is Scalar) - .ToDictionary(x => ((Scalar)x.Key).Text, x => x.Value); - - var extensionDescriptor = new ExtensionDescriptor { - Location = parseResult.Location, - Name = name, - ExtensionType = extensionType, - DisplayName = GetValue(fields, "name") ?? name, - Description = GetValue(fields, "description"), - Version = GetValue(fields, "version"), - OrchardVersion = GetValue(fields, "orchardversion"), - Author = GetValue(fields, "author"), - WebSite = GetValue(fields, "website"), - Tags = GetValue(fields, "tags"), - AntiForgery = GetValue(fields, "antiforgery"), - }; - extensionDescriptor.Features = GetFeaturesForExtension(GetMapping(fields, "features"), extensionDescriptor); - return extensionDescriptor; - } - - private static IEnumerable GetFeaturesForExtension(Mapping features, ExtensionDescriptor extensionDescriptor) { - List featureDescriptors = new List(); - if (features != null) { - foreach (var entity in features.Entities) { - FeatureDescriptor featureDescriptor = new FeatureDescriptor { - Extension = extensionDescriptor, - Name = entity.Key.ToString(), - }; - Mapping featureMapping = (Mapping)entity.Value; - foreach (var featureEntity in featureMapping.Entities) { - if (String.Equals(featureEntity.Key.ToString(), "description", StringComparison.OrdinalIgnoreCase)) { - featureDescriptor.Description = featureEntity.Value.ToString(); - } - else if (String.Equals(featureEntity.Key.ToString(), "category", StringComparison.OrdinalIgnoreCase)) { - featureDescriptor.Category = featureEntity.Value.ToString(); - } - else if (String.Equals(featureEntity.Key.ToString(), "dependencies", StringComparison.OrdinalIgnoreCase)) { - featureDescriptor.Dependencies = ParseFeatureDependenciesEntry(featureEntity.Value.ToString()); - } - } - featureDescriptors.Add(featureDescriptor); - } - } - if (!featureDescriptors.Any(fd => fd.Name == extensionDescriptor.Name)) { - featureDescriptors.Add(new FeatureDescriptor { - Name = extensionDescriptor.Name, - Dependencies = new string[0], - Extension = extensionDescriptor, - }); - } - return featureDescriptors; - } - private Feature LoadFeature(FeatureDescriptor featureDescriptor) { var featureName = featureDescriptor.Name; string extensionName = GetExtensionForFeature(featureName); @@ -237,28 +172,5 @@ namespace Orchard.Environment.Extensions { return null; } - private static string[] ParseFeatureDependenciesEntry(string dependenciesEntry) { - List dependencies = new List(); - foreach (var s in dependenciesEntry.Split(',')) { - dependencies.Add(s.Trim()); - } - return dependencies.ToArray(); - } - - private static Mapping GetMapping( - IDictionary fields, - string key) { - - DataItem value; - return fields.TryGetValue(key, out value) ? (Mapping)value : null; - } - - private static string GetValue( - IDictionary fields, - string key) { - - DataItem value; - return fields.TryGetValue(key, out value) ? value.ToString() : null; - } } } \ No newline at end of file diff --git a/src/Orchard/Environment/Extensions/Folders/AreaFolders.cs b/src/Orchard/Environment/Extensions/Folders/AreaFolders.cs index eb9a17fc0..58b1bd7d7 100644 --- a/src/Orchard/Environment/Extensions/Folders/AreaFolders.cs +++ b/src/Orchard/Environment/Extensions/Folders/AreaFolders.cs @@ -1,9 +1,11 @@ using System.Collections.Generic; +using Orchard.Caching; +using Orchard.Environment.FileSystems; namespace Orchard.Environment.Extensions.Folders { public class AreaFolders : ExtensionFolders { - public AreaFolders(IEnumerable paths) : - base(paths, "Module.txt", true/*isManifestOptional*/) { + public AreaFolders(IEnumerable paths, ICacheManager cacheManager, IVirtualPathProvider virtualPathProvider) : + base(paths, "Module.txt", true/*isManifestOptional*/, cacheManager, virtualPathProvider) { } } } \ No newline at end of file diff --git a/src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs b/src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs index 86ed67d61..ea9a4ff15 100644 --- a/src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs +++ b/src/Orchard/Environment/Extensions/Folders/ExtensionFolders.cs @@ -1,19 +1,67 @@ +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.Environment.FileSystems; using Yaml.Grammar; namespace Orchard.Environment.Extensions.Folders { + public class ParseResult { + public string Location { get; set; } + public string Name { get; set; } + public YamlDocument YamlDocument { get; set; } + } + public class ExtensionFolders : IExtensionFolders { private readonly IEnumerable _paths; private readonly string _manifestName; + private readonly string _extensionType; private readonly bool _manifestIsOptional; + private readonly ICacheManager _cacheManager; + private readonly IVirtualPathProvider _virtualPathProvider; - public ExtensionFolders(IEnumerable paths, string manifestName, bool manifestIsOptional) { + public ExtensionFolders( + IEnumerable paths, + string manifestName, + bool manifestIsOptional, + ICacheManager cacheManager, + IVirtualPathProvider virtualPathProvider) { _paths = paths; _manifestName = manifestName; + _extensionType = manifestName == "Theme.txt" ? "Theme" : "Module"; _manifestIsOptional = manifestIsOptional; + _cacheManager = cacheManager; + _virtualPathProvider = virtualPathProvider; + } + + public IEnumerable AvailableExtensions() { + var virtualPaths = _cacheManager.Get("", ctx => { + var x = 5; + return new[] { "hello" }; + }); + + + var list = new List(); + foreach (var virtualPath in virtualPaths) { + list.Add(GetExtensionDescriptor(virtualPath)); + } + return list; + } + + ExtensionDescriptor GetExtensionDescriptor(string virtualPath) { + return _cacheManager.Get(virtualPath, context => { + + context.IsInvalid(_virtualPathProvider.WhenPathChanges(virtualPath)); + + var text = _virtualPathProvider.ReadAllText(virtualPath); + + var parseResult = ParseManifest(text); + return GetDescriptorForExtension(parseResult.Name, parseResult); + }); } public IEnumerable ListNames() { @@ -43,10 +91,10 @@ namespace Orchard.Environment.Extensions.Folders { if (File.Exists(extensionManifestPath)) { var yamlStream = YamlParser.Load(extensionManifestPath); return new ParseResult { - Location = path, - Name = name, - YamlDocument = yamlStream.Documents.Single() - }; + Location = path, + Name = name, + YamlDocument = yamlStream.Documents.Single() + }; } if (_manifestIsOptional) { @@ -55,13 +103,94 @@ namespace Orchard.Environment.Extensions.Folders { bool success; var yamlStream = parser.ParseYamlStream(yamlInput, out success); return new ParseResult { - Location = path, - Name = name, - YamlDocument = yamlStream.Documents.Single() - }; + Location = path, + Name = name, + YamlDocument = yamlStream.Documents.Single() + }; } } return null; } + + + private ExtensionDescriptor GetDescriptorForExtension(string name, ParseResult parseResult) { + var mapping = (Mapping)parseResult.YamlDocument.Root; + var fields = mapping.Entities + .Where(x => x.Key is Scalar) + .ToDictionary(x => ((Scalar)x.Key).Text, x => x.Value); + + var extensionDescriptor = new ExtensionDescriptor { + Location = parseResult.Location, + Name = name, + ExtensionType = _extensionType, + DisplayName = GetValue(fields, "name") ?? name, + Description = GetValue(fields, "description"), + Version = GetValue(fields, "version"), + OrchardVersion = GetValue(fields, "orchardversion"), + Author = GetValue(fields, "author"), + WebSite = GetValue(fields, "website"), + Tags = GetValue(fields, "tags"), + AntiForgery = GetValue(fields, "antiforgery"), + }; + extensionDescriptor.Features = GetFeaturesForExtension(GetMapping(fields, "features"), extensionDescriptor); + return extensionDescriptor; + } + + private static IEnumerable GetFeaturesForExtension(Mapping features, ExtensionDescriptor extensionDescriptor) { + List featureDescriptors = new List(); + if (features != null) { + foreach (var entity in features.Entities) { + FeatureDescriptor featureDescriptor = new FeatureDescriptor { + Extension = extensionDescriptor, + Name = entity.Key.ToString(), + }; + Mapping featureMapping = (Mapping)entity.Value; + foreach (var featureEntity in featureMapping.Entities) { + if (String.Equals(featureEntity.Key.ToString(), "description", StringComparison.OrdinalIgnoreCase)) { + featureDescriptor.Description = featureEntity.Value.ToString(); + } + else if (String.Equals(featureEntity.Key.ToString(), "category", StringComparison.OrdinalIgnoreCase)) { + featureDescriptor.Category = featureEntity.Value.ToString(); + } + else if (String.Equals(featureEntity.Key.ToString(), "dependencies", StringComparison.OrdinalIgnoreCase)) { + featureDescriptor.Dependencies = ParseFeatureDependenciesEntry(featureEntity.Value.ToString()); + } + } + featureDescriptors.Add(featureDescriptor); + } + } + if (!featureDescriptors.Any(fd => fd.Name == extensionDescriptor.Name)) { + featureDescriptors.Add(new FeatureDescriptor { + Name = extensionDescriptor.Name, + Dependencies = new string[0], + Extension = extensionDescriptor, + }); + } + return featureDescriptors; + } + + private static string[] ParseFeatureDependenciesEntry(string dependenciesEntry) { + List dependencies = new List(); + foreach (var s in dependenciesEntry.Split(',')) { + dependencies.Add(s.Trim()); + } + return dependencies.ToArray(); + } + + private static Mapping GetMapping( + IDictionary fields, + string key) { + + DataItem value; + return fields.TryGetValue(key, out value) ? (Mapping)value : null; + } + + private static string GetValue( + IDictionary fields, + string key) { + + DataItem value; + return fields.TryGetValue(key, out value) ? value.ToString() : null; + } } } \ No newline at end of file diff --git a/src/Orchard/Environment/Extensions/Folders/IExtensionFolders.cs b/src/Orchard/Environment/Extensions/Folders/IExtensionFolders.cs index eb57ccf24..527a3a024 100644 --- a/src/Orchard/Environment/Extensions/Folders/IExtensionFolders.cs +++ b/src/Orchard/Environment/Extensions/Folders/IExtensionFolders.cs @@ -1,15 +1,11 @@ using System.Collections.Generic; +using Orchard.Environment.Extensions.Models; using Yaml.Grammar; namespace Orchard.Environment.Extensions.Folders { public interface IExtensionFolders { - IEnumerable ListNames(); - ParseResult ParseManifest(string name); + IEnumerable AvailableExtensions(); } - public class ParseResult { - public string Location { get; set; } - public string Name { get; set; } - public YamlDocument YamlDocument { get; set; } - } + } \ No newline at end of file diff --git a/src/Orchard/Environment/Extensions/Folders/ModuleFolders.cs b/src/Orchard/Environment/Extensions/Folders/ModuleFolders.cs index 1e256a4e0..82f065982 100644 --- a/src/Orchard/Environment/Extensions/Folders/ModuleFolders.cs +++ b/src/Orchard/Environment/Extensions/Folders/ModuleFolders.cs @@ -1,9 +1,11 @@ using System.Collections.Generic; +using Orchard.Caching; +using Orchard.Environment.FileSystems; namespace Orchard.Environment.Extensions.Folders { public class ModuleFolders : ExtensionFolders { - public ModuleFolders(IEnumerable paths) : - base(paths, "Module.txt", false/*isManifestOptional*/) { + public ModuleFolders(IEnumerable paths, ICacheManager cacheManager, IVirtualPathProvider virtualPathProvider) : + base(paths, "Module.txt", false/*isManifestOptional*/, cacheManager, virtualPathProvider) { } } } \ No newline at end of file diff --git a/src/Orchard/Environment/Extensions/Folders/ThemeFolders.cs b/src/Orchard/Environment/Extensions/Folders/ThemeFolders.cs index 08253d384..9ebc50e3a 100644 --- a/src/Orchard/Environment/Extensions/Folders/ThemeFolders.cs +++ b/src/Orchard/Environment/Extensions/Folders/ThemeFolders.cs @@ -1,9 +1,11 @@ using System.Collections.Generic; +using Orchard.Caching; +using Orchard.Environment.FileSystems; namespace Orchard.Environment.Extensions.Folders { public class ThemeFolders : ExtensionFolders { - public ThemeFolders(IEnumerable paths) : - base(paths, "Theme.txt", false/*manifestIsOptional*/) { + public ThemeFolders(IEnumerable paths, ICacheManager cacheManager, IVirtualPathProvider virtualPathProvider) : + base(paths, "Theme.txt", false/*manifestIsOptional*/, cacheManager, virtualPathProvider) { } } } \ No newline at end of file diff --git a/src/Orchard/Environment/Configuration/AppDataFolder.cs b/src/Orchard/Environment/FileSystems/AppDataFolder.cs similarity index 73% rename from src/Orchard/Environment/Configuration/AppDataFolder.cs rename to src/Orchard/Environment/FileSystems/AppDataFolder.cs index 050ef0b71..a28c71906 100644 --- a/src/Orchard/Environment/Configuration/AppDataFolder.cs +++ b/src/Orchard/Environment/FileSystems/AppDataFolder.cs @@ -3,33 +3,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Web.Hosting; +using Orchard.Environment.FileSystems; namespace Orchard.Environment.Configuration { - /// - /// Abstraction of App_Data folder - /// Expected to work on physical filesystem, but decouples core - /// system from web hosting apis - /// - public interface IAppDataFolder { - IEnumerable ListFiles(string path); - IEnumerable ListDirectories(string path); - - void CreateFile(string path, string content); - string ReadFile(string path); - void DeleteFile(string path); - bool FileExists(string path); - - string CreateDirectory(string path); - - - /// - /// May be called to initialize component when not in a hosting environment - /// app domain - /// - void SetBasePath(string basePath); - string MapPath(string path); - } - public class AppDataFolder : IAppDataFolder { protected string _basePath; diff --git a/src/Orchard/Environment/FileSystems/DefaultVirtualPathProvider.cs b/src/Orchard/Environment/FileSystems/DefaultVirtualPathProvider.cs new file mode 100644 index 000000000..733c335e6 --- /dev/null +++ b/src/Orchard/Environment/FileSystems/DefaultVirtualPathProvider.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Web.Hosting; +using Orchard.Caching.Providers; +using Orchard.Services; + +namespace Orchard.Environment.FileSystems { + public class DefaultVirtualPathProvider : IVirtualPathProvider { + private readonly IClock _clock; + private readonly IList _sinks = new List(); + //private string _cachePrefix = Guid.NewGuid().ToString("n"); + + public DefaultVirtualPathProvider(IClock clock) { + _clock = clock; + } + + public string ReadAllText(string virtualPath) { + using (var stream = VirtualPathProvider.OpenFile(virtualPath)) { + using (var reader = new StreamReader(stream)) { + return reader.ReadToEnd(); + } + } + //var cd = HostingEnvironment.VirtualPathProvider.. .GetCacheDependency(virtualPath, null, _clock.UtcNow); + //HostingEnvironment.Cache.Add( + // _cachePrefix + virtualPath, + // virtualPath, + // cd, + // NoAbsoluteExpiration, + // ); + } + + public IVolatileSignal WhenPathChanges(string virtualPath) { + + return new VirtualPathSignal(this, virtualPath); + } + + + class VirtualPathSignal : IVolatileSignal { + private readonly string _virtualPath; + + public VirtualPathSignal(DefaultVirtualPathProvider provider, string virtualPath) { + _virtualPath = virtualPath; + Provider = provider; + } + + public IVolatileProvider Provider { get; set; } + } + + public void Enlist(IVolatileSink sink) { + _sinks.Add(sink); + } + } +} \ No newline at end of file diff --git a/src/Orchard/Environment/FileSystems/IAppDataFolder.cs b/src/Orchard/Environment/FileSystems/IAppDataFolder.cs new file mode 100644 index 000000000..59b16bc58 --- /dev/null +++ b/src/Orchard/Environment/FileSystems/IAppDataFolder.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace Orchard.Environment.FileSystems { + /// + /// Abstraction of App_Data folder + /// Expected to work on physical filesystem, but decouples core + /// system from web hosting apis + /// + public interface IAppDataFolder { + IEnumerable ListFiles(string path); + IEnumerable ListDirectories(string path); + + void CreateFile(string path, string content); + string ReadFile(string path); + void DeleteFile(string path); + bool FileExists(string path); + + string CreateDirectory(string path); + + + /// + /// May be called to initialize component when not in a hosting environment + /// app domain + /// + void SetBasePath(string basePath); + string MapPath(string path); + } +} \ No newline at end of file diff --git a/src/Orchard/Environment/FileSystems/IVirtualPathProvider.cs b/src/Orchard/Environment/FileSystems/IVirtualPathProvider.cs new file mode 100644 index 000000000..7efa1ed44 --- /dev/null +++ b/src/Orchard/Environment/FileSystems/IVirtualPathProvider.cs @@ -0,0 +1,9 @@ +using Orchard.Caching.Providers; + +namespace Orchard.Environment.FileSystems { + public interface IVirtualPathProvider : IVolatileProvider { + IVolatileSignal WhenPathChanges(string path); + + string ReadAllText(string virtualPath); + } +} \ No newline at end of file diff --git a/src/Orchard/Environment/OrchardStarter.cs b/src/Orchard/Environment/OrchardStarter.cs index 5d959d057..0734a66af 100644 --- a/src/Orchard/Environment/OrchardStarter.cs +++ b/src/Orchard/Environment/OrchardStarter.cs @@ -10,6 +10,7 @@ using Orchard.Environment.Configuration; using Orchard.Environment.Extensions; using Orchard.Environment.Extensions.Folders; using Orchard.Environment.Extensions.Loaders; +using Orchard.Environment.FileSystems; using Orchard.Environment.ShellBuilders; using Orchard.Environment.Topology; using Orchard.Events; diff --git a/src/Orchard/Environment/ShellBuilders/ShellContainerFactory.cs b/src/Orchard/Environment/ShellBuilders/ShellContainerFactory.cs index 67eac9c64..bf20ac080 100644 --- a/src/Orchard/Environment/ShellBuilders/ShellContainerFactory.cs +++ b/src/Orchard/Environment/ShellBuilders/ShellContainerFactory.cs @@ -106,7 +106,8 @@ namespace Orchard.Environment.ShellBuilders { private IRegistrationBuilder RegisterType(ContainerBuilder builder, ShellTopologyItem item) { return builder.RegisterType(item.Type) - .WithProperty("Feature", item.Feature); + .WithProperty("Feature", item.Feature) + .WithMetadata("Feature", item.Feature); } } } diff --git a/src/Orchard/Environment/Topology/ShellDescriptorCache.cs b/src/Orchard/Environment/Topology/ShellDescriptorCache.cs index 8d2fa07b4..3daf77a8d 100644 --- a/src/Orchard/Environment/Topology/ShellDescriptorCache.cs +++ b/src/Orchard/Environment/Topology/ShellDescriptorCache.cs @@ -2,7 +2,7 @@ using System.IO; using System.Runtime.Serialization; using System.Xml; -using Orchard.Environment.Configuration; +using Orchard.Environment.FileSystems; using Orchard.Environment.Topology.Models; using Orchard.Localization; using Orchard.Logging; diff --git a/src/Orchard/Mvc/Extensions/ControllerExtensions.cs b/src/Orchard/Mvc/Extensions/ControllerExtensions.cs deleted file mode 100644 index 84a3bd106..000000000 --- a/src/Orchard/Mvc/Extensions/ControllerExtensions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Web.Mvc; - -namespace Orchard.Mvc.Extensions { - public static class ControllerExtensions { - public static RedirectResult ReturnUrlRedirect(this Controller controller) { - string returnUrl = controller.Request.QueryString["ReturnUrl"]; - - // prevents phishing attacks by using only relative urls - if(!returnUrl.StartsWith("/")) { - return new RedirectResult("~/"); - } - - return new RedirectResult(returnUrl); - } - } -} diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index f5378536f..e1d257527 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -63,6 +63,18 @@ False ..\..\lib\sharpziplib\ICSharpCode.SharpZipLib.dll + + False + ..\..\lib\machine.migrations\Machine.Core.dll + + + False + ..\..\lib\machine.migrations\Machine.Migrations.dll + + + False + ..\..\lib\machine.migrations\Machine.Migrations.NHibernate.dll + False ..\..\lib\fluentnhibernate\NHibernate.dll @@ -134,8 +146,14 @@ + + + + + + @@ -173,7 +191,7 @@ - + @@ -204,7 +222,6 @@ -