mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-21 19:34:40 +08:00
Cleaning Alias code
--HG-- branch : 1.x
This commit is contained in:
@@ -22,7 +22,7 @@ namespace Orchard.Alias.Controllers {
|
||||
public AdminController(
|
||||
IAliasService aliasService,
|
||||
IOrchardServices orchardServices,
|
||||
IAliasHolder aliasHolder ) {
|
||||
IAliasHolder aliasHolder) {
|
||||
_aliasService = aliasService;
|
||||
_aliasHolder = aliasHolder;
|
||||
Services = orchardServices;
|
||||
@@ -65,7 +65,7 @@ namespace Orchard.Alias.Controllers {
|
||||
aliases = aliases.OrderBy(x => x.Path);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (pager.PageSize != 0) {
|
||||
aliases = aliases.Skip(pager.GetStartIndex()).Take(pager.PageSize);
|
||||
}
|
||||
@@ -73,7 +73,7 @@ namespace Orchard.Alias.Controllers {
|
||||
var model = new AdminIndexViewModel {
|
||||
Options = options,
|
||||
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);
|
||||
@@ -103,7 +103,7 @@ namespace Orchard.Alias.Controllers {
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
return RedirectToAction("Index");
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
public ActionResult Add() {
|
||||
@@ -118,7 +118,7 @@ namespace Orchard.Alias.Controllers {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage aliases")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
if(aliasPath == "/") {
|
||||
if (aliasPath == "/") {
|
||||
aliasPath = String.Empty;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace Orchard.Alias.Controllers {
|
||||
ModelState.AddModelError("Route", T("Route can't be empty").Text);
|
||||
}
|
||||
|
||||
if(!ModelState.IsValid) {
|
||||
if (!ModelState.IsValid) {
|
||||
return View();
|
||||
}
|
||||
|
||||
@@ -162,11 +162,11 @@ namespace Orchard.Alias.Controllers {
|
||||
|
||||
var routeValues = _aliasService.Get(path);
|
||||
|
||||
if (routeValues==null)
|
||||
if (routeValues == null)
|
||||
return HttpNotFound();
|
||||
|
||||
var virtualPaths = _aliasService.LookupVirtualPaths(routeValues,HttpContext)
|
||||
.Select(vpd=>vpd.VirtualPath);
|
||||
var virtualPaths = _aliasService.LookupVirtualPaths(routeValues, HttpContext)
|
||||
.Select(vpd => vpd.VirtualPath);
|
||||
|
||||
ViewBag.AliasPath = path;
|
||||
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
|
||||
_aliasService.Set(aliasPath, routePath, "Custom");
|
||||
|
||||
|
||||
// Remove previous alias
|
||||
if (path != aliasPath)
|
||||
{
|
||||
if (path != aliasPath) {
|
||||
// TODO: (PH:Autoroute) Ability to fire an "AliasChanged" event so we make a redirect
|
||||
_aliasService.Delete(path);
|
||||
}
|
||||
|
||||
Services.Notifier.Information(T("Alias {0} updated", path));
|
||||
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Delete(string path) {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage aliases")))
|
||||
|
@@ -2,10 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Routing;
|
||||
|
||||
namespace Orchard.Alias
|
||||
{
|
||||
public interface IAliasService : IDependency
|
||||
{
|
||||
namespace Orchard.Alias {
|
||||
public interface IAliasService : IDependency {
|
||||
RouteValueDictionary Get(string aliasPath);
|
||||
void Set(string aliasPath, RouteValueDictionary routeValues, 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);
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
@@ -8,34 +8,33 @@ using System.Web.Routing;
|
||||
using Orchard.Alias.Implementation.Holder;
|
||||
using Orchard.Alias.Implementation.Map;
|
||||
|
||||
namespace Orchard.Alias.Implementation
|
||||
{
|
||||
public class AliasRoute : RouteBase, IRouteWithArea
|
||||
{
|
||||
namespace Orchard.Alias.Implementation {
|
||||
public class AliasRoute : RouteBase, IRouteWithArea {
|
||||
private readonly AliasMap _aliasMap;
|
||||
private readonly IRouteHandler _routeHandler;
|
||||
|
||||
public AliasRoute(IAliasHolder aliasHolder, string areaName, IRouteHandler routeHandler)
|
||||
{
|
||||
public AliasRoute(IAliasHolder aliasHolder, string areaName, IRouteHandler routeHandler) {
|
||||
Area = areaName;
|
||||
_aliasMap = aliasHolder.GetMap(areaName);
|
||||
_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
|
||||
var virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
|
||||
|
||||
// Attempt to lookup RouteValues in the alias map
|
||||
IDictionary<string, string> routeValues;
|
||||
// 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
|
||||
var data = new RouteData(this, _routeHandler);
|
||||
foreach (var routeValue in routeValues)
|
||||
{
|
||||
foreach (var routeValue in routeValues) {
|
||||
var key = routeValue.Key;
|
||||
if (key.EndsWith("-"))
|
||||
data.Values.Add(key.Substring(0, key.Length - 1), routeValue.Value);
|
||||
@@ -51,22 +50,19 @@ namespace Orchard.Alias.Implementation
|
||||
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
|
||||
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)
|
||||
var sb = new StringBuilder(match.Item2);
|
||||
var extra = 0;
|
||||
foreach (var routeValue in routeValues)
|
||||
{
|
||||
foreach (var routeValue in routeValues) {
|
||||
// Ignore any we already have
|
||||
if (match.Item1.ContainsKey(routeValue.Key))
|
||||
{
|
||||
if (match.Item1.ContainsKey(routeValue.Key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add a query string fragment
|
||||
sb.Append((extra++ == 0) ? '?' : '&');
|
||||
sb.Append(Uri.EscapeDataString(routeValue.Key));
|
||||
|
@@ -25,7 +25,7 @@ namespace Orchard.Alias.Implementation.Holder {
|
||||
}
|
||||
|
||||
public void SetAlias(AliasInfo alias) {
|
||||
foreach(var map in _aliasMaps.Values) {
|
||||
foreach (var map in _aliasMaps.Values) {
|
||||
map.Remove(alias);
|
||||
}
|
||||
|
||||
|
@@ -53,6 +53,10 @@ namespace Orchard.Alias.Implementation.Map {
|
||||
CollapseTree(_root, info.Path, info.RouteValues);
|
||||
}
|
||||
|
||||
public bool Any() {
|
||||
return _aliases.Any();
|
||||
}
|
||||
|
||||
private static void CollapseTree(Node root, string path, IDictionary<string, string> routeValues) {
|
||||
foreach (var expanded in Expand(routeValues)) {
|
||||
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);
|
||||
}
|
||||
|
||||
private static IEnumerable<T> Single<T>(T t) {
|
||||
yield return t;
|
||||
}
|
||||
|
||||
private static IEnumerable<T> Empty<T>() {
|
||||
return Enumerable.Empty<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expand the route values into all possible combinations of keys
|
||||
/// </summary>
|
||||
@@ -111,7 +107,7 @@ namespace Orchard.Alias.Implementation.Map {
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<IEnumerable<KeyValuePair<string, string>>> Expand(IDictionary<string, string> routeValues) {
|
||||
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
|
||||
var termSets = ordered.Select(term => {
|
||||
@@ -119,15 +115,15 @@ namespace Orchard.Alias.Implementation.Map {
|
||||
var termKey = term.Key.Substring(0, term.Key.Length - 1);
|
||||
return new[] {
|
||||
// This entry will auto-match in some cases because it was omitted from the route values
|
||||
Single(new KeyValuePair<string, string>(termKey, "\u0000")),
|
||||
Single(new KeyValuePair<string, string>(termKey, term.Value))
|
||||
new [] { new KeyValuePair<string, string>(termKey, "\u0000") },
|
||||
new [] { new KeyValuePair<string, string>(termKey, term.Value) }
|
||||
};
|
||||
}
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
|
@@ -9,38 +9,33 @@ using Orchard.Environment;
|
||||
using Orchard.Tasks;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Alias.Implementation.Updater
|
||||
{
|
||||
public class AliasHolderUpdater : IOrchardShellEvents, IBackgroundTask
|
||||
{
|
||||
namespace Orchard.Alias.Implementation.Updater {
|
||||
public class AliasHolderUpdater : IOrchardShellEvents, IBackgroundTask {
|
||||
private readonly IAliasHolder _aliasHolder;
|
||||
private readonly IAliasStorage _storage;
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public AliasHolderUpdater(IAliasHolder aliasHolder, IAliasStorage storage)
|
||||
{
|
||||
public AliasHolderUpdater(IAliasHolder aliasHolder, IAliasStorage storage) {
|
||||
_aliasHolder = aliasHolder;
|
||||
_storage = storage;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
void IOrchardShellEvents.Activated()
|
||||
{
|
||||
void IOrchardShellEvents.Activated() {
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void IOrchardShellEvents.Terminating()
|
||||
{
|
||||
void IOrchardShellEvents.Terminating() {
|
||||
}
|
||||
|
||||
private void Refresh() {
|
||||
try {
|
||||
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) {
|
||||
Logger.Error(ex,"Exception during Alias refresh");
|
||||
catch (Exception ex) {
|
||||
Logger.Error(ex, "Exception during Alias refresh");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -8,15 +8,12 @@ using Orchard.Mvc.Extensions;
|
||||
using Orchard.Mvc.Routes;
|
||||
using Orchard.Mvc.Wrappers;
|
||||
|
||||
namespace Orchard.Alias.Implementation
|
||||
{
|
||||
public static class Utils
|
||||
{
|
||||
namespace Orchard.Alias.Implementation {
|
||||
public static class Utils {
|
||||
public static IDictionary<string, string> LookupRouteValues
|
||||
(HttpContextBase httpContext, IEnumerable<RouteDescriptor>
|
||||
routeDescriptors,
|
||||
string routePath)
|
||||
{
|
||||
(HttpContextBase httpContext, IEnumerable<RouteDescriptor>
|
||||
routeDescriptors,
|
||||
string routePath) {
|
||||
var queryStringIndex = routePath.IndexOf('?');
|
||||
var routePathNoQueryString = queryStringIndex == -1 ? routePath : routePath.Substring(0, queryStringIndex);
|
||||
var queryString = queryStringIndex == -1 ? null : routePath.Substring(queryStringIndex + 1);
|
||||
@@ -51,8 +48,8 @@ namespace Orchard.Alias.Implementation
|
||||
public static IEnumerable<VirtualPathData> LookupVirtualPaths(
|
||||
HttpContextBase httpContext,
|
||||
IEnumerable<RouteDescriptor> routeDescriptors,
|
||||
string areaName,
|
||||
IDictionary<string,string> routeValues) {
|
||||
string areaName,
|
||||
IDictionary<string, string> routeValues) {
|
||||
|
||||
var routeValueDictionary = new RouteValueDictionary(routeValues.ToDictionary(kv => RemoveDash(kv.Key), kv => (object)kv.Value));
|
||||
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
|
||||
.Select(kv =>
|
||||
{
|
||||
.Select(kv => {
|
||||
var value = Convert.ToString(kv.Value, CultureInfo.InvariantCulture);
|
||||
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 { kv.Key, Value = value };
|
||||
})
|
||||
.ToDictionary(kv => kv.Key, kv => kv.Value);
|
||||
if (queryString != null)
|
||||
{
|
||||
if (queryString != null) {
|
||||
foreach (var term in queryString
|
||||
.Split(new[] { "&" }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(ParseTerm))
|
||||
{
|
||||
.Select(ParseTerm)) {
|
||||
if (!routeValues.ContainsKey(term[0]))
|
||||
routeValues[term[0]] = term[1];
|
||||
}
|
||||
@@ -95,75 +87,61 @@ namespace Orchard.Alias.Implementation
|
||||
return routeValues;
|
||||
}
|
||||
|
||||
private static string[] ParseTerm(string term)
|
||||
{
|
||||
private static string[] ParseTerm(string term) {
|
||||
var equalsIndex = term.IndexOf('=');
|
||||
if (equalsIndex == -1)
|
||||
{
|
||||
if (equalsIndex == -1) {
|
||||
return new[] { Uri.UnescapeDataString(term), null };
|
||||
}
|
||||
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;
|
||||
if (route2 == null)
|
||||
{
|
||||
if (route2 == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
object defaultValue;
|
||||
if (!route2.Defaults.TryGetValue(key, out defaultValue))
|
||||
{
|
||||
if (!route2.Defaults.TryGetValue(key, out defaultValue)) {
|
||||
return null;
|
||||
}
|
||||
return Convert.ToString(defaultValue, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public class LookupHttpContext : HttpContextBaseWrapper
|
||||
{
|
||||
public class LookupHttpContext : HttpContextBaseWrapper {
|
||||
private readonly string _path;
|
||||
|
||||
public LookupHttpContext(HttpContextBase httpContext, string path)
|
||||
: base(httpContext)
|
||||
{
|
||||
: base(httpContext) {
|
||||
_path = path;
|
||||
}
|
||||
|
||||
public override HttpRequestBase Request
|
||||
{
|
||||
public override HttpRequestBase Request {
|
||||
get { return new LookupHttpRequest(this, base.Request, _path); }
|
||||
}
|
||||
|
||||
private class LookupHttpRequest : HttpRequestBaseWrapper
|
||||
{
|
||||
private class LookupHttpRequest : HttpRequestBaseWrapper {
|
||||
private readonly string _path;
|
||||
|
||||
public LookupHttpRequest(HttpContextBase httpContextBase, HttpRequestBase httpRequestBase, string path)
|
||||
: base( /*httpContextBase,*/ httpRequestBase)
|
||||
{
|
||||
: base( /*httpContextBase,*/ httpRequestBase) {
|
||||
_path = path;
|
||||
}
|
||||
|
||||
|
||||
public override string AppRelativeCurrentExecutionFilePath
|
||||
{
|
||||
public override string AppRelativeCurrentExecutionFilePath {
|
||||
get { return "~/" + _path; }
|
||||
}
|
||||
|
||||
public override string ApplicationPath
|
||||
{
|
||||
public override string ApplicationPath {
|
||||
get { return "/"; }
|
||||
}
|
||||
|
||||
public override string Path
|
||||
{
|
||||
public override string Path {
|
||||
get { return "/" + _path; }
|
||||
}
|
||||
|
||||
public override string PathInfo
|
||||
{
|
||||
public override string PathInfo {
|
||||
get { return ""; }
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user