mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Merge pull request #5599 from mahsaro/dev
Importing/Exporting of Aliases.
This commit is contained in:
@@ -3,19 +3,21 @@ using Orchard.Localization;
|
||||
using Orchard.Security;
|
||||
using Orchard.UI.Navigation;
|
||||
|
||||
namespace Orchard.Alias
|
||||
{
|
||||
namespace Orchard.Alias {
|
||||
[OrchardFeature("Orchard.Alias.UI")]
|
||||
public class AdminMenu : INavigationProvider
|
||||
{
|
||||
public class AdminMenu : INavigationProvider {
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public string MenuName { get { return "admin"; } }
|
||||
|
||||
public void GetNavigation(NavigationBuilder builder)
|
||||
{
|
||||
builder
|
||||
.Add(T("Aliases"), "4", item => item.Action("Index", "Admin", new { area = "Orchard.Alias" }).Permission(StandardPermissions.SiteOwner));
|
||||
public void GetNavigation(NavigationBuilder builder) {
|
||||
builder.AddImageSet("aliases");
|
||||
builder.Add(T("Aliases"), "1.4.1", menu => {
|
||||
menu.LinkToFirstChild(true);
|
||||
|
||||
menu.Add(T("Unmanaged"), "1", item => item.Action("IndexUnmanaged", "Admin", new { area = "Orchard.Alias" }).Permission(StandardPermissions.SiteOwner).LocalNav());
|
||||
menu.Add(T("Managed"), "2", item => item.Action("IndexManaged", "Admin", new { area = "Orchard.Alias" }).Permission(StandardPermissions.SiteOwner).LocalNav());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@@ -35,7 +35,7 @@ namespace Orchard.Alias.Controllers {
|
||||
public Localizer T { get; set; }
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public ActionResult Index(AdminIndexOptions options, PagerParameters pagerParameters) {
|
||||
public ActionResult IndexUnmanaged(AdminIndexOptions options, PagerParameters pagerParameters) {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage aliases")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
@@ -45,22 +45,13 @@ namespace Orchard.Alias.Controllers {
|
||||
if (options == null)
|
||||
options = new AdminIndexOptions();
|
||||
|
||||
switch (options.Filter) {
|
||||
case AliasFilter.All:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
var aliases = _aliasHolder.GetMaps().SelectMany(x => x.GetAliases());
|
||||
var aliases = _aliasHolder.GetMaps().SelectMany(x => x.GetAliases()).Where(x => !x.IsManaged);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(options.Search)) {
|
||||
var invariantSearch = options.Search.ToLowerInvariant();
|
||||
aliases = aliases.Where(x => x.Path.ToLowerInvariant().Contains(invariantSearch));
|
||||
}
|
||||
|
||||
aliases = aliases.ToList();
|
||||
|
||||
var pagerShape = Services.New.Pager(pager).TotalItemCount(aliases.Count());
|
||||
|
||||
switch (options.Order) {
|
||||
@@ -84,7 +75,7 @@ namespace Orchard.Alias.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
[FormValueRequired("submit.BulkEdit")]
|
||||
public ActionResult Index(FormCollection input) {
|
||||
public ActionResult IndexUnmanaged(FormCollection input) {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage aliases")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
@@ -105,8 +96,45 @@ namespace Orchard.Alias.Controllers {
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
return RedirectToAction("IndexUnmanaged");
|
||||
}
|
||||
|
||||
return RedirectToAction("Index");
|
||||
public ActionResult IndexManaged(AdminIndexOptions options, PagerParameters pagerParameters) {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage aliases")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var pager = new Pager(Services.WorkContext.CurrentSite, pagerParameters);
|
||||
|
||||
// default options
|
||||
if (options == null)
|
||||
options = new AdminIndexOptions();
|
||||
|
||||
var aliases = _aliasHolder.GetMaps().SelectMany(x => x.GetAliases()).Where(x => x.IsManaged);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(options.Search)) {
|
||||
var invariantSearch = options.Search.ToLowerInvariant();
|
||||
aliases = aliases.Where(x => x.Path.ToLowerInvariant().Contains(invariantSearch));
|
||||
}
|
||||
|
||||
var pagerShape = Services.New.Pager(pager).TotalItemCount(aliases.Count());
|
||||
|
||||
switch (options.Order) {
|
||||
case AliasOrder.Path:
|
||||
aliases = aliases.OrderBy(x => x.Path);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pager.PageSize != 0) {
|
||||
aliases = aliases.Skip(pager.GetStartIndex()).Take(pager.PageSize);
|
||||
}
|
||||
|
||||
var model = new AdminIndexViewModel {
|
||||
Options = options,
|
||||
Pager = pagerShape,
|
||||
AliasEntries = aliases.Select(x => new AliasEntry() { Alias = x, IsChecked = false }).ToList()
|
||||
};
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
public ActionResult Add() {
|
||||
@@ -140,9 +168,9 @@ namespace Orchard.Alias.Controllers {
|
||||
}
|
||||
|
||||
try {
|
||||
_aliasService.Set(aliasPath, routePath, "Custom");
|
||||
_aliasService.Set(aliasPath, routePath, "Custom", false);
|
||||
}
|
||||
catch(Exception ex) {
|
||||
catch (Exception ex) {
|
||||
Services.TransactionManager.Cancel();
|
||||
Services.Notifier.Error(T("An error occured while creating the alias {0}: {1}. Please check the values are correct.", aliasPath, ex.Message));
|
||||
Logger.Error(ex, T("An error occured while creating the alias {0}", aliasPath).Text);
|
||||
@@ -155,7 +183,7 @@ namespace Orchard.Alias.Controllers {
|
||||
|
||||
Services.Notifier.Information(T("Alias {0} created", aliasPath));
|
||||
|
||||
return RedirectToAction("Index");
|
||||
return RedirectToAction("IndexUnmanaged");
|
||||
}
|
||||
|
||||
public ActionResult Edit(string path) {
|
||||
@@ -204,10 +232,9 @@ namespace Orchard.Alias.Controllers {
|
||||
}
|
||||
|
||||
try {
|
||||
_aliasService.Set(aliasPath, routePath, "Custom");
|
||||
_aliasService.Set(aliasPath, routePath, "Custom", false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
catch (Exception ex) {
|
||||
Services.TransactionManager.Cancel();
|
||||
Services.Notifier.Error(T("An error occured while editing the alias '{0}': {1}. Please check the values are correct.", aliasPath, ex.Message));
|
||||
Logger.Error(ex, T("An error occured while creating the alias '{0}'", aliasPath).Text);
|
||||
@@ -226,7 +253,7 @@ namespace Orchard.Alias.Controllers {
|
||||
|
||||
Services.Notifier.Information(T("Alias {0} updated", path));
|
||||
|
||||
return RedirectToAction("Index");
|
||||
return RedirectToAction("IndexUnmanaged");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
@@ -242,11 +269,10 @@ namespace Orchard.Alias.Controllers {
|
||||
|
||||
Services.Notifier.Information(T("Alias {0} deleted", path));
|
||||
|
||||
return this.RedirectLocal(returnUrl, Url.Action("Index"));
|
||||
return this.RedirectLocal(returnUrl, Url.Action("IndexUnmanaged"));
|
||||
}
|
||||
|
||||
private string GetExistingPathForAlias(string aliasPath)
|
||||
{
|
||||
private string GetExistingPathForAlias(string aliasPath) {
|
||||
var routeValues = _aliasService.Get(aliasPath.TrimStart('/', '\\'));
|
||||
if (routeValues == null) return null;
|
||||
|
||||
@@ -255,8 +281,7 @@ namespace Orchard.Alias.Controllers {
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
private bool CheckAndWarnIfAliasExists(string aliasPath)
|
||||
{
|
||||
private bool CheckAndWarnIfAliasExists(string aliasPath) {
|
||||
var routePath = GetExistingPathForAlias(aliasPath);
|
||||
if (routePath == null) return false;
|
||||
|
||||
@@ -267,8 +292,8 @@ namespace Orchard.Alias.Controllers {
|
||||
var changeLink = T("<a href=\"{0}\">change</a>", editUrl);
|
||||
var deleteLink = T("<a href=\"{0}\" itemprop=\"UnsafeUrl RemoveUrl\">delete</a>", deleteUrl);
|
||||
|
||||
Services.Notifier.Error(T("Cannot save alias <i>{0}</i>. It conflicts with existing one pointing to {1}. Please {2} or {3} the existing alias first.",
|
||||
aliasPath,
|
||||
Services.Notifier.Error(T("Cannot save alias <i>{0}</i>. It conflicts with existing one pointing to {1}. Please {2} or {3} the existing alias first.",
|
||||
aliasPath,
|
||||
routePathLink,
|
||||
changeLink,
|
||||
deleteLink));
|
||||
|
@@ -5,8 +5,8 @@ using System.Web.Routing;
|
||||
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);
|
||||
void Set(string aliasPath, RouteValueDictionary routeValues, string aliasSource, bool isManaged = false);
|
||||
void Set(string aliasPath, string routePath, string aliasSource, bool isManaged = false);
|
||||
void Delete(string aliasPath);
|
||||
void Delete(string aliasPath, string aliasSource);
|
||||
/// <summary>
|
||||
@@ -18,8 +18,8 @@ namespace Orchard.Alias {
|
||||
IEnumerable<string> Lookup(RouteValueDictionary routeValues);
|
||||
IEnumerable<string> Lookup(string routePath);
|
||||
|
||||
void Replace(string aliasPath, RouteValueDictionary routeValues, string aliasSource);
|
||||
void Replace(string aliasPath, string routePath, string aliasSource);
|
||||
void Replace(string aliasPath, RouteValueDictionary routeValues, string aliasSource, bool isManaged = false);
|
||||
void Replace(string aliasPath, string routePath, string aliasSource, bool isManaged = false);
|
||||
|
||||
IEnumerable<Tuple<string, RouteValueDictionary>> List();
|
||||
IEnumerable<Tuple<string, RouteValueDictionary, string>> List(string sourceStartsWith);
|
||||
|
@@ -29,12 +29,13 @@ namespace Orchard.Alias.Implementation {
|
||||
var virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
|
||||
|
||||
// Attempt to lookup RouteValues in the alias map
|
||||
IDictionary<string, string> routeValues;
|
||||
//IDictionary<string, string> routeValues;
|
||||
AliasInfo aliasInfo;
|
||||
// TODO: Might as well have the lookup in AliasHolder...
|
||||
if (_aliasMap.TryGetAlias(virtualPath, out routeValues)) {
|
||||
if (_aliasMap.TryGetAlias(virtualPath, out aliasInfo)) {
|
||||
// Construct RouteData from the route values
|
||||
var data = new RouteData(this, _routeHandler);
|
||||
foreach (var routeValue in routeValues) {
|
||||
foreach (var routeValue in aliasInfo.RouteValues) {
|
||||
var key = routeValue.Key;
|
||||
if (key.EndsWith("-"))
|
||||
data.Values.Add(key.Substring(0, key.Length - 1), routeValue.Value);
|
||||
|
@@ -31,18 +31,20 @@ namespace Orchard.Alias.Implementation {
|
||||
return _aliasStorage.Get(aliasPath).ToRouteValueDictionary();
|
||||
}
|
||||
|
||||
public void Set(string aliasPath, RouteValueDictionary routeValues, string aliasSource) {
|
||||
public void Set(string aliasPath, RouteValueDictionary routeValues, string aliasSource, bool isManaged) {
|
||||
_aliasStorage.Set(
|
||||
aliasPath,
|
||||
ToDictionary(routeValues),
|
||||
aliasSource);
|
||||
aliasSource,
|
||||
isManaged);
|
||||
}
|
||||
|
||||
public void Set(string aliasPath, string routePath, string aliasSource) {
|
||||
public void Set(string aliasPath, string routePath, string aliasSource, bool isManaged) {
|
||||
_aliasStorage.Set(
|
||||
aliasPath.TrimStart('/'),
|
||||
ToDictionary(routePath),
|
||||
aliasSource);
|
||||
aliasSource,
|
||||
isManaged);
|
||||
}
|
||||
|
||||
public void Delete(string aliasPath) {
|
||||
@@ -71,15 +73,15 @@ namespace Orchard.Alias.Implementation {
|
||||
return Lookup(ToDictionary(routePath).ToRouteValueDictionary());
|
||||
}
|
||||
|
||||
public void Replace(string aliasPath, RouteValueDictionary routeValues, string aliasSource) {
|
||||
public void Replace(string aliasPath, RouteValueDictionary routeValues, string aliasSource, bool isManaged) {
|
||||
foreach (var lookup in Lookup(routeValues).Where(path => path != aliasPath)) {
|
||||
Delete(lookup, aliasSource);
|
||||
}
|
||||
Set(aliasPath, routeValues, aliasSource);
|
||||
Set(aliasPath, routeValues, aliasSource, isManaged);
|
||||
}
|
||||
|
||||
public void Replace(string aliasPath, string routePath, string aliasSource) {
|
||||
Replace(aliasPath, ToDictionary(routePath).ToRouteValueDictionary(), aliasSource);
|
||||
public void Replace(string aliasPath, string routePath, string aliasSource, bool isManaged) {
|
||||
Replace(aliasPath, ToDictionary(routePath).ToRouteValueDictionary(), aliasSource, isManaged);
|
||||
}
|
||||
|
||||
public IEnumerable<string> Lookup(RouteValueDictionary routeValues) {
|
||||
@@ -89,7 +91,7 @@ namespace Orchard.Alias.Implementation {
|
||||
// the route has an area, lookup in the specific alias map
|
||||
|
||||
var map = _aliasHolder.GetMap(area.ToString());
|
||||
|
||||
|
||||
if (map == null) {
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
@@ -102,7 +104,7 @@ namespace Orchard.Alias.Implementation {
|
||||
|
||||
return new[] { locate.Item2 };
|
||||
}
|
||||
|
||||
|
||||
// no specific area, lookup in all alias maps
|
||||
var result = new List<string>();
|
||||
foreach (var map in _aliasHolder.GetMaps()) {
|
||||
@@ -115,7 +117,7 @@ namespace Orchard.Alias.Implementation {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public IEnumerable<Tuple<string, RouteValueDictionary>> List() {
|
||||
return _aliasStorage.List().Select(item => Tuple.Create(item.Item1, item.Item3.ToRouteValueDictionary()));
|
||||
}
|
||||
@@ -145,21 +147,20 @@ namespace Orchard.Alias.Implementation {
|
||||
private IEnumerable<RouteDescriptor> GetRouteDescriptors() {
|
||||
return _routeProviders
|
||||
.SelectMany(routeProvider => {
|
||||
var routes = new List<RouteDescriptor>();
|
||||
routeProvider.GetRoutes(routes);
|
||||
return routes;
|
||||
})
|
||||
var routes = new List<RouteDescriptor>();
|
||||
routeProvider.GetRoutes(routes);
|
||||
return routes;
|
||||
})
|
||||
.Where(routeDescriptor => !(routeDescriptor.Route is AliasRoute))
|
||||
.OrderByDescending(routeDescriptor => routeDescriptor.Priority);
|
||||
}
|
||||
|
||||
private class StubHttpContext : HttpContextBase {
|
||||
public override HttpRequestBase Request
|
||||
{
|
||||
get{return new StubHttpRequest();}
|
||||
public override HttpRequestBase Request {
|
||||
get { return new StubHttpRequest(); }
|
||||
}
|
||||
|
||||
private class StubHttpRequest : HttpRequestBase {}
|
||||
private class StubHttpRequest : HttpRequestBase { }
|
||||
}
|
||||
}
|
||||
}
|
@@ -5,5 +5,6 @@ namespace Orchard.Alias.Implementation.Holder {
|
||||
public string Area { get; set; }
|
||||
public string Path { get; set; }
|
||||
public IDictionary<string, string> RouteValues { get; set; }
|
||||
public bool IsManaged { get; set; }
|
||||
}
|
||||
}
|
@@ -26,7 +26,7 @@ namespace Orchard.Alias.Implementation.Holder {
|
||||
/// Adds or updates a set of aliases in the tree
|
||||
/// </summary>
|
||||
void SetAliases(IEnumerable<AliasInfo> aliases);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Removes an alias from the tree based on its path
|
||||
/// </summary>
|
||||
|
@@ -9,21 +9,21 @@ using System.Collections.Concurrent;
|
||||
namespace Orchard.Alias.Implementation.Map {
|
||||
public class AliasMap {
|
||||
private readonly string _area;
|
||||
private readonly ConcurrentDictionary<string, IDictionary<string, string>> _aliases;
|
||||
private readonly ConcurrentDictionary<string, AliasInfo> _aliases;
|
||||
private readonly Node _root;
|
||||
|
||||
public AliasMap(string area) {
|
||||
_area = area;
|
||||
_aliases = new ConcurrentDictionary<string, IDictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
|
||||
_aliases = new ConcurrentDictionary<string, AliasInfo>(StringComparer.OrdinalIgnoreCase);
|
||||
_root = new Node();
|
||||
}
|
||||
|
||||
public IEnumerable<AliasInfo> GetAliases() {
|
||||
return _aliases.Select(x => new AliasInfo {Area = _area, Path = x.Key, RouteValues = x.Value});
|
||||
return _aliases.Select(x => new AliasInfo { Area = _area, Path = x.Key, RouteValues = x.Value.RouteValues, IsManaged = x.Value.IsManaged });
|
||||
}
|
||||
|
||||
public bool TryGetAlias(string virtualPath, out IDictionary<string, string> routeValues) {
|
||||
return _aliases.TryGetValue(virtualPath, out routeValues);
|
||||
|
||||
public bool TryGetAlias(string virtualPath, out AliasInfo aliasInfo) {
|
||||
return _aliases.TryGetValue(virtualPath, out aliasInfo);
|
||||
}
|
||||
|
||||
public Tuple<IDictionary<string, object>, string> Locate(RouteValueDictionary routeValues) {
|
||||
@@ -35,11 +35,10 @@ namespace Orchard.Alias.Implementation.Map {
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="AliasInfo"/> intance to add</param>
|
||||
public void Insert(AliasInfo info) {
|
||||
if(info == null) {
|
||||
if (info == null) {
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
_aliases[info.Path] = info.RouteValues;
|
||||
_aliases[info.Path] = info;
|
||||
ExpandTree(_root, info.Path, info.RouteValues);
|
||||
}
|
||||
|
||||
@@ -48,8 +47,8 @@ namespace Orchard.Alias.Implementation.Map {
|
||||
/// </summary>
|
||||
/// <param name="info"></param>
|
||||
public void Remove(AliasInfo info) {
|
||||
IDictionary<string,string> values;
|
||||
_aliases.TryRemove(info.Path, out values);
|
||||
AliasInfo aliasInfo;
|
||||
_aliases.TryRemove(info.Path, out aliasInfo);
|
||||
CollapseTree(_root, info.Path, info.RouteValues);
|
||||
}
|
||||
|
||||
@@ -73,18 +72,18 @@ namespace Orchard.Alias.Implementation.Map {
|
||||
}
|
||||
// Set the path at the end of the tree
|
||||
object takenPath;
|
||||
focus.Paths.TryRemove(path,out takenPath);
|
||||
focus.Paths.TryRemove(path, out takenPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExpandTree(Node root, string path, IDictionary<string, string> routeValues) {
|
||||
foreach(var expanded in Expand(routeValues)) {
|
||||
foreach (var expanded in Expand(routeValues)) {
|
||||
var focus = root;
|
||||
foreach (var routeValue in expanded.OrderBy(kv => kv.Key, StringComparer.InvariantCultureIgnoreCase)) {
|
||||
// See if we already have a stem for this route key (i.e. "controller") and create if not
|
||||
var stem = focus.Stems.GetOrAdd(routeValue.Key,key=>new ConcurrentDictionary<string, Node>(StringComparer.InvariantCultureIgnoreCase));
|
||||
var stem = focus.Stems.GetOrAdd(routeValue.Key, key => new ConcurrentDictionary<string, Node>(StringComparer.InvariantCultureIgnoreCase));
|
||||
// See if the stem has a node for this value (i.e. "Item") and create if not
|
||||
var node = stem.GetOrAdd(routeValue.Value, key=>new Node());
|
||||
var node = stem.GetOrAdd(routeValue.Value, key => new Node());
|
||||
// Keep switching to new node until we reach deepest match
|
||||
// TODO: (PH) Thread safety: at this point something could techincally traverse and find an empty node with a blank path ... not fatal
|
||||
// since it will simply not match and therefore return a default-looking route instead of the aliased one. And the changes of that route
|
||||
@@ -111,23 +110,22 @@ namespace Orchard.Alias.Implementation.Map {
|
||||
|
||||
// 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 => {
|
||||
if (term.Key.EndsWith("-")) {
|
||||
var termKey = term.Key.Substring(0, term.Key.Length - 1);
|
||||
return new[] {
|
||||
if (term.Key.EndsWith("-")) {
|
||||
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
|
||||
new [] { new KeyValuePair<string, string>(termKey, "\u0000") },
|
||||
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
|
||||
var produced = termSets.Aggregate(new[] { empty }.AsEnumerable(), (coords, termSet) => Product(coords, termSet, (coord, term) => coord.Concat(term)));
|
||||
return produced;
|
||||
}
|
||||
|
||||
|
||||
private static Tuple<IDictionary<string, object>, string> Traverse(Node focus, RouteValueDictionary routeValues, string areaName) {
|
||||
|
||||
// Initialize a match variable
|
||||
@@ -191,7 +189,7 @@ namespace Orchard.Alias.Implementation.Map {
|
||||
}
|
||||
|
||||
public ConcurrentDictionary<string, ConcurrentDictionary<string, Node>> Stems { get; set; }
|
||||
public ConcurrentDictionary<string,object> Paths { get; set; }
|
||||
public ConcurrentDictionary<string, object> Paths { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -10,15 +10,15 @@ using Orchard.Validation;
|
||||
|
||||
namespace Orchard.Alias.Implementation.Storage {
|
||||
public interface IAliasStorage : IDependency {
|
||||
void Set(string path, IDictionary<string, string> routeValues, string source);
|
||||
void Set(string path, IDictionary<string, string> routeValues, string source, bool isManaged);
|
||||
IDictionary<string, string> Get(string aliasPath);
|
||||
void Remove(Expression<Func<AliasRecord, bool>> filter);
|
||||
void Remove(string path);
|
||||
void Remove(string path, string aliasSource);
|
||||
void RemoveBySource(string aliasSource);
|
||||
IEnumerable<Tuple<string, string, IDictionary<string, string>, string, int>> List(Expression<Func<AliasRecord, bool>> predicate);
|
||||
IEnumerable<Tuple<string, string, IDictionary<string, string>, string, int>> List();
|
||||
IEnumerable<Tuple<string, string, IDictionary<string, string>, string, int>> List(string sourceStartsWith);
|
||||
IEnumerable<Tuple<string, string, IDictionary<string, string>, string, int, bool>> List(Expression<Func<AliasRecord, bool>> predicate);
|
||||
IEnumerable<Tuple<string, string, IDictionary<string, string>, string, int, bool>> List();
|
||||
IEnumerable<Tuple<string, string, IDictionary<string, string>, string, int, bool>> List(string sourceStartsWith);
|
||||
}
|
||||
|
||||
public class AliasStorage : IAliasStorage {
|
||||
@@ -31,7 +31,7 @@ namespace Orchard.Alias.Implementation.Storage {
|
||||
_aliasHolder = aliasHolder;
|
||||
}
|
||||
|
||||
public void Set(string path, IDictionary<string, string> routeValues, string source) {
|
||||
public void Set(string path, IDictionary<string, string> routeValues, string source, bool isManaged) {
|
||||
if (path == null) {
|
||||
throw new ArgumentNullException("path");
|
||||
}
|
||||
@@ -66,6 +66,7 @@ namespace Orchard.Alias.Implementation.Storage {
|
||||
|
||||
aliasRecord.RouteValues = values.ToString();
|
||||
aliasRecord.Source = source;
|
||||
aliasRecord.IsManaged = isManaged;
|
||||
if (aliasRecord.Action.Id == 0 || aliasRecord.Id == 0) {
|
||||
if (aliasRecord.Action.Id == 0) {
|
||||
_actionRepository.Create(aliasRecord.Action);
|
||||
@@ -78,7 +79,7 @@ namespace Orchard.Alias.Implementation.Storage {
|
||||
}
|
||||
// Transform and push into AliasHolder
|
||||
var dict = ToDictionary(aliasRecord);
|
||||
_aliasHolder.SetAlias(new AliasInfo { Path = dict.Item1, Area = dict.Item2, RouteValues = dict.Item3 });
|
||||
_aliasHolder.SetAlias(new AliasInfo { Path = dict.Item1, Area = dict.Item2, RouteValues = dict.Item3, IsManaged = dict.Item6 });
|
||||
}
|
||||
|
||||
public IDictionary<string, string> Get(string path) {
|
||||
@@ -90,7 +91,7 @@ namespace Orchard.Alias.Implementation.Storage {
|
||||
}
|
||||
|
||||
public void Remove(string path) {
|
||||
Remove(x => x.Path == path && x.Source == path);
|
||||
Remove(x => x.Path == path);
|
||||
}
|
||||
|
||||
public void Remove(string path, string aliasSource) {
|
||||
@@ -109,15 +110,15 @@ namespace Orchard.Alias.Implementation.Storage {
|
||||
// Bulk updates might go wrong if we don't flush.
|
||||
_aliasRepository.Flush();
|
||||
var dict = ToDictionary(aliasRecord);
|
||||
_aliasHolder.RemoveAlias(new AliasInfo() { Path = dict.Item1, Area = dict.Item2, RouteValues = dict.Item3 });
|
||||
_aliasHolder.RemoveAlias(new AliasInfo() { Path = dict.Item1, Area = dict.Item2, RouteValues = dict.Item3, IsManaged = dict.Item6 });
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Tuple<string, string, IDictionary<string, string>, string, int>> List() {
|
||||
public IEnumerable<Tuple<string, string, IDictionary<string, string>, string, int, bool>> List() {
|
||||
return List((Expression<Func<AliasRecord, bool>>)null);
|
||||
}
|
||||
|
||||
public IEnumerable<Tuple<string, string, IDictionary<string, string>, string, int>> List(Expression<Func<AliasRecord, bool>> predicate) {
|
||||
public IEnumerable<Tuple<string, string, IDictionary<string, string>, string, int, bool>> List(Expression<Func<AliasRecord, bool>> predicate) {
|
||||
var table = _aliasRepository.Table;
|
||||
|
||||
if (predicate != null) {
|
||||
@@ -127,11 +128,11 @@ namespace Orchard.Alias.Implementation.Storage {
|
||||
return table.OrderBy(a => a.Id).Select(ToDictionary).ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<Tuple<string, string, IDictionary<string, string>, string, int>> List(string sourceStartsWith) {
|
||||
public IEnumerable<Tuple<string, string, IDictionary<string, string>, string, int, bool>> List(string sourceStartsWith) {
|
||||
return List(a => a.Source.StartsWith(sourceStartsWith));
|
||||
}
|
||||
|
||||
private static Tuple<string, string, IDictionary<string, string>, string, int> ToDictionary(AliasRecord aliasRecord) {
|
||||
private static Tuple<string, string, IDictionary<string, string>, string, int, bool> ToDictionary(AliasRecord aliasRecord) {
|
||||
IDictionary<string, string> routeValues = new Dictionary<string, string>();
|
||||
if (aliasRecord.Action.Area != null) {
|
||||
routeValues.Add("area", aliasRecord.Action.Area);
|
||||
@@ -147,7 +148,7 @@ namespace Orchard.Alias.Implementation.Storage {
|
||||
routeValues.Add(attr.Name.LocalName, attr.Value);
|
||||
}
|
||||
}
|
||||
return Tuple.Create(aliasRecord.Path, aliasRecord.Action.Area, routeValues, aliasRecord.Source, aliasRecord.Id);
|
||||
return Tuple.Create(aliasRecord.Path, aliasRecord.Action.Area, routeValues, aliasRecord.Source, aliasRecord.Id, aliasRecord.IsManaged);
|
||||
}
|
||||
}
|
||||
}
|
@@ -34,7 +34,7 @@ namespace Orchard.Alias.Implementation.Updater {
|
||||
// update the last processed id
|
||||
if (aliases.Any()) {
|
||||
_cursor.Cursor = aliases.Last().Item5;
|
||||
_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, IsManaged = alias.Item6 }));
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
@@ -44,13 +44,13 @@ namespace Orchard.Alias.Implementation.Updater {
|
||||
}
|
||||
|
||||
public class AliasUpdaterEvent : IOrchardShellEvents {
|
||||
|
||||
|
||||
private readonly IAliasHolderUpdater _aliasHolderUpdater;
|
||||
|
||||
public AliasUpdaterEvent(IAliasHolderUpdater aliasHolderUpdater) {
|
||||
_aliasHolderUpdater = aliasHolderUpdater;
|
||||
}
|
||||
|
||||
|
||||
void IOrchardShellEvents.Activated() {
|
||||
_aliasHolderUpdater.Refresh();
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
namespace Orchard.Alias.Implementation.Updater {
|
||||
public interface IAliasUpdateCursor : ISingletonDependency {
|
||||
int Cursor { get; set; }
|
||||
int Cursor { get; set; }
|
||||
}
|
||||
}
|
@@ -65,7 +65,6 @@ namespace Orchard.Alias.Implementation {
|
||||
return key.EndsWith("-", StringComparison.InvariantCulture) ? key.Substring(0, key.Length - 1) : key;
|
||||
}
|
||||
|
||||
|
||||
private static Dictionary<string, string> ToRouteValues(RouteData routeData, string queryString) {
|
||||
var routeValues = routeData.Values
|
||||
.Select(kv => {
|
||||
|
@@ -20,5 +20,13 @@ namespace Orchard.Alias {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int UpdateFrom1() {
|
||||
SchemaBuilder.AlterTable("AliasRecord",
|
||||
table => table
|
||||
.AddColumn<bool>("IsManaged", column => column.WithDefault(false))
|
||||
);
|
||||
return 2;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -75,7 +75,7 @@
|
||||
<Content Include="Views\Admin\Add.cshtml" />
|
||||
<Content Include="Views\Admin\Delete.cshtml" />
|
||||
<Content Include="Views\Admin\Edit.cshtml" />
|
||||
<Content Include="Views\Admin\Index.cshtml" />
|
||||
<Content Include="Views\Admin\IndexUnmanaged.cshtml" />
|
||||
<Content Include="Web.config" />
|
||||
<Compile Include="Implementation\Updater\AliasHolderUpdater.cs" />
|
||||
<Compile Include="Implementation\Updater\AliasUpdateCursor.cs" />
|
||||
@@ -110,12 +110,16 @@
|
||||
<Compile Include="Implementation\Updater\AliasHolderUpdaterTask.cs" />
|
||||
<Compile Include="Implementation\Utils.cs" />
|
||||
<Compile Include="Migrations.cs" />
|
||||
<Compile Include="Recipes\Builders\AliasStep.cs" />
|
||||
<Compile Include="Recipes\Executors\AliasStep.cs" />
|
||||
<Compile Include="Records\ActionRecord.cs" />
|
||||
<Compile Include="Records\AliasRecord.cs" />
|
||||
<Compile Include="Routes.cs" />
|
||||
<Compile Include="ViewModels\AdminIndexViewModel.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Content Include="Views\Admin\IndexManaged.cshtml" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
@@ -123,20 +127,20 @@
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target> -->
|
||||
<Target Name="AfterBuild" DependsOnTargets="AfterBuildCompiler">
|
||||
<PropertyGroup>
|
||||
<AreasManifestDir>$(ProjectDir)\..\Manifests</AreasManifestDir>
|
||||
</PropertyGroup>
|
||||
<!-- If this is an area child project, uncomment the following line:
|
||||
<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Child" AreaPath="$(ProjectDir)" ManifestPath="$(AreasManifestDir)" ContentFiles="@(Content)" />
|
||||
<!-- If this is an area child project, uncomment the following line:
|
||||
<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Child" AreaPath="$(ProjectDir)" ManifestPath="$(AreasManifestDir)" ContentFiles="@(Content)" />
|
||||
-->
|
||||
<!-- If this is an area parent project, uncomment the following lines:
|
||||
<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Parent" AreaPath="$(ProjectDir)" ManifestPath="$(AreasManifestDir)" ContentFiles="@(Content)" />
|
||||
<CopyAreaManifests ManifestPath="$(AreasManifestDir)" CrossCopy="false" RenameViews="true" />
|
||||
<!-- If this is an area parent project, uncomment the following lines:
|
||||
<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Parent" AreaPath="$(ProjectDir)" ManifestPath="$(AreasManifestDir)" ContentFiles="@(Content)" />
|
||||
<CopyAreaManifests ManifestPath="$(AreasManifestDir)" CrossCopy="false" RenameViews="true" />
|
||||
-->
|
||||
</Target>
|
||||
<Target Name="AfterBuildCompiler" Condition="'$(MvcBuildViews)'=='true'">
|
||||
|
@@ -0,0 +1,53 @@
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.Data;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Recipes.Services;
|
||||
using Orchard.Alias.Records;
|
||||
using Orchard.Alias.Implementation.Holder;
|
||||
|
||||
namespace Orchard.Alias.Recipes.Builders {
|
||||
public class AliasStep : RecipeBuilderStep {
|
||||
private readonly IRepository<AliasRecord> _aliasRecordepository;
|
||||
private readonly IAliasHolder _aliasHolder;
|
||||
|
||||
public AliasStep(IRepository<AliasRecord> aliasRecordRepository, IAliasHolder aliasHolder) {
|
||||
_aliasRecordepository = aliasRecordRepository;
|
||||
_aliasHolder = aliasHolder;
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Alias"; }
|
||||
}
|
||||
|
||||
public override LocalizedString DisplayName {
|
||||
get { return T("Aliases"); }
|
||||
}
|
||||
|
||||
public override LocalizedString Description {
|
||||
get { return T("Exports unmanaged aliases."); }
|
||||
}
|
||||
|
||||
public override void Build(BuildContext context) {
|
||||
var aliases = _aliasHolder.GetMaps().SelectMany(m => m.GetAliases()).Where(m => m.IsManaged == false).OrderBy(m => m.Path).ToList();
|
||||
|
||||
if (!aliases.Any())
|
||||
return;
|
||||
|
||||
var root = new XElement("Aliases");
|
||||
context.RecipeDocument.Element("Orchard").Add(root);
|
||||
|
||||
foreach (var alias in aliases) {
|
||||
var aliasElement = new XElement("Alias", new XAttribute("Path", alias.Path));
|
||||
|
||||
var routeValuesElement = new XElement("RouteValues");
|
||||
foreach (var routeValue in alias.RouteValues) {
|
||||
routeValuesElement.Add(new XElement("Add", new XAttribute("Key", routeValue.Key), new XAttribute("Value", routeValue.Value)));
|
||||
}
|
||||
|
||||
aliasElement.Add(routeValuesElement);
|
||||
root.Add(aliasElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.Routing;
|
||||
using System.Linq;
|
||||
using Orchard.Alias;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Recipes.Models;
|
||||
using Orchard.Recipes.Services;
|
||||
|
||||
namespace Orchard.Alias.Recipes.Executors {
|
||||
public class AliasStep : RecipeExecutionStep {
|
||||
private readonly IAliasService _aliasService;
|
||||
|
||||
public AliasStep(
|
||||
IAliasService aliasService,
|
||||
RecipeExecutionLogger logger) : base(logger) {
|
||||
_aliasService = aliasService;
|
||||
}
|
||||
|
||||
public override string Name {
|
||||
get { return "Aliases"; }
|
||||
}
|
||||
|
||||
/*
|
||||
<Aliases>
|
||||
<Alias Path="Profile/Edit" Area="Custom.Profile">
|
||||
<RouteValues>
|
||||
<Add Key="area" Value="Custom.Profile" />
|
||||
<Add Key="controller" Value="Profile" />
|
||||
<Add Key="action" Value="Edit" />
|
||||
</RouteValues>
|
||||
</Alias>
|
||||
*/
|
||||
public override void Execute(RecipeExecutionContext context) {
|
||||
|
||||
foreach (var aliasElement in context.RecipeStep.Step.Elements()) {
|
||||
var aliasPath = aliasElement.Attribute("Path").Value;
|
||||
|
||||
Logger.Information("Importing alias '{0}'.", aliasPath);
|
||||
|
||||
try {
|
||||
var rvd = new RouteValueDictionary();
|
||||
|
||||
var routeValuesElement = aliasElement.Descendants("RouteValues").FirstOrDefault();
|
||||
|
||||
if (routeValuesElement != null) {
|
||||
foreach (var routeValue in routeValuesElement.Descendants("Add")) {
|
||||
rvd.Add(routeValue.Attribute("Key").Value, routeValue.Attribute("Value").Value);
|
||||
}
|
||||
}
|
||||
|
||||
_aliasService.Set(aliasPath, rvd, "Custom", false);
|
||||
}
|
||||
|
||||
catch (Exception ex) {
|
||||
Logger.Error(ex, "Error while processing alias '{0}'.", aliasPath);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -5,5 +5,6 @@
|
||||
public virtual ActionRecord Action { get; set; }
|
||||
public virtual string RouteValues { get; set; }
|
||||
public virtual string Source { get; set; }
|
||||
public virtual bool IsManaged { get; set; }
|
||||
}
|
||||
}
|
@@ -10,7 +10,7 @@ namespace Orchard.Alias {
|
||||
public class Routes : IRouteProvider {
|
||||
private readonly ShellBlueprint _blueprint;
|
||||
private readonly IAliasHolder _aliasHolder;
|
||||
|
||||
|
||||
public Routes(ShellBlueprint blueprint, IAliasHolder aliasHolder) {
|
||||
_blueprint = blueprint;
|
||||
_aliasHolder = aliasHolder;
|
||||
|
@@ -13,6 +13,7 @@ namespace Orchard.Alias.ViewModels {
|
||||
public AliasInfo Alias { get; set; }
|
||||
public bool IsChecked { get; set; }
|
||||
}
|
||||
|
||||
public class AdminIndexOptions {
|
||||
public string Search { get; set; }
|
||||
public AliasOrder Order { get; set; }
|
||||
@@ -25,7 +26,9 @@ namespace Orchard.Alias.ViewModels {
|
||||
}
|
||||
|
||||
public enum AliasFilter {
|
||||
All
|
||||
All,
|
||||
Managed,
|
||||
Unmanaged
|
||||
}
|
||||
|
||||
public enum AliasBulkAction {
|
||||
|
@@ -4,25 +4,25 @@
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@Html.ValidationSummary()
|
||||
<fieldset>
|
||||
<legend>@T("Create Alias")</legend>
|
||||
<div>
|
||||
<label for="aliasPath">@T("Alias Path")</label>
|
||||
@Html.TextBox("aliasPath", (object)ViewBag.Path, new { @class = "text large" })
|
||||
@Html.ValidationMessage("aliasPath")
|
||||
<span class="hint">@T("The path of the alias e.g., my-blog/my-post")</span>
|
||||
</div>
|
||||
<div>
|
||||
<label for="routePath">@T("Route Path")</label>
|
||||
@Html.TextBox("routePath", (object)ViewBag.Route, new { @class = "text medium" })
|
||||
@Html.ValidationMessage("routePath")
|
||||
<span class="hint">@T("The actual route Orchard should call when the path is requested e.g., Blogs/Blog/Item?blogId=18")</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<div>
|
||||
<button class="primaryAction" type="submit">@T("Save")</button>
|
||||
@Html.ActionLink(T("Cancel").ToString(), "Index", new { }, new { @class = "button" })
|
||||
</div>
|
||||
</fieldset>
|
||||
}
|
||||
<fieldset>
|
||||
<legend>@T("Create Alias")</legend>
|
||||
<div>
|
||||
<label for="aliasPath">@T("Alias Path")</label>
|
||||
@Html.TextBox("aliasPath", (object)ViewBag.Path, new { @class = "text large" })
|
||||
@Html.ValidationMessage("aliasPath")
|
||||
<span class="hint">@T("The path of the alias e.g., my-blog/my-post")</span>
|
||||
</div>
|
||||
<div>
|
||||
<label for="routePath">@T("Route Path")</label>
|
||||
@Html.TextBox("routePath", (object)ViewBag.Route, new { @class = "text medium" })
|
||||
@Html.ValidationMessage("routePath")
|
||||
<span class="hint">@T("The actual route Orchard should call when the path is requested e.g., Blogs/Blog/Item?blogId=18")</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<div>
|
||||
<button class="primaryAction" type="submit">@T("Save")</button>
|
||||
@Html.ActionLink(T("Cancel").ToString(), "IndexUnmanaged", new { }, new { @class = "button" })
|
||||
</div>
|
||||
</fieldset>
|
||||
}
|
@@ -3,11 +3,11 @@
|
||||
}
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
<fieldset>
|
||||
<legend>@T("Delete alias")</legend>
|
||||
<p>@T("Removing alias '{0}'. Are you sure?", ViewBag.Path)</p>
|
||||
@Html.Hidden("path")
|
||||
@Html.Hidden("confirmed", true)
|
||||
<button class="primaryAction" type="submit">@T("Yes")</button>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>@T("Delete alias")</legend>
|
||||
<p>@T("Removing alias '{0}'. Are you sure?", ViewBag.Path)</p>
|
||||
@Html.Hidden("path")
|
||||
@Html.Hidden("confirmed", true)
|
||||
<button class="primaryAction" type="submit">@T("Yes")</button>
|
||||
</fieldset>
|
||||
}
|
||||
|
@@ -4,25 +4,25 @@
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@Html.ValidationSummary()
|
||||
<fieldset>
|
||||
<legend>@T("Edit alias")</legend>
|
||||
<div>
|
||||
<label for="aliasPath">@T("Alias Path")</label>
|
||||
@Html.TextBox("aliasPath", null, new { @class = "text large" })
|
||||
@Html.ValidationMessage("aliasPath")
|
||||
<span class="hint">@T("The path of the alias e.g., my-blog/my-post")</span>
|
||||
</div>
|
||||
<div>
|
||||
<label for="routePath">@T("Route Path")</label>
|
||||
@Html.TextBox("routePath", null, new { @class = "text medium" })
|
||||
@Html.ValidationMessage("routePath")
|
||||
<span class="hint">@T("The actual route Orchard should call when the path is requested e.g., Blogs/Blog/Item?blogId=18")</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<div>
|
||||
<button class="primaryAction" type="submit">@T("Save")</button>
|
||||
@Html.ActionLink(T("Cancel").ToString(), "Index", new { }, new { @class = "button" })
|
||||
</div>
|
||||
</fieldset>
|
||||
}
|
||||
<fieldset>
|
||||
<legend>@T("Edit alias")</legend>
|
||||
<div>
|
||||
<label for="aliasPath">@T("Alias Path")</label>
|
||||
@Html.TextBox("aliasPath", null, new { @class = "text large" })
|
||||
@Html.ValidationMessage("aliasPath")
|
||||
<span class="hint">@T("The path of the alias e.g., my-blog/my-post")</span>
|
||||
</div>
|
||||
<div>
|
||||
<label for="routePath">@T("Route Path")</label>
|
||||
@Html.TextBox("routePath", null, new { @class = "text medium" })
|
||||
@Html.ValidationMessage("routePath")
|
||||
<span class="hint">@T("The actual route Orchard should call when the path is requested e.g., Blogs/Blog/Item?blogId=18")</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<div>
|
||||
<button class="primaryAction" type="submit">@T("Save")</button>
|
||||
@Html.ActionLink(T("Cancel").ToString(), "IndexUnmanaged", new { }, new { @class = "button" })
|
||||
</div>
|
||||
</fieldset>
|
||||
}
|
||||
|
@@ -1,92 +0,0 @@
|
||||
@model AdminIndexViewModel
|
||||
|
||||
@using Orchard.Alias
|
||||
@using Orchard.Alias.ViewModels
|
||||
@using Orchard.Environment.Configuration
|
||||
@using Orchard.Utility.Extensions
|
||||
|
||||
@{
|
||||
var urlPrefix = WorkContext.Resolve<ShellSettings>().RequestUrlPrefix;
|
||||
|
||||
Layout.Title = T("Manage Aliases").Text;
|
||||
var aliasService = WorkContext.Resolve<IAliasService>();
|
||||
AdminIndexOptions options = Model.Options;
|
||||
int index = -1;
|
||||
|
||||
var pageSizes = new List<int?>() { 10, 50, 100 };
|
||||
var defaultPageSize = WorkContext.CurrentSite.PageSize;
|
||||
if (!pageSizes.Contains(defaultPageSize)) {
|
||||
pageSizes.Add(defaultPageSize);
|
||||
}
|
||||
}
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@Html.ValidationSummary()
|
||||
<div class="manage">@Html.ActionLink(T("Add new Alias").Text, "Add", new { returnurl = HttpContext.Current.Request.RawUrl }, new { @class = "button primaryAction" })</div>
|
||||
|
||||
<fieldset class="bulk-actions">
|
||||
<label for="publishActions">@T("Actions:")</label>
|
||||
<select id="publishActions" name="@Html.NameOf(m => m.Options.BulkAction)">
|
||||
@Html.SelectOption(options.BulkAction, AliasBulkAction.None, T("Choose action...").ToString())
|
||||
@Html.SelectOption(options.BulkAction, AliasBulkAction.Delete, T("Delete").ToString())
|
||||
</select>
|
||||
<button type="submit" name="submit.BulkEdit" value="@T("Apply")">@T("Apply")</button>
|
||||
</fieldset>
|
||||
<fieldset class="bulk-actions">
|
||||
<label for="filterResults">@T("Sort by:")</label>
|
||||
<select id="filterResults" name="@Html.NameOf(m => m.Options.Order)">
|
||||
@Html.SelectOption(options.Order, AliasOrder.Path, T("Path").ToString())
|
||||
</select>
|
||||
<input type="hidden" name="Page" value="1" />
|
||||
<label for="pageSize">@T("Show:")</label>
|
||||
<select id="pageSize" name="PageSize">
|
||||
@Html.SelectOption((int)Model.Pager.PageSize, 0, T("All").ToString())
|
||||
@foreach(int size in pageSizes.OrderBy(p => p)) {
|
||||
@Html.SelectOption((int)Model.Pager.PageSize, size, size.ToString())
|
||||
}
|
||||
</select>
|
||||
<button type="submit" name="submit.Filter" value="@T("Filter")">@T("Filter")</button>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<table class="items">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="checkbox"><input type="checkbox" class="check-all"/></th>
|
||||
<th scope="col">@T("Alias")</th>
|
||||
<th scope="col">@T("Route")</th>
|
||||
<th scope="col"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
@foreach (var aliasEntry in Model.AliasEntries) {
|
||||
var alias = aliasEntry.Alias;
|
||||
index++;
|
||||
var virtualPathData = aliasService.LookupVirtualPaths(alias.RouteValues.ToRouteValueDictionary(), ViewContext.HttpContext).FirstOrDefault();
|
||||
|
||||
if (virtualPathData == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var url = virtualPathData.VirtualPath;
|
||||
<tr>
|
||||
<td>
|
||||
<input type="hidden" value="@alias.Path" name="@Html.FieldNameFor(m => Model.AliasEntries[index].Alias.Path)"/>
|
||||
<input type="checkbox" value="true" name="@Html.FieldNameFor(m => Model.AliasEntries[index].IsChecked)"/>
|
||||
</td>
|
||||
<td>
|
||||
@Html.Link(alias.Path == String.Empty ? "/" : alias.Path, Href("~/" + urlPrefix + alias.Path))
|
||||
</td>
|
||||
<td>
|
||||
@Html.Link(url, Href("~/" + urlPrefix + "/" + url))
|
||||
</td>
|
||||
<td>
|
||||
@Html.ActionLink(T("Edit").Text, "Edit", new { path = alias.Path == String.Empty ? "/" : alias.Path })
|
||||
|
|
||||
@Html.ActionLink(T("Delete").Text, "Delete", new { path = alias.Path }, new { itemprop = "UnsafeUrl RemoveUrl" })
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
|
||||
@Display(Model.Pager)
|
||||
</fieldset>
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
@model AdminIndexViewModel
|
||||
|
||||
@using Orchard.Alias
|
||||
@using Orchard.Alias.ViewModels
|
||||
@using Orchard.Environment.Configuration
|
||||
@using Orchard.Utility.Extensions
|
||||
|
||||
@{
|
||||
var urlPrefix = WorkContext.Resolve<ShellSettings>().RequestUrlPrefix;
|
||||
|
||||
Layout.Title = T("Manage Aliases").Text;
|
||||
var aliasService = WorkContext.Resolve<IAliasService>();
|
||||
AdminIndexOptions options = Model.Options;
|
||||
int index = -1;
|
||||
|
||||
var pageSizes = new List<int?>() { 10, 50, 100 };
|
||||
var defaultPageSize = WorkContext.CurrentSite.PageSize;
|
||||
if (!pageSizes.Contains(defaultPageSize)) {
|
||||
pageSizes.Add(defaultPageSize);
|
||||
}
|
||||
}
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@Html.ValidationSummary()
|
||||
|
||||
<fieldset class="bulk-actions">
|
||||
<label for="filterResults">@T("Sort by:")</label>
|
||||
<select id="filterResults" name="@Html.NameOf(m => m.Options.Order)">
|
||||
@Html.SelectOption(options.Order, AliasOrder.Path, T("Path").ToString())
|
||||
</select>
|
||||
<input type="hidden" name="Page" value="1" />
|
||||
<label for="pageSize">@T("Show:")</label>
|
||||
<select id="pageSize" name="PageSize">
|
||||
@Html.SelectOption((int)Model.Pager.PageSize, 0, T("All").ToString())
|
||||
@foreach (int size in pageSizes.OrderBy(p => p)) {
|
||||
@Html.SelectOption((int)Model.Pager.PageSize, size, size.ToString())
|
||||
}
|
||||
</select>
|
||||
<button type="submit" name="submit.Filter" value="@T("Filter")">@T("Filter")</button>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<table class="items">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">@T("Alias")</th>
|
||||
<th scope="col">@T("Route")</th>
|
||||
<th scope="col"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
@foreach (var aliasEntry in Model.AliasEntries) {
|
||||
var alias = aliasEntry.Alias;
|
||||
index++;
|
||||
var virtualPathData = aliasService.LookupVirtualPaths(alias.RouteValues.ToRouteValueDictionary(), ViewContext.HttpContext).FirstOrDefault();
|
||||
|
||||
if (virtualPathData == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var url = virtualPathData.VirtualPath;
|
||||
<tr>
|
||||
<td>
|
||||
<input type="hidden" value="@alias.Path" name="@Html.FieldNameFor(m => Model.AliasEntries[index].Alias.Path)" />
|
||||
@Html.Link(alias.Path == String.Empty ? "/" : alias.Path, Href("~/" + urlPrefix + alias.Path))
|
||||
</td>
|
||||
<td>
|
||||
@Html.Link(url, Href("~/" + urlPrefix + "/" + url))
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
|
||||
@Display(Model.Pager)
|
||||
</fieldset>
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
@model AdminIndexViewModel
|
||||
|
||||
@using Orchard.Alias
|
||||
@using Orchard.Alias.ViewModels
|
||||
@using Orchard.Environment.Configuration
|
||||
@using Orchard.Utility.Extensions
|
||||
|
||||
@{
|
||||
var urlPrefix = WorkContext.Resolve<ShellSettings>().RequestUrlPrefix;
|
||||
|
||||
Layout.Title = T("Manage Aliases").Text;
|
||||
var aliasService = WorkContext.Resolve<IAliasService>();
|
||||
AdminIndexOptions options = Model.Options;
|
||||
int index = -1;
|
||||
|
||||
var pageSizes = new List<int?>() { 10, 50, 100 };
|
||||
var defaultPageSize = WorkContext.CurrentSite.PageSize;
|
||||
if (!pageSizes.Contains(defaultPageSize)) {
|
||||
pageSizes.Add(defaultPageSize);
|
||||
}
|
||||
}
|
||||
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@Html.ValidationSummary()
|
||||
<div class="manage">@Html.ActionLink(T("Add new Alias").Text, "Add", new { returnurl = HttpContext.Current.Request.RawUrl }, new { @class = "button primaryAction" })</div>
|
||||
|
||||
<fieldset class="bulk-actions">
|
||||
<label for="publishActions">@T("Actions:")</label>
|
||||
<select id="publishActions" name="@Html.NameOf(m => m.Options.BulkAction)">
|
||||
@Html.SelectOption(options.BulkAction, AliasBulkAction.None, T("Choose action...").ToString())
|
||||
@Html.SelectOption(options.BulkAction, AliasBulkAction.Delete, T("Delete").ToString())
|
||||
</select>
|
||||
<button type="submit" name="submit.BulkEdit" value="@T("Apply")">@T("Apply")</button>
|
||||
</fieldset>
|
||||
<fieldset class="bulk-actions">
|
||||
<label for="filterResults">@T("Sort by:")</label>
|
||||
<select id="filterResults" name="@Html.NameOf(m => m.Options.Order)">
|
||||
@Html.SelectOption(options.Order, AliasOrder.Path, T("Path").ToString())
|
||||
</select>
|
||||
<input type="hidden" name="Page" value="1" />
|
||||
<label for="pageSize">@T("Show:")</label>
|
||||
<select id="pageSize" name="PageSize">
|
||||
@Html.SelectOption((int)Model.Pager.PageSize, 0, T("All").ToString())
|
||||
@foreach (int size in pageSizes.OrderBy(p => p)) {
|
||||
@Html.SelectOption((int)Model.Pager.PageSize, size, size.ToString())
|
||||
}
|
||||
</select>
|
||||
<button type="submit" name="submit.Filter" value="@T("Filter")">@T("Filter")</button>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<table class="items">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="checkbox"><input type="checkbox" class="check-all" /></th>
|
||||
<th scope="col">@T("Alias")</th>
|
||||
<th scope="col">@T("Route")</th>
|
||||
<th scope="col"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
@foreach (var aliasEntry in Model.AliasEntries) {
|
||||
var alias = aliasEntry.Alias;
|
||||
index++;
|
||||
var virtualPathData = aliasService.LookupVirtualPaths(alias.RouteValues.ToRouteValueDictionary(), ViewContext.HttpContext).FirstOrDefault();
|
||||
|
||||
if (virtualPathData == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var url = virtualPathData.VirtualPath;
|
||||
<tr>
|
||||
<td>
|
||||
<input type="hidden" value="@alias.Path" name="@Html.FieldNameFor(m => Model.AliasEntries[index].Alias.Path)" />
|
||||
<input type="checkbox" value="true" name="@Html.FieldNameFor(m => Model.AliasEntries[index].IsChecked)" />
|
||||
</td>
|
||||
<td>
|
||||
@Html.Link(alias.Path == String.Empty ? "/" : alias.Path, Href("~/" + urlPrefix + alias.Path))
|
||||
</td>
|
||||
<td>
|
||||
@Html.Link(url, Href("~/" + urlPrefix + "/" + url))
|
||||
</td>
|
||||
<td>
|
||||
@Html.ActionLink(T("Edit").Text, "Edit", new { path = alias.Path == String.Empty ? "/" : alias.Path })
|
||||
@Html.ActionLink(T("Delete").Text, "Delete", new { path = alias.Path }, new { itemprop = "UnsafeUrl RemoveUrl" })
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
|
||||
@Display(Model.Pager)
|
||||
</fieldset>
|
||||
}
|
@@ -96,7 +96,7 @@ namespace Orchard.Autoroute.Services {
|
||||
|
||||
public void PublishAlias(AutoroutePart part) {
|
||||
var displayRouteValues = _contentManager.GetItemMetadata(part).DisplayRouteValues;
|
||||
_aliasService.Replace(part.DisplayAlias, displayRouteValues, AliasSource);
|
||||
_aliasService.Replace(part.DisplayAlias, displayRouteValues, AliasSource, true);
|
||||
_routeEvents.Routed(part, part.DisplayAlias);
|
||||
}
|
||||
|
||||
@@ -146,7 +146,8 @@ namespace Orchard.Autoroute.Services {
|
||||
if (String.Equals(culture, _cultureManager.GetSiteCulture(), StringComparison.OrdinalIgnoreCase) && !String.IsNullOrWhiteSpace(patternIndex)) {
|
||||
settings.DefaultPatterns.Add(new DefaultPattern { PatternIndex = patternIndex, Culture = culture });
|
||||
return settings.Patterns.Where(x => x.Culture == null).ElementAt(Convert.ToInt32(settings.DefaultPatterns.Where(x => x.Culture == culture).FirstOrDefault().PatternIndex));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
settings.DefaultPatterns.Add(new DefaultPattern { PatternIndex = "0", Culture = culture });
|
||||
return new RoutePattern { Name = "Title", Description = "my-title", Pattern = "{Content.Slug}", Culture = culture };
|
||||
}
|
||||
|
@@ -37,18 +37,18 @@ namespace Orchard.Blogs.Routing {
|
||||
return false;
|
||||
}
|
||||
|
||||
IDictionary<string, string> routeValues;
|
||||
if (!_aliasHolder.GetMap("Orchard.Blogs").TryGetAlias(path, out routeValues)) {
|
||||
AliasInfo aliasInfo;
|
||||
if (!_aliasHolder.GetMap("Orchard.Blogs").TryGetAlias(path, out aliasInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var isBlog =
|
||||
var isBlog =
|
||||
//routeValues.ContainsKey("area") &&
|
||||
//routeValues["area"] == "Orchard.Blogs" &&
|
||||
routeValues.ContainsKey("controller") &&
|
||||
routeValues["controller"] == "Blog" &&
|
||||
routeValues.ContainsKey("action") &&
|
||||
routeValues["action"] == "Item"
|
||||
aliasInfo.RouteValues.ContainsKey("controller") &&
|
||||
aliasInfo.RouteValues["controller"] == "Blog" &&
|
||||
aliasInfo.RouteValues.ContainsKey("action") &&
|
||||
aliasInfo.RouteValues["action"] == "Item"
|
||||
;
|
||||
|
||||
return isBlog;
|
||||
@@ -84,7 +84,7 @@ namespace Orchard.Blogs.Routing {
|
||||
}
|
||||
|
||||
// archive for blog as homepage ?
|
||||
if(path.StartsWith("archive/", StringComparison.OrdinalIgnoreCase)) {
|
||||
if (path.StartsWith("archive/", StringComparison.OrdinalIgnoreCase)) {
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
|
@@ -25,18 +25,19 @@ namespace Orchard.Blogs.Routing {
|
||||
return false;
|
||||
}
|
||||
|
||||
IDictionary<string, string> routeValues;
|
||||
if (!_aliasHolder.GetMap("Orchard.Blogs").TryGetAlias(path, out routeValues)) {
|
||||
AliasInfo aliasInfo;
|
||||
if (!_aliasHolder.GetMap("Orchard.Blogs").TryGetAlias(path, out aliasInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var isBlog =
|
||||
//routeValues.ContainsKey("area") &&
|
||||
//routeValues["area"] == "Orchard.Blogs" &&
|
||||
routeValues.ContainsKey("controller") &&
|
||||
routeValues["controller"] == "Blog" &&
|
||||
routeValues.ContainsKey("action") &&
|
||||
routeValues["action"] == "Item"
|
||||
aliasInfo.RouteValues.ContainsKey("controller") &&
|
||||
aliasInfo.RouteValues["controller"] == "Blog" &&
|
||||
aliasInfo.RouteValues.ContainsKey("action") &&
|
||||
aliasInfo.RouteValues["action"] == "Item"
|
||||
;
|
||||
|
||||
return isBlog;
|
||||
|
@@ -22,11 +22,11 @@ namespace Orchard.Roles.Recipes.Builders {
|
||||
}
|
||||
|
||||
public override LocalizedString Description {
|
||||
get { return T("Exports the user roles."); }
|
||||
get { return T("Exports user roles."); }
|
||||
}
|
||||
|
||||
public override void Build(BuildContext context) {
|
||||
var roles = _roleRecordepository.Table.ToList();
|
||||
var roles = _roleRecordepository.Table.OrderBy(x => x.Name).ToList();
|
||||
|
||||
if (!roles.Any())
|
||||
return;
|
||||
@@ -34,7 +34,7 @@ namespace Orchard.Roles.Recipes.Builders {
|
||||
var root = new XElement("Roles");
|
||||
context.RecipeDocument.Element("Orchard").Add(root);
|
||||
|
||||
foreach (var role in roles.OrderBy(x => x.Name)) {
|
||||
foreach (var role in roles) {
|
||||
root.Add(
|
||||
new XElement("Role",
|
||||
new XAttribute("Name", role.Name),
|
||||
|
Reference in New Issue
Block a user