Merge with 1.x

This commit is contained in:
Sebastien Ros 2012-10-26 19:00:13 -07:00
commit 395029fdbd
41 changed files with 156 additions and 414 deletions

View File

@ -84,7 +84,7 @@
<ItemGroup> <ItemGroup>
<!-- filter to exclude any binary from a folder --> <!-- filter to exclude any binary from a folder -->
<Excluded Include="$(SrcFolder)\**\bin\**\*;$(SrcFolder)\**\obj\**\*;$(SrcFolder)\**\*.user; $(SrcFolder)\**\*.cs;$(SrcFolder)\**\*.csproj" /> <Excluded Include="$(SrcFolder)\**\bin\**\*;$(SrcFolder)\**\obj\**\*;$(SrcFolder)\**\*.user; $(SrcFolder)\**\*.cs;$(SrcFolder)\**\*.csproj;$(SrcFolder)\**\.hg\**\*" />
<!-- list of files from Themes, Core and Modules to export --> <!-- list of files from Themes, Core and Modules to export -->
<Stage-Themes Include="$(SrcFolder)\Orchard.Web\Themes\**\*" Exclude="@(Excluded)" /> <Stage-Themes Include="$(SrcFolder)\Orchard.Web\Themes\**\*" Exclude="@(Excluded)" />

View File

@ -1,5 +1,5 @@
REM Check if this task is running on the compute emulator, if not then sets the Idle Timeout to zero REM Check if this task is running on the compute emulator, if not then sets the Idle Timeout to zero
IF "%ComputeEmulatorRunning%" == "true" ( IF "%ComputeEmulatorRunning%" == "false" (
%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00 %windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00
) )

View File

@ -190,5 +190,17 @@ namespace Orchard.Tests.Data {
Assert.That(one.Name, Is.EqualTo("one")); Assert.That(one.Name, Is.EqualTo("one"));
Assert.That(one.Timespan.Value.Millisecond, Is.EqualTo(489)); Assert.That(one.Timespan.Value.Millisecond, Is.EqualTo(489));
} }
[Test]
public void RepositoryFetchTakesExistsPredicate() {
CreateThreeFoos();
var array = new[] { "one", "two" };
var result = _fooRepos.Fetch(f => array.Contains(f.Name)).ToList();
Assert.That(result.Count(), Is.EqualTo(2));
}
} }
} }

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<HostComponents> <HostComponents>
<Components> <Components>
<Component Type="Orchard.Environment.Extensions.Loaders.DynamicExtensionLoader"> <Component Type="Orchard.Environment.Extensions.ExtensionMonitoringCoordinator">
<Properties> <Properties>
<Property Name="Disabled" Value="true"/> <Property Name="Disabled" Value="true"/>
</Properties> </Properties>

View File

@ -2,8 +2,8 @@
AntiForgery: enabled AntiForgery: enabled
Author: The Orchard Team Author: The Orchard Team
Website: http://orchardproject.net Website: http://orchardproject.net
Version: 1.5.1 Version: 1.6
OrchardVersion: 1.5.1 OrchardVersion: 1.6
Description: The common module introduces content parts that are going to be used by most content types (common, body, identity). Description: The common module introduces content parts that are going to be used by most content types (common, body, identity).
FeatureDescription: Core content parts. FeatureDescription: Core content parts.
Dependencies: Settings Dependencies: Settings

View File

@ -2,8 +2,8 @@
AntiForgery: enabled AntiForgery: enabled
Author: The Orchard Team Author: The Orchard Team
Website: http://orchardproject.net Website: http://orchardproject.net
Version: 1.5.1 Version: 1.6
OrchardVersion: 1.5.1 OrchardVersion: 1.6
Description: The containers module introduces container and containable behaviors for content items. Description: The containers module introduces container and containable behaviors for content items.
FeatureDescription: Container and containable parts to enable parent-child relationships between content items. FeatureDescription: Container and containable parts to enable parent-child relationships between content items.
Dependencies: Contents, Feeds Dependencies: Contents, Feeds

View File

@ -2,8 +2,8 @@
AntiForgery: enabled AntiForgery: enabled
Author: The Orchard Team Author: The Orchard Team
Website: http://orchardproject.net Website: http://orchardproject.net
Version: 1.5.1 Version: 1.6
OrchardVersion: 1.5.1 OrchardVersion: 1.6
Description: The contents module enables the creation of custom content types. Description: The contents module enables the creation of custom content types.
Features: Features:
Contents Contents

View File

@ -2,8 +2,8 @@
AntiForgery: enabled AntiForgery: enabled
Author: The Orchard Team Author: The Orchard Team
Website: http://orchardproject.net Website: http://orchardproject.net
Version: 1.5.1 Version: 1.6
OrchardVersion: 1.5.1 OrchardVersion: 1.6
Description: The dashboard module is providing the dashboard screen of the admininstration UI of the application. Description: The dashboard module is providing the dashboard screen of the admininstration UI of the application.
FeatureDescription: Standard admin dashboard. FeatureDescription: Standard admin dashboard.
Category: Core Category: Core

View File

@ -2,8 +2,8 @@
AntiForgery: enabled AntiForgery: enabled
Author: The Orchard Team Author: The Orchard Team
Website: http://orchardproject.net Website: http://orchardproject.net
Version: 1.5.1 Version: 1.6
OrchardVersion: 1.5.1 OrchardVersion: 1.6
Description: The Feeds module is providing RSS feeds to content items. Description: The Feeds module is providing RSS feeds to content items.
FeatureDescription: RSS feeds for content items. FeatureDescription: RSS feeds for content items.
Category: Syndication Category: Syndication

View File

@ -27,6 +27,12 @@ namespace Orchard.Core.Navigation.Handlers {
var contentMenuItemPart = context.ContentItem.As<ContentMenuItemPart>(); var contentMenuItemPart = context.ContentItem.As<ContentMenuItemPart>();
// the display route for the menu item is the one for the referenced content item // the display route for the menu item is the one for the referenced content item
if(contentMenuItemPart != null) { if(contentMenuItemPart != null) {
// if the content doesn't exist anymore
if(contentMenuItemPart.Content == null) {
return;
}
context.Metadata.DisplayRouteValues = _contentManager.GetItemMetadata(contentMenuItemPart.Content).DisplayRouteValues; context.Metadata.DisplayRouteValues = _contentManager.GetItemMetadata(contentMenuItemPart.Content).DisplayRouteValues;
} }
} }

View File

@ -2,8 +2,8 @@
AntiForgery: enabled AntiForgery: enabled
Author: The Orchard Team Author: The Orchard Team
Website: http://orchardproject.net Website: http://orchardproject.net
Version: 1.5.1 Version: 1.6
OrchardVersion: 1.5.1 OrchardVersion: 1.6
Description: The navigation module creates and manages a simple navigation menu for the front-end of the application and allows you to add content items to the admin menu. Description: The navigation module creates and manages a simple navigation menu for the front-end of the application and allows you to add content items to the admin menu.
FeatureDescription: Menu management. FeatureDescription: Menu management.
Category: Core Category: Core

View File

@ -2,8 +2,8 @@
AntiForgery: enabled AntiForgery: enabled
Author: The Orchard Team Author: The Orchard Team
Website: http://orchardproject.net Website: http://orchardproject.net
Version: 1.5.1 Version: 1.6
OrchardVersion: 1.5.1 OrchardVersion: 1.6
Description: The dashboard module is providing the reports screen of the application. Description: The dashboard module is providing the reports screen of the application.
FeatureDescription: Reports management. FeatureDescription: Reports management.
Category: Core Category: Core

View File

@ -2,8 +2,8 @@
AntiForgery: enabled AntiForgery: enabled
Author: The Orchard Team Author: The Orchard Team
Website: http://orchardproject.net Website: http://orchardproject.net
Version: 1.5.1 Version: 1.6
OrchardVersion: 1.5.1 OrchardVersion: 1.6
Description: The scheduling module enables background task scheduling. Description: The scheduling module enables background task scheduling.
FeatureDescription: Scheduled background tasks. FeatureDescription: Scheduled background tasks.
Category: Core Category: Core

View File

@ -2,8 +2,8 @@
AntiForgery: enabled AntiForgery: enabled
Author: The Orchard Team Author: The Orchard Team
Website: http://orchardproject.net Website: http://orchardproject.net
Version: 1.5.1 Version: 1.6
OrchardVersion: 1.5.1 OrchardVersion: 1.6
Description: The settings module creates site settings that other modules can contribute to. Description: The settings module creates site settings that other modules can contribute to.
FeatureDescription: Site settings. FeatureDescription: Site settings.
Category: Core Category: Core

View File

@ -2,8 +2,8 @@
AntiForgery: enabled AntiForgery: enabled
Author: The Orchard Team Author: The Orchard Team
Website: http://orchardproject.net Website: http://orchardproject.net
Version: 1.5.1 Version: 1.6
OrchardVersion: 1.5.1 OrchardVersion: 1.6
Description: The shapes module contains core shape templates and display hooks. Description: The shapes module contains core shape templates and display hooks.
FeatureDescription: Core shape templates and display hooks. FeatureDescription: Core shape templates and display hooks.
Category: Core Category: Core

View File

@ -2,8 +2,8 @@
AntiForgery: enabled AntiForgery: enabled
Author: The Orchard Team Author: The Orchard Team
Website: http://orchardproject.net Website: http://orchardproject.net
Version: 1.5.1 Version: 1.6
OrchardVersion: 1.5.1 OrchardVersion: 1.6
Description: The title module enables content items to have titles. Description: The title module enables content items to have titles.
FeatureDescription: Title content part. FeatureDescription: Title content part.
Category: Core Category: Core

View File

@ -2,8 +2,8 @@
AntiForgery: enabled AntiForgery: enabled
Author: The Orchard Team Author: The Orchard Team
Website: http://orchardproject.net Website: http://orchardproject.net
Version: 1.5.1 Version: 1.6
OrchardVersion: 1.5.1 OrchardVersion: 1.6
Description: The XmlRpc module enables creation of contents from client applications such as LiveWriter. Description: The XmlRpc module enables creation of contents from client applications such as LiveWriter.
FeatureDescription: XML-RPC opt-in implementation. FeatureDescription: XML-RPC opt-in implementation.
Category: Content Publishing Category: Content Publishing

View File

@ -22,7 +22,7 @@ namespace Orchard.Alias.Controllers {
public AdminController( public AdminController(
IAliasService aliasService, IAliasService aliasService,
IOrchardServices orchardServices, IOrchardServices orchardServices,
IAliasHolder aliasHolder ) { IAliasHolder aliasHolder) {
_aliasService = aliasService; _aliasService = aliasService;
_aliasHolder = aliasHolder; _aliasHolder = aliasHolder;
Services = orchardServices; Services = orchardServices;
@ -65,7 +65,7 @@ namespace Orchard.Alias.Controllers {
aliases = aliases.OrderBy(x => x.Path); aliases = aliases.OrderBy(x => x.Path);
break; break;
} }
if (pager.PageSize != 0) { if (pager.PageSize != 0) {
aliases = aliases.Skip(pager.GetStartIndex()).Take(pager.PageSize); aliases = aliases.Skip(pager.GetStartIndex()).Take(pager.PageSize);
} }
@ -73,7 +73,7 @@ namespace Orchard.Alias.Controllers {
var model = new AdminIndexViewModel { var model = new AdminIndexViewModel {
Options = options, Options = options,
Pager = pagerShape, Pager = pagerShape,
AliasEntries = aliases.Select(x => new AliasEntry() {Alias = x, IsChecked = false}).ToList() AliasEntries = aliases.Select(x => new AliasEntry() { Alias = x, IsChecked = false }).ToList()
}; };
return View(model); return View(model);
@ -103,7 +103,7 @@ namespace Orchard.Alias.Controllers {
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
public ActionResult Add() { public ActionResult Add() {
@ -118,7 +118,7 @@ namespace Orchard.Alias.Controllers {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage aliases"))) if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage aliases")))
return new HttpUnauthorizedResult(); return new HttpUnauthorizedResult();
if(aliasPath == "/") { if (aliasPath == "/") {
aliasPath = String.Empty; aliasPath = String.Empty;
} }
@ -130,7 +130,7 @@ namespace Orchard.Alias.Controllers {
ModelState.AddModelError("Route", T("Route can't be empty").Text); ModelState.AddModelError("Route", T("Route can't be empty").Text);
} }
if(!ModelState.IsValid) { if (!ModelState.IsValid) {
return View(); return View();
} }
@ -162,11 +162,11 @@ namespace Orchard.Alias.Controllers {
var routeValues = _aliasService.Get(path); var routeValues = _aliasService.Get(path);
if (routeValues==null) if (routeValues == null)
return HttpNotFound(); return HttpNotFound();
var virtualPaths = _aliasService.LookupVirtualPaths(routeValues,HttpContext) var virtualPaths = _aliasService.LookupVirtualPaths(routeValues, HttpContext)
.Select(vpd=>vpd.VirtualPath); .Select(vpd => vpd.VirtualPath);
ViewBag.AliasPath = path; ViewBag.AliasPath = path;
ViewBag.RoutePath = virtualPaths.FirstOrDefault(); ViewBag.RoutePath = virtualPaths.FirstOrDefault();
@ -181,19 +181,18 @@ namespace Orchard.Alias.Controllers {
// TODO: (PH:Autoroute) This could overwrite an existing Alias without warning, should handle this // TODO: (PH:Autoroute) This could overwrite an existing Alias without warning, should handle this
_aliasService.Set(aliasPath, routePath, "Custom"); _aliasService.Set(aliasPath, routePath, "Custom");
// Remove previous alias // Remove previous alias
if (path != aliasPath) if (path != aliasPath) {
{
// TODO: (PH:Autoroute) Ability to fire an "AliasChanged" event so we make a redirect // TODO: (PH:Autoroute) Ability to fire an "AliasChanged" event so we make a redirect
_aliasService.Delete(path); _aliasService.Delete(path);
} }
Services.Notifier.Information(T("Alias {0} updated", path)); Services.Notifier.Information(T("Alias {0} updated", path));
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
[HttpPost] [HttpPost]
public ActionResult Delete(string path) { public ActionResult Delete(string path) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage aliases"))) if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage aliases")))

View File

@ -2,10 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Web.Routing; using System.Web.Routing;
namespace Orchard.Alias namespace Orchard.Alias {
{ public interface IAliasService : IDependency {
public interface IAliasService : IDependency
{
RouteValueDictionary Get(string aliasPath); RouteValueDictionary Get(string aliasPath);
void Set(string aliasPath, RouteValueDictionary routeValues, string aliasSource); void Set(string aliasPath, RouteValueDictionary routeValues, string aliasSource);
void Set(string aliasPath, string routePath, string aliasSource); void Set(string aliasPath, string routePath, string aliasSource);
@ -24,7 +22,7 @@ namespace Orchard.Alias
void Replace(string aliasPath, string routePath, string aliasSource); void Replace(string aliasPath, string routePath, string aliasSource);
IEnumerable<Tuple<string, RouteValueDictionary>> List(); IEnumerable<Tuple<string, RouteValueDictionary>> List();
IEnumerable<Tuple<string, RouteValueDictionary,string>> List(string sourceStartsWith); IEnumerable<Tuple<string, RouteValueDictionary, string>> List(string sourceStartsWith);
IEnumerable<VirtualPathData> LookupVirtualPaths(RouteValueDictionary routeValues, System.Web.HttpContextBase HttpContext); IEnumerable<VirtualPathData> LookupVirtualPaths(RouteValueDictionary routeValues, System.Web.HttpContextBase HttpContext);
} }

View File

@ -8,34 +8,33 @@ using System.Web.Routing;
using Orchard.Alias.Implementation.Holder; using Orchard.Alias.Implementation.Holder;
using Orchard.Alias.Implementation.Map; using Orchard.Alias.Implementation.Map;
namespace Orchard.Alias.Implementation namespace Orchard.Alias.Implementation {
{ public class AliasRoute : RouteBase, IRouteWithArea {
public class AliasRoute : RouteBase, IRouteWithArea
{
private readonly AliasMap _aliasMap; private readonly AliasMap _aliasMap;
private readonly IRouteHandler _routeHandler; private readonly IRouteHandler _routeHandler;
public AliasRoute(IAliasHolder aliasHolder, string areaName, IRouteHandler routeHandler) public AliasRoute(IAliasHolder aliasHolder, string areaName, IRouteHandler routeHandler) {
{
Area = areaName; Area = areaName;
_aliasMap = aliasHolder.GetMap(areaName); _aliasMap = aliasHolder.GetMap(areaName);
_routeHandler = routeHandler; _routeHandler = routeHandler;
} }
public override RouteData GetRouteData(HttpContextBase httpContext) public override RouteData GetRouteData(HttpContextBase httpContext) {
{ // don't compute unnecessary virtual path if the map is empty
if (!_aliasMap.Any()) {
return null;
}
// Get the full inbound request path // Get the full inbound request path
var virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo; var virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
// Attempt to lookup RouteValues in the alias map // Attempt to lookup RouteValues in the alias map
IDictionary<string, string> routeValues; IDictionary<string, string> routeValues;
// TODO: Might as well have the lookup in AliasHolder... // TODO: Might as well have the lookup in AliasHolder...
if (_aliasMap.TryGetAlias(virtualPath, out routeValues)) if (_aliasMap.TryGetAlias(virtualPath, out routeValues)) {
{
// Construct RouteData from the route values // Construct RouteData from the route values
var data = new RouteData(this, _routeHandler); var data = new RouteData(this, _routeHandler);
foreach (var routeValue in routeValues) foreach (var routeValue in routeValues) {
{
var key = routeValue.Key; var key = routeValue.Key;
if (key.EndsWith("-")) if (key.EndsWith("-"))
data.Values.Add(key.Substring(0, key.Length - 1), routeValue.Value); data.Values.Add(key.Substring(0, key.Length - 1), routeValue.Value);
@ -51,22 +50,19 @@ namespace Orchard.Alias.Implementation
return null; return null;
} }
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary routeValues) public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary routeValues) {
{
// Lookup best match for route values in the expanded tree // Lookup best match for route values in the expanded tree
var match = _aliasMap.Locate(routeValues); var match = _aliasMap.Locate(routeValues);
if (match != null) if (match != null) {
{
// Build any "spare" route values onto the Alias (so we correctly support any additional query parameters) // Build any "spare" route values onto the Alias (so we correctly support any additional query parameters)
var sb = new StringBuilder(match.Item2); var sb = new StringBuilder(match.Item2);
var extra = 0; var extra = 0;
foreach (var routeValue in routeValues) foreach (var routeValue in routeValues) {
{
// Ignore any we already have // Ignore any we already have
if (match.Item1.ContainsKey(routeValue.Key)) if (match.Item1.ContainsKey(routeValue.Key)) {
{
continue; continue;
} }
// Add a query string fragment // Add a query string fragment
sb.Append((extra++ == 0) ? '?' : '&'); sb.Append((extra++ == 0) ? '?' : '&');
sb.Append(Uri.EscapeDataString(routeValue.Key)); sb.Append(Uri.EscapeDataString(routeValue.Key));

View File

@ -25,7 +25,7 @@ namespace Orchard.Alias.Implementation.Holder {
} }
public void SetAlias(AliasInfo alias) { public void SetAlias(AliasInfo alias) {
foreach(var map in _aliasMaps.Values) { foreach (var map in _aliasMaps.Values) {
map.Remove(alias); map.Remove(alias);
} }

View File

@ -53,6 +53,10 @@ namespace Orchard.Alias.Implementation.Map {
CollapseTree(_root, info.Path, info.RouteValues); CollapseTree(_root, info.Path, info.RouteValues);
} }
public bool Any() {
return _aliases.Any();
}
private static void CollapseTree(Node root, string path, IDictionary<string, string> routeValues) { private static void CollapseTree(Node root, string path, IDictionary<string, string> routeValues) {
foreach (var expanded in Expand(routeValues)) { foreach (var expanded in Expand(routeValues)) {
var focus = root; var focus = root;
@ -96,14 +100,6 @@ namespace Orchard.Alias.Implementation.Map {
return from item1 in source1 from item2 in source2 select produce(item1, item2); return from item1 in source1 from item2 in source2 select produce(item1, item2);
} }
private static IEnumerable<T> Single<T>(T t) {
yield return t;
}
private static IEnumerable<T> Empty<T>() {
return Enumerable.Empty<T>();
}
/// <summary> /// <summary>
/// Expand the route values into all possible combinations of keys /// Expand the route values into all possible combinations of keys
/// </summary> /// </summary>
@ -111,7 +107,7 @@ namespace Orchard.Alias.Implementation.Map {
/// <returns></returns> /// <returns></returns>
private static IEnumerable<IEnumerable<KeyValuePair<string, string>>> Expand(IDictionary<string, string> routeValues) { private static IEnumerable<IEnumerable<KeyValuePair<string, string>>> Expand(IDictionary<string, string> routeValues) {
var ordered = routeValues.OrderBy(kv => kv.Key, StringComparer.InvariantCultureIgnoreCase); var ordered = routeValues.OrderBy(kv => kv.Key, StringComparer.InvariantCultureIgnoreCase);
var empty = Empty<KeyValuePair<string, string>>(); var empty = Enumerable.Empty<KeyValuePair<string, string>>();
// For each key/value pair, we want a list containing a single list with either the term, or the term and the "default" value // For each key/value pair, we want a list containing a single list with either the term, or the term and the "default" value
var termSets = ordered.Select(term => { var termSets = ordered.Select(term => {
@ -119,15 +115,15 @@ namespace Orchard.Alias.Implementation.Map {
var termKey = term.Key.Substring(0, term.Key.Length - 1); var termKey = term.Key.Substring(0, term.Key.Length - 1);
return new[] { return new[] {
// This entry will auto-match in some cases because it was omitted from the route values // This entry will auto-match in some cases because it was omitted from the route values
Single(new KeyValuePair<string, string>(termKey, "\u0000")), new [] { new KeyValuePair<string, string>(termKey, "\u0000") },
Single(new KeyValuePair<string, string>(termKey, term.Value)) new [] { new KeyValuePair<string, string>(termKey, term.Value) }
}; };
} }
return new[] {new[] {term}}; return new[] {new[] {term}};
}); });
// Run each of those lists through an aggregation function, by taking the product of each set, so producting a tree of possibilities // Run each of those lists through an aggregation function, by taking the product of each set, so producting a tree of possibilities
var produced = termSets.Aggregate(Single(empty), (coords, termSet) => Product(coords, termSet, (coord, term) => coord.Concat(term))); var produced = termSets.Aggregate(new[] { empty }.AsEnumerable(), (coords, termSet) => Product(coords, termSet, (coord, term) => coord.Concat(term)));
return produced; return produced;
} }

View File

@ -9,38 +9,33 @@ using Orchard.Environment;
using Orchard.Tasks; using Orchard.Tasks;
using Orchard.Logging; using Orchard.Logging;
namespace Orchard.Alias.Implementation.Updater namespace Orchard.Alias.Implementation.Updater {
{ public class AliasHolderUpdater : IOrchardShellEvents, IBackgroundTask {
public class AliasHolderUpdater : IOrchardShellEvents, IBackgroundTask
{
private readonly IAliasHolder _aliasHolder; private readonly IAliasHolder _aliasHolder;
private readonly IAliasStorage _storage; private readonly IAliasStorage _storage;
public ILogger Logger { get; set; } public ILogger Logger { get; set; }
public AliasHolderUpdater(IAliasHolder aliasHolder, IAliasStorage storage) public AliasHolderUpdater(IAliasHolder aliasHolder, IAliasStorage storage) {
{
_aliasHolder = aliasHolder; _aliasHolder = aliasHolder;
_storage = storage; _storage = storage;
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
} }
void IOrchardShellEvents.Activated() void IOrchardShellEvents.Activated() {
{
Refresh(); Refresh();
} }
void IOrchardShellEvents.Terminating() void IOrchardShellEvents.Terminating() {
{
} }
private void Refresh() { private void Refresh() {
try { try {
var aliases = _storage.List(); var aliases = _storage.List();
_aliasHolder.SetAliases(aliases.Select(alias=>new AliasInfo{Path = alias.Item1, Area = alias.Item2, RouteValues=alias.Item3})); _aliasHolder.SetAliases(aliases.Select(alias => new AliasInfo { Path = alias.Item1, Area = alias.Item2, RouteValues = alias.Item3 }));
} }
catch(Exception ex) { catch (Exception ex) {
Logger.Error(ex,"Exception during Alias refresh"); Logger.Error(ex, "Exception during Alias refresh");
} }
} }

View File

@ -8,15 +8,12 @@ using Orchard.Mvc.Extensions;
using Orchard.Mvc.Routes; using Orchard.Mvc.Routes;
using Orchard.Mvc.Wrappers; using Orchard.Mvc.Wrappers;
namespace Orchard.Alias.Implementation namespace Orchard.Alias.Implementation {
{ public static class Utils {
public static class Utils
{
public static IDictionary<string, string> LookupRouteValues public static IDictionary<string, string> LookupRouteValues
(HttpContextBase httpContext, IEnumerable<RouteDescriptor> (HttpContextBase httpContext, IEnumerable<RouteDescriptor>
routeDescriptors, routeDescriptors,
string routePath) string routePath) {
{
var queryStringIndex = routePath.IndexOf('?'); var queryStringIndex = routePath.IndexOf('?');
var routePathNoQueryString = queryStringIndex == -1 ? routePath : routePath.Substring(0, queryStringIndex); var routePathNoQueryString = queryStringIndex == -1 ? routePath : routePath.Substring(0, queryStringIndex);
var queryString = queryStringIndex == -1 ? null : routePath.Substring(queryStringIndex + 1); var queryString = queryStringIndex == -1 ? null : routePath.Substring(queryStringIndex + 1);
@ -51,8 +48,8 @@ namespace Orchard.Alias.Implementation
public static IEnumerable<VirtualPathData> LookupVirtualPaths( public static IEnumerable<VirtualPathData> LookupVirtualPaths(
HttpContextBase httpContext, HttpContextBase httpContext,
IEnumerable<RouteDescriptor> routeDescriptors, IEnumerable<RouteDescriptor> routeDescriptors,
string areaName, string areaName,
IDictionary<string,string> routeValues) { IDictionary<string, string> routeValues) {
var routeValueDictionary = new RouteValueDictionary(routeValues.ToDictionary(kv => RemoveDash(kv.Key), kv => (object)kv.Value)); var routeValueDictionary = new RouteValueDictionary(routeValues.ToDictionary(kv => RemoveDash(kv.Key), kv => (object)kv.Value));
var virtualPathDatas = routeDescriptors.Where(r2 => r2.Route.GetAreaName() == areaName) var virtualPathDatas = routeDescriptors.Where(r2 => r2.Route.GetAreaName() == areaName)
@ -68,26 +65,21 @@ namespace Orchard.Alias.Implementation
} }
private static Dictionary<string, string> ToRouteValues(RouteData routeData, string queryString) private static Dictionary<string, string> ToRouteValues(RouteData routeData, string queryString) {
{
var routeValues = routeData.Values var routeValues = routeData.Values
.Select(kv => .Select(kv => {
{
var value = Convert.ToString(kv.Value, CultureInfo.InvariantCulture); var value = Convert.ToString(kv.Value, CultureInfo.InvariantCulture);
var defaultValue = FindDefault(routeData.Route, kv.Key); var defaultValue = FindDefault(routeData.Route, kv.Key);
if (defaultValue != null && string.Equals(defaultValue, value, StringComparison.InvariantCultureIgnoreCase)) if (defaultValue != null && string.Equals(defaultValue, value, StringComparison.InvariantCultureIgnoreCase)) {
{
return new { Key = kv.Key + "-", Value = value }; return new { Key = kv.Key + "-", Value = value };
} }
return new { kv.Key, Value = value }; return new { kv.Key, Value = value };
}) })
.ToDictionary(kv => kv.Key, kv => kv.Value); .ToDictionary(kv => kv.Key, kv => kv.Value);
if (queryString != null) if (queryString != null) {
{
foreach (var term in queryString foreach (var term in queryString
.Split(new[] { "&" }, StringSplitOptions.RemoveEmptyEntries) .Split(new[] { "&" }, StringSplitOptions.RemoveEmptyEntries)
.Select(ParseTerm)) .Select(ParseTerm)) {
{
if (!routeValues.ContainsKey(term[0])) if (!routeValues.ContainsKey(term[0]))
routeValues[term[0]] = term[1]; routeValues[term[0]] = term[1];
} }
@ -95,75 +87,61 @@ namespace Orchard.Alias.Implementation
return routeValues; return routeValues;
} }
private static string[] ParseTerm(string term) private static string[] ParseTerm(string term) {
{
var equalsIndex = term.IndexOf('='); var equalsIndex = term.IndexOf('=');
if (equalsIndex == -1) if (equalsIndex == -1) {
{
return new[] { Uri.UnescapeDataString(term), null }; return new[] { Uri.UnescapeDataString(term), null };
} }
return new[] { Uri.UnescapeDataString(term.Substring(0, equalsIndex)), Uri.UnescapeDataString(term.Substring(equalsIndex + 1)) }; return new[] { Uri.UnescapeDataString(term.Substring(0, equalsIndex)), Uri.UnescapeDataString(term.Substring(equalsIndex + 1)) };
} }
private static string FindDefault(RouteBase route, string key) private static string FindDefault(RouteBase route, string key) {
{
var route2 = route as Route; var route2 = route as Route;
if (route2 == null) if (route2 == null) {
{
return null; return null;
} }
object defaultValue; object defaultValue;
if (!route2.Defaults.TryGetValue(key, out defaultValue)) if (!route2.Defaults.TryGetValue(key, out defaultValue)) {
{
return null; return null;
} }
return Convert.ToString(defaultValue, CultureInfo.InvariantCulture); return Convert.ToString(defaultValue, CultureInfo.InvariantCulture);
} }
public class LookupHttpContext : HttpContextBaseWrapper public class LookupHttpContext : HttpContextBaseWrapper {
{
private readonly string _path; private readonly string _path;
public LookupHttpContext(HttpContextBase httpContext, string path) public LookupHttpContext(HttpContextBase httpContext, string path)
: base(httpContext) : base(httpContext) {
{
_path = path; _path = path;
} }
public override HttpRequestBase Request public override HttpRequestBase Request {
{
get { return new LookupHttpRequest(this, base.Request, _path); } get { return new LookupHttpRequest(this, base.Request, _path); }
} }
private class LookupHttpRequest : HttpRequestBaseWrapper private class LookupHttpRequest : HttpRequestBaseWrapper {
{
private readonly string _path; private readonly string _path;
public LookupHttpRequest(HttpContextBase httpContextBase, HttpRequestBase httpRequestBase, string path) public LookupHttpRequest(HttpContextBase httpContextBase, HttpRequestBase httpRequestBase, string path)
: base( /*httpContextBase,*/ httpRequestBase) : base( /*httpContextBase,*/ httpRequestBase) {
{
_path = path; _path = path;
} }
public override string AppRelativeCurrentExecutionFilePath public override string AppRelativeCurrentExecutionFilePath {
{
get { return "~/" + _path; } get { return "~/" + _path; }
} }
public override string ApplicationPath public override string ApplicationPath {
{
get { return "/"; } get { return "/"; }
} }
public override string Path public override string Path {
{
get { return "/" + _path; } get { return "/" + _path; }
} }
public override string PathInfo public override string PathInfo {
{
get { return ""; } get { return ""; }
} }
} }

View File

@ -98,7 +98,7 @@ namespace Orchard.Autoroute.Drivers {
if (path.StartsWith(".") || path.EndsWith(".")) if (path.StartsWith(".") || path.EndsWith("."))
updater.AddModelError("CurrentUrl", T("The \".\" can't be used at either end of the permalink.")); updater.AddModelError("CurrentUrl", T("The \".\" can't be used at either end of the permalink."));
else else
updater.AddModelError("CurrentUrl", T("Please do not use any of the following characters in your permalink: \":\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\", \", \"<\", \">\", \"\\\". No spaces are allowed (please use dashes or underscores instead).")); updater.AddModelError("CurrentUrl", T("Please do not use any of the following characters in your permalink: \":\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\", \", \"<\", \">\", \"\\\", \"|\". No spaces are allowed (please use dashes or underscores instead)."));
} }
// if CurrentUrl is set, the handler won't try to create an alias for it // if CurrentUrl is set, the handler won't try to create an alias for it

View File

@ -166,7 +166,7 @@ namespace Orchard.Autoroute.Services {
} }
public bool IsPathValid(string slug) { public bool IsPathValid(string slug) {
return String.IsNullOrWhiteSpace(slug) || Regex.IsMatch(slug, @"^[^:?#\[\]@!$&'()*+,;=\s\""\<\>\\]+$") && !(slug.StartsWith(".") || slug.EndsWith(".")); return String.IsNullOrWhiteSpace(slug) || Regex.IsMatch(slug, @"^[^:?#\[\]@!$&'()*+,;=\s\""\<\>\\\|]+$") && !(slug.StartsWith(".") || slug.EndsWith("."));
} }
public bool ProcessPath(AutoroutePart part) { public bool ProcessPath(AutoroutePart part) {

View File

@ -7,7 +7,7 @@ namespace Orchard.Autoroute.Services {
public class DefaultSlugService : ISlugService { public class DefaultSlugService : ISlugService {
private readonly ISlugEventHandler _slugEventHandler; private readonly ISlugEventHandler _slugEventHandler;
public DefaultSlugService( public DefaultSlugService(
ISlugEventHandler slugEventHander ISlugEventHandler slugEventHander
) { ) {
@ -26,7 +26,7 @@ namespace Orchard.Autoroute.Services {
if (!slugContext.Adjusted) { if (!slugContext.Adjusted) {
var disallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s\""\<\>\\]+"); var disallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s\""\<\>\\\|]+");
slugContext.Slug = disallowed.Replace(slugContext.Title, "-").Trim('-','.'); slugContext.Slug = disallowed.Replace(slugContext.Title, "-").Trim('-','.');

View File

@ -131,8 +131,9 @@ namespace Orchard.CustomForms.Controllers {
foreach (var error in ModelState.Values.SelectMany(m => m.Errors).Select(e => e.ErrorMessage)) { foreach (var error in ModelState.Values.SelectMany(m => m.Errors).Select(e => e.ErrorMessage)) {
Services.Notifier.Error(T(error)); Services.Notifier.Error(T(error));
} }
if (returnUrl != null) { if (returnUrl != null) {
return Redirect(returnUrl); return this.RedirectLocal(returnUrl);
} }
} }
@ -165,7 +166,8 @@ namespace Orchard.CustomForms.Controllers {
} }
} }
return this.RedirectLocal(returnUrl, () => Redirect(Request.RawUrl)); var referrer = Request.UrlReferrer != null ? Request.UrlReferrer.ToString() : null;
return this.RedirectLocal(returnUrl, () => this.RedirectLocal(referrer, () => Redirect(Request.RawUrl)));
} }
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) { bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {

View File

@ -33,8 +33,7 @@ namespace Orchard.CustomForms.Drivers {
return ContentShape("Parts_CustomForm_Wrapper", () => { return ContentShape("Parts_CustomForm_Wrapper", () => {
return shapeHelper.Parts_CustomForm_Wrapper() return shapeHelper.Parts_CustomForm_Wrapper()
.Editor(_orchardServices.ContentManager.BuildEditor(contentItem)) .Editor(_orchardServices.ContentManager.BuildEditor(contentItem))
.ContenItem(part) .ContenItem(part);
.ReturnUrl(part.Redirect ? part.RedirectUrl : _orchardServices.WorkContext.HttpContext.Request.RawUrl);
}); });
} }

View File

@ -2,7 +2,6 @@
@{ @{
ContentItem customForm = Model.ContentItem; ContentItem customForm = Model.ContentItem;
string returnUrl = Model.ReturnUrl;
// remove default Save/Publish buttons // remove default Save/Publish buttons
Model.Editor.Zones["Sidebar"].Items.Clear(); Model.Editor.Zones["Sidebar"].Items.Clear();
@ -13,7 +12,7 @@
// Model is a Shape, calling Display() so that it is rendered using the most specific template for its Shape type // Model is a Shape, calling Display() so that it is rendered using the most specific template for its Shape type
@Display(Model.Editor) @Display(Model.Editor)
@Html.Hidden("returnUrl", returnUrl); @Html.Hidden("returnUrl", Request.RawUrl);
<fieldset class="submit-button"> <fieldset class="submit-button">
<button type="submit" name="submit.Save" value="submit.Save">@T("Submit")</button> <button type="submit" name="submit.Save" value="submit.Save">@T("Submit")</button>

View File

@ -67,7 +67,7 @@ shapeTracingMetadataHost[@Model.ShapeId].shape = {
@if (!String.IsNullOrEmpty((string)Model.PlacementSource) && (WorkContext.HttpContext.Items[(string)Model.PlacementSource] == null)) { @if (!String.IsNullOrEmpty((string)Model.PlacementSource) && (WorkContext.HttpContext.Items[(string)Model.PlacementSource] == null)) {
WorkContext.HttpContext.Items[(string)Model.PlacementSource] = new object(); WorkContext.HttpContext.Items[(string)Model.PlacementSource] = new object();
<text>shapeTracingMetadataHost.placement['@Model.PlacementSource.ToString()'] = '@ShapeTracingFactory.FormatJsonValue((string)Model.PlacementContent)'; </text> <text>shapeTracingMetadataHost.placement['@Model.PlacementSource.ToString()'] = '@HttpUtility.JavaScriptStringEncode((string)Model.PlacementContent)'; </text>
} }
</script> </script>

View File

@ -21,14 +21,13 @@
@Html.HiddenFor(m => m.Class) @Html.HiddenFor(m => m.Class)
@Html.HiddenFor(m => m.Style) @Html.HiddenFor(m => m.Style)
@Html.HiddenFor(m => m.Alignment) @Html.HiddenFor(m => m.Alignment)
@Html.HiddenFor(m => m.Alignment)
@Html.HiddenFor(m => m.Width) @Html.HiddenFor(m => m.Width)
@Html.HiddenFor(m => m.Height) @Html.HiddenFor(m => m.Height)
</fieldset> </fieldset>
@using (Script.Foot()) @using (Script.Foot()) {
{
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
@ -37,8 +36,22 @@
}); });
jQuery('#btn-@Html.FieldIdFor(m => m.Url)').click(function () { jQuery('#btn-@Html.FieldIdFor(m => m.Url)').click(function () {
var currentImageUrl = $('#@Html.FieldIdFor(m => m.Url)').val();
if (currentImageUrl && currentImageUrl.length > 2 && currentImageUrl.substr(0, 2) == "~/") {
currentImageUrl = '@Url.Content("~/")' + currentImageUrl.substr(2);
}
jQuery('#btn-@Html.FieldIdFor(m => m.Url)').trigger("orchard-admin-pickimage-open", { jQuery('#btn-@Html.FieldIdFor(m => m.Url)').trigger("orchard-admin-pickimage-open", {
img: null, img: {
src: currentImageUrl,
"class": $('#@Html.FieldIdFor(m => m.Class)').val(),
style: $('#@Html.FieldIdFor(m => m.Style)').val(),
alt: $('#@Html.FieldIdFor(m => m.AlternateText)').val(),
width: $('#@Html.FieldIdFor(m => m.Width)').val(),
height: $('#@Html.FieldIdFor(m => m.Height)').val(),
align: $('#@Html.FieldIdFor(m => m.Alignment)').val()
},
uploadMediaPath: 'images', uploadMediaPath: 'images',
callback: function (data) { callback: function (data) {
var applicationPath = '@Url.RequestContext.HttpContext.Request.ApplicationPath.ToLower()'; var applicationPath = '@Url.RequestContext.HttpContext.Request.ApplicationPath.ToLower()';

View File

@ -36,7 +36,7 @@
@foreach (var module in Model.Entries) { @foreach (var module in Model.Entries) {
<li> <li>
@{ @{
string iconUrl = @module.NewVersionToInstall.IconUrl; string iconUrl = module.NewVersionToInstall.IconUrl;
if (string.IsNullOrWhiteSpace(iconUrl)) { if (string.IsNullOrWhiteSpace(iconUrl)) {
iconUrl = Href("../../Content/Images/ModuleDefaultIcon.png"); iconUrl = Href("../../Content/Images/ModuleDefaultIcon.png");
} }

View File

@ -37,9 +37,9 @@
<li> <li>
@{ @{
string extensionClass = "iconThumbnail"; string extensionClass = "iconThumbnail";
string iconUrl = @theme.NewVersionToInstall.IconUrl; string iconUrl = theme.NewVersionToInstall.IconUrl;
if (!string.IsNullOrWhiteSpace(@theme.NewVersionToInstall.FirstScreenshot)) { if (!string.IsNullOrWhiteSpace(@theme.NewVersionToInstall.FirstScreenshot)) {
iconUrl = @theme.NewVersionToInstall.FirstScreenshot; iconUrl = theme.NewVersionToInstall.FirstScreenshot;
extensionClass = "screenshotThumbnail"; extensionClass = "screenshotThumbnail";
} else if (string.IsNullOrWhiteSpace(iconUrl)) { } else if (string.IsNullOrWhiteSpace(iconUrl)) {
iconUrl = Href("../../Content/Images/imagePlaceholder.png"); iconUrl = Href("../../Content/Images/imagePlaceholder.png");

View File

@ -59,10 +59,6 @@ namespace Orchard.Environment.Extensions.Loaders {
return GetDependencies(dependency.VirtualPath); return GetDependencies(dependency.VirtualPath);
} }
public IEnumerable<string> GetFileHashDependencies(DependencyDescriptor dependency) {
return GetDependencies(dependency.VirtualPath);
}
public override void Monitor(ExtensionDescriptor descriptor, Action<IVolatileToken> monitor) { public override void Monitor(ExtensionDescriptor descriptor, Action<IVolatileToken> monitor) {
if (Disabled) if (Disabled)
return; return;

View File

@ -173,7 +173,7 @@ namespace Orchard.Environment.Extensions.Loaders {
// A pre-compiled module is _not_ compatible with a dynamically loaded module // A pre-compiled module is _not_ compatible with a dynamically loaded module
// because a pre-compiled module usually references a pre-compiled assembly binary // because a pre-compiled module usually references a pre-compiled assembly binary
// which will have a different identity (i.e. name) from the dynamic module. // which will have a different identity (i.e. name) from the dynamic module.
bool result = references.All(r => r.Loader.GetType() != typeof(DynamicExtensionLoader) && r.Loader.GetType() != typeof(ProbingExtensionLoader)); bool result = references.All(r => r.Loader.GetType() != typeof(DynamicExtensionLoader));
if (!result) { if (!result) {
Logger.Information("Extension \"{0}\" will not be loaded as pre-compiled extension because one or more referenced extension is dynamically compiled", extension.Id); Logger.Information("Extension \"{0}\" will not be loaded as pre-compiled extension because one or more referenced extension is dynamically compiled", extension.Id);
} }

View File

@ -1,248 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Orchard.Caching;
using Orchard.Environment.Extensions.Compilers;
using Orchard.Environment.Extensions.Models;
using Orchard.FileSystems.Dependencies;
using Orchard.FileSystems.VirtualPath;
using Orchard.Logging;
using Orchard.Utility.Extensions;
namespace Orchard.Environment.Extensions.Loaders {
/// <summary>
/// In case <see cref="DynamicExtensionLoader"/> is disabled, this loader will dynamically compile the assembly
/// and save a copy to the probing folder so that next restart doesn't need to compile it again.
/// </summary>
public class ProbingExtensionLoader : ExtensionLoaderBase {
public static readonly string[] ExtensionsVirtualPathPrefixes = { "~/Modules/", "~/Themes/" };
private readonly IBuildManager _buildManager;
private readonly IVirtualPathProvider _virtualPathProvider;
private readonly IHostEnvironment _hostEnvironment;
private readonly IAssemblyProbingFolder _assemblyProbingFolder;
private readonly IDependenciesFolder _dependenciesFolder;
private readonly IProjectFileParser _projectFileParser;
public ProbingExtensionLoader(
IBuildManager buildManager,
IVirtualPathProvider virtualPathProvider,
IVirtualPathMonitor virtualPathMonitor,
IHostEnvironment hostEnvironment,
IAssemblyProbingFolder assemblyProbingFolder,
IDependenciesFolder dependenciesFolder,
IProjectFileParser projectFileParser)
: base(dependenciesFolder) {
_buildManager = buildManager;
_virtualPathProvider = virtualPathProvider;
_hostEnvironment = hostEnvironment;
_assemblyProbingFolder = assemblyProbingFolder;
_projectFileParser = projectFileParser;
_dependenciesFolder = dependenciesFolder;
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public bool Disabled { get; set; }
public override int Order { get { return 110; } }
public override IEnumerable<ExtensionCompilationReference> GetCompilationReferences(DependencyDescriptor dependency) {
yield return new ExtensionCompilationReference { BuildProviderTarget = dependency.VirtualPath };
}
public override void ExtensionRemoved(ExtensionLoadingContext ctx, DependencyDescriptor dependency) {
}
public override void ExtensionDeactivated(ExtensionLoadingContext ctx, ExtensionDescriptor extension) {
}
public override void ExtensionActivated(ExtensionLoadingContext ctx, ExtensionDescriptor extension) {
}
public override IEnumerable<ExtensionReferenceProbeEntry> ProbeReferences(ExtensionDescriptor descriptor) {
if (Disabled)
return Enumerable.Empty<ExtensionReferenceProbeEntry>();
Logger.Information("Probing references for module '{0}'", descriptor.Id);
string projectPath = GetProjectPath(descriptor);
if (projectPath == null)
return Enumerable.Empty<ExtensionReferenceProbeEntry>();
var projectFile = _projectFileParser.Parse(projectPath);
var result = projectFile.References.Select(r => new ExtensionReferenceProbeEntry {
Descriptor = descriptor,
Loader = this,
Name = r.SimpleName,
VirtualPath = _virtualPathProvider.GetProjectReferenceVirtualPath(projectPath, r.SimpleName, r.Path)
});
Logger.Information("Done probing references for module '{0}'", descriptor.Id);
return result;
}
public override void ReferenceActivated(ExtensionLoadingContext context, ExtensionReferenceProbeEntry referenceEntry) {
//Note: This is the same implementation as "PrecompiledExtensionLoader"
if (string.IsNullOrEmpty(referenceEntry.VirtualPath))
return;
string sourceFileName = _virtualPathProvider.MapPath(referenceEntry.VirtualPath);
// Copy the assembly if it doesn't exist or if it is older than the source file.
bool copyAssembly =
!_assemblyProbingFolder.AssemblyExists(referenceEntry.Name) ||
File.GetLastWriteTimeUtc(sourceFileName) > _assemblyProbingFolder.GetAssemblyDateTimeUtc(referenceEntry.Name);
if (copyAssembly) {
context.CopyActions.Add(() => _assemblyProbingFolder.StoreAssembly(referenceEntry.Name, sourceFileName));
// We need to restart the appDomain if the assembly is loaded
if (_hostEnvironment.IsAssemblyLoaded(referenceEntry.Name)) {
Logger.Information("ReferenceActivated: Reference \"{0}\" is activated with newer file and its assembly is loaded, forcing AppDomain restart", referenceEntry.Name);
context.RestartAppDomain = true;
}
}
}
public override Assembly LoadReference(DependencyReferenceDescriptor reference) {
if (Disabled)
return null;
Logger.Information("Loading reference '{0}'", reference.Name);
// DynamicExtensionLoader has 2 types of references: assemblies from module bin directory
// and .csproj.
Assembly result;
if (StringComparer.OrdinalIgnoreCase.Equals(Path.GetExtension(reference.VirtualPath), ".dll"))
result = _assemblyProbingFolder.LoadAssembly(reference.Name);
else {
result = ProbeAssembly(reference.Name, reference.VirtualPath);
}
Logger.Information("Done loading reference '{0}'", reference.Name);
return result;
}
public override ExtensionProbeEntry Probe(ExtensionDescriptor descriptor) {
if (Disabled)
return null;
Logger.Information("Probing for module '{0}'", descriptor.Id);
string projectPath = GetProjectPath(descriptor);
if (projectPath == null)
return null;
var result = new ExtensionProbeEntry {
Descriptor = descriptor,
Loader = this,
Priority = 50,
VirtualPath = projectPath,
VirtualPathDependencies = new string[] { projectPath },
};
Logger.Information("Done probing for module '{0}'", descriptor.Id);
return result;
}
protected override ExtensionEntry LoadWorker(ExtensionDescriptor descriptor) {
if (Disabled)
return null;
Logger.Information("Start loading dynamic extension \"{0}\"", descriptor.Name);
var assembly = _assemblyProbingFolder.LoadAssembly(descriptor.Id);
if (assembly == null) {
string projectPath = GetProjectPath(descriptor);
if (projectPath == null)
return null;
assembly = ProbeAssembly(descriptor.Id, projectPath);
}
if (assembly == null)
return null;
Logger.Information("Done loading dynamic extension \"{0}\": assembly name=\"{1}\"", descriptor.Name, assembly.FullName);
return new ExtensionEntry {
Descriptor = descriptor,
Assembly = assembly,
ExportedTypes = assembly.GetExportedTypes(),
};
}
private void AddDependencies(string projectPath, HashSet<string> currentSet) {
// Skip files from locations other than "~/Modules" and "~/Themes"
if (string.IsNullOrEmpty(PrefixMatch(projectPath, ExtensionsVirtualPathPrefixes))) {
return;
}
// Add project path
currentSet.Add(projectPath);
// Add source file paths
var projectFile = _projectFileParser.Parse(projectPath);
string basePath = _virtualPathProvider.GetDirectoryName(projectPath);
currentSet.UnionWith(projectFile.SourceFilenames.Select(f => _virtualPathProvider.Combine(basePath, f)));
// Add Project and Library references
if (projectFile.References != null) {
foreach (ReferenceDescriptor referenceDescriptor in projectFile.References.Where(reference => !string.IsNullOrEmpty(reference.Path))) {
string path = referenceDescriptor.ReferenceType == ReferenceType.Library
? _virtualPathProvider.GetProjectReferenceVirtualPath(projectPath, referenceDescriptor.SimpleName, referenceDescriptor.Path)
: _virtualPathProvider.Combine(basePath, referenceDescriptor.Path);
// Normalize the virtual path (avoid ".." in the path name)
if (!string.IsNullOrEmpty(path)) {
path = _virtualPathProvider.ToAppRelative(path);
}
// Attempt to reference the project / library file
if (!string.IsNullOrEmpty(path) && !currentSet.Contains(path) && _virtualPathProvider.TryFileExists(path)) {
switch (referenceDescriptor.ReferenceType) {
case ReferenceType.Project:
AddDependencies(path, currentSet);
break;
case ReferenceType.Library:
currentSet.Add(path);
break;
}
}
}
}
}
private Assembly ProbeAssembly(string moduleName, string virtualPath) {
var assembly = _buildManager.GetCompiledAssembly(virtualPath);
if (assembly != null) {
_assemblyProbingFolder.StoreAssembly(moduleName, assembly.Location);
return assembly;
}
return null;
}
private static string PrefixMatch(string virtualPath, params string[] prefixes) {
return prefixes
.FirstOrDefault(p => virtualPath.StartsWith(p, StringComparison.OrdinalIgnoreCase));
}
private string GetProjectPath(ExtensionDescriptor descriptor) {
string projectPath = _virtualPathProvider.Combine(descriptor.Location, descriptor.Id,
descriptor.Id + ".csproj");
if (!_virtualPathProvider.FileExists(projectPath)) {
return null;
}
return projectPath;
}
}
}

View File

@ -103,7 +103,6 @@ namespace Orchard.Environment {
builder.RegisterType<ReferencedExtensionLoader>().As<IExtensionLoader>().SingleInstance(); builder.RegisterType<ReferencedExtensionLoader>().As<IExtensionLoader>().SingleInstance();
builder.RegisterType<PrecompiledExtensionLoader>().As<IExtensionLoader>().SingleInstance(); builder.RegisterType<PrecompiledExtensionLoader>().As<IExtensionLoader>().SingleInstance();
builder.RegisterType<DynamicExtensionLoader>().As<IExtensionLoader>().SingleInstance(); builder.RegisterType<DynamicExtensionLoader>().As<IExtensionLoader>().SingleInstance();
builder.RegisterType<ProbingExtensionLoader>().As<IExtensionLoader>().SingleInstance();
builder.RegisterType<RawThemeExtensionLoader>().As<IExtensionLoader>().SingleInstance(); builder.RegisterType<RawThemeExtensionLoader>().As<IExtensionLoader>().SingleInstance();
} }
} }

View File

@ -111,7 +111,6 @@ namespace Orchard.FileSystems.Dependencies {
// implementations. // implementations.
return return
loaderName == "DynamicExtensionLoader" || loaderName == "DynamicExtensionLoader" ||
loaderName == "ProbingExtensionLoader" ||
loaderName == "PrecompiledExtensionLoader"; loaderName == "PrecompiledExtensionLoader";
} }

View File

@ -202,7 +202,6 @@
<Compile Include="Environment\Extensions\Folders\CoreModuleFolders.cs" /> <Compile Include="Environment\Extensions\Folders\CoreModuleFolders.cs" />
<Compile Include="Environment\Extensions\Folders\IExtensionHarvester.cs" /> <Compile Include="Environment\Extensions\Folders\IExtensionHarvester.cs" />
<Compile Include="Environment\Extensions\IExtensionMonitoringCoordinator.cs" /> <Compile Include="Environment\Extensions\IExtensionMonitoringCoordinator.cs" />
<Compile Include="Environment\Extensions\Loaders\ProbingExtensionLoader.cs" />
<Compile Include="Environment\Extensions\OrchardSuppressDependencyAttribute.cs" /> <Compile Include="Environment\Extensions\OrchardSuppressDependencyAttribute.cs" />
<Compile Include="Environment\Features\IFeatureManager.cs" /> <Compile Include="Environment\Features\IFeatureManager.cs" />
<Compile Include="Environment\IAssemblyNameResolver.cs" /> <Compile Include="Environment\IAssemblyNameResolver.cs" />

View File

@ -72,6 +72,10 @@ namespace Orchard.Utility.Extensions {
return false; return false;
} }
if (url.StartsWith("~/")) {
return true;
}
if (url.StartsWith("//") || url.StartsWith("/\\")) { if (url.StartsWith("//") || url.StartsWith("/\\")) {
return false; return false;
} }