Skip to content

Commit 5b6edac

Browse files
BenedekFarkasMatteoPiovanellidomonkosgabor
authored
#7412: Cloning overrides for some content parts, including deep clone for records (Lombiq Technologies: ORCH-204) (#8854)
Co-authored-by: matteo.piovanelli <matteo.piovanelli@laser-group.com> Co-authored-by: Gábor Domonkos <gabor.domonkos@lombiq.com>
1 parent d8537f1 commit 5b6edac

File tree

37 files changed

+532
-291
lines changed

37 files changed

+532
-291
lines changed

src/Orchard.Web/Core/Containers/Drivers/ContainablePartDriver.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
using System.Xml;
55
using Orchard.ContentManagement;
66
using Orchard.ContentManagement.Drivers;
7+
using Orchard.ContentManagement.Handlers;
78
using Orchard.Core.Common.Models;
89
using Orchard.Core.Containers.Models;
910
using Orchard.Core.Containers.Services;
1011
using Orchard.Core.Containers.Settings;
1112
using Orchard.Core.Containers.ViewModels;
1213
using Orchard.Localization;
13-
using Orchard.ContentManagement.Handlers;
1414

1515
namespace Orchard.Core.Containers.Drivers {
1616
public class ContainablePartDriver : ContentPartDriver<ContainablePart> {
@@ -96,5 +96,9 @@ protected override void Importing(ContainablePart part, ImportContentContext con
9696
protected override void Exporting(ContainablePart part, ExportContentContext context) {
9797
context.Element(part.PartDefinition.Name).SetAttributeValue("Position", part.Position);
9898
}
99+
100+
protected override void Cloning(ContainablePart originalPart, ContainablePart clonePart, CloneContentContext context) {
101+
clonePart.Position = originalPart.Position;
102+
}
99103
}
100104
}

src/Orchard.Web/Core/Containers/Drivers/ContainerPartDriver.cs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Web.Routing;
45
using System.Xml;
56
using Orchard.ContentManagement;
67
using Orchard.ContentManagement.Drivers;
@@ -11,12 +12,11 @@
1112
using Orchard.Core.Containers.Models;
1213
using Orchard.Core.Containers.Services;
1314
using Orchard.Core.Containers.ViewModels;
15+
using Orchard.Core.Feeds;
1416
using Orchard.Localization;
15-
using Orchard.UI.Notify;
16-
using System.Web.Routing;
1717
using Orchard.Settings;
18-
using Orchard.Core.Feeds;
1918
using Orchard.UI.Navigation;
19+
using Orchard.UI.Notify;
2020

2121
namespace Orchard.Core.Containers.Drivers {
2222
public class ContainerPartDriver : ContentPartDriver<ContainerPart> {
@@ -57,7 +57,7 @@ protected override DriverResult Display(ContainerPart part, string displayType,
5757

5858
var metadata = container.ContentManager.GetItemMetadata(container);
5959
if (metadata != null) {
60-
_feedManager.Register(metadata.DisplayText, "rss", new RouteValueDictionary {{"containerid", container.Id}});
60+
_feedManager.Register(metadata.DisplayText, "rss", new RouteValueDictionary { { "containerid", container.Id } });
6161
}
6262

6363
// Retrieving pager parameters.
@@ -179,5 +179,17 @@ protected override void Exporting(ContainerPart part, ExportContentContext conte
179179
context.Element(part.PartDefinition.Name).SetAttributeValue("AdminMenuImageSet", part.AdminMenuImageSet);
180180
context.Element(part.PartDefinition.Name).SetAttributeValue("ItemCount", part.ItemCount);
181181
}
182+
183+
protected override void Cloning(ContainerPart originalPart, ContainerPart clonePart, CloneContentContext context) {
184+
clonePart.ItemContentTypes = originalPart.ItemContentTypes;
185+
clonePart.ItemsShown = originalPart.ItemsShown;
186+
clonePart.Paginated = originalPart.Paginated;
187+
clonePart.PageSize = originalPart.PageSize;
188+
clonePart.ShowOnAdminMenu = originalPart.ShowOnAdminMenu;
189+
clonePart.AdminMenuText = originalPart.AdminMenuText;
190+
clonePart.AdminMenuPosition = originalPart.AdminMenuPosition;
191+
clonePart.AdminMenuImageSet = originalPart.AdminMenuImageSet;
192+
clonePart.ItemCount = originalPart.ItemCount;
193+
}
182194
}
183195
}

src/Orchard.Web/Core/Contents/Controllers/AdminController.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -436,15 +436,15 @@ private ActionResult EditPOST(int id, string returnUrl, Func<ContentItem, bool>
436436
}
437437

438438
[HttpPost]
439-
public ActionResult Clone(int id) {
439+
public ActionResult Clone(int id, string returnUrl) {
440440
var originalContentItem = _contentManager.GetLatest(id);
441441

442442
if (!Services.Authorizer.Authorize(Permissions.ViewContent, originalContentItem, T("You do not have permission to view existing content.")))
443443
return new HttpUnauthorizedResult();
444444

445445
if (!Services.Authorizer.Authorize(Permissions.CreateContent, originalContentItem, T("Couldn't clone content")))
446-
return new HttpUnauthorizedResult();
447-
446+
return new HttpUnauthorizedResult();
447+
448448
// pass a dummy content to the authorization check to check for "own" variations
449449
var dummyContent = _contentManager.New(originalContentItem.ContentType);
450450

@@ -461,8 +461,13 @@ public ActionResult Clone(int id) {
461461
? T("The content has been cloned as a draft.")
462462
: T("The {0} has been cloned as a draft.", originalContentItem.TypeDefinition.DisplayName));
463463

464-
var adminRouteValues = _contentManager.GetItemMetadata(cloneContentItem).AdminRouteValues;
465-
return RedirectToRoute(adminRouteValues);
464+
if (string.IsNullOrWhiteSpace(returnUrl)) {
465+
var adminRouteValues = _contentManager.GetItemMetadata(cloneContentItem).AdminRouteValues;
466+
return RedirectToRoute(adminRouteValues);
467+
}
468+
else {
469+
return this.RedirectLocal(returnUrl, () => RedirectToAction("List"));
470+
}
466471
}
467472

468473
[HttpPost]

src/Orchard.Web/Core/Contents/Views/Parts.Contents.Clone.SummaryAdmin.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
@if (Authorizer.Authorize(Permissions.CreateContent, contentPart)) {
77
<ul class="action-links action-links-item">
88
<li class="action-link">
9-
<a href="@Url.Action("Clone", "Admin", new { Id = Model.ContentItem.Id, ReturnUrl = Request.RawUrl, Area = "Contents" })" itemprop="UnsafeUrl">@T("Clone")</a>
9+
<a href="@Url.Action("Clone", "Admin", new { Id = Model.ContentItem.Id, Area = "Contents" })" itemprop="UnsafeUrl">@T("Clone")</a>
1010
</li>
1111
</ul>
1212
}

src/Orchard.Web/Core/Contents/Views/Parts.Contents.Publish.SummaryAdmin.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
</li>
2727
}
2828
<li class="action-link">
29-
@Html.ActionLink(T("Clone").Text, "Clone", "Admin", new { Id = contentItem.Id, ReturnUrl = Request.RawUrl, Area = "Contents" }, new { itemprop = "UnsafeUrl" })
29+
@Html.ActionLink(T("Clone").Text, "Clone", "Admin", new { Id = contentItem.Id, Area = "Contents" }, new { itemprop = "UnsafeUrl" })
3030
</li>
3131
}
3232

src/Orchard.Web/Core/Navigation/Controllers/AdminController.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,12 @@ public ActionResult CreateMenuItemPost(string id, int menuId, string returnUrl)
231231
_contentManager.Create(contentItem);
232232

233233
menuPart.Menu = menu;
234-
menuPart.MenuPosition = Position.GetNext(_navigationManager.BuildMenu(menu));
235234

236235
var model = _contentManager.UpdateEditor(contentItem, this);
237236

237+
// This needs to be called after UpdateEditor for INavigationFilters not to operate with stale data.
238+
menuPart.MenuPosition = Position.GetNext(_navigationManager.BuildMenu(menu));
239+
238240
if (!ModelState.IsValid) {
239241
_transactionManager.Cancel();
240242
return View(model);

src/Orchard.Web/Core/Navigation/Drivers/AdminMenuPartDriver.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using Orchard.ContentManagement;
33
using Orchard.ContentManagement.Drivers;
4+
using Orchard.ContentManagement.Handlers;
45
using Orchard.Core.Navigation.Models;
56
using Orchard.Core.Navigation.Settings;
67
using Orchard.Localization;
@@ -94,5 +95,11 @@ protected override void Exporting(AdminMenuPart part, ContentManagement.Handlers
9495
context.Element(part.PartDefinition.Name).SetAttributeValue("AdminMenuPosition", part.AdminMenuPosition);
9596
context.Element(part.PartDefinition.Name).SetAttributeValue("OnAdminMenu", part.OnAdminMenu);
9697
}
98+
99+
protected override void Cloning(AdminMenuPart originalPart, AdminMenuPart clonePart, CloneContentContext context) {
100+
clonePart.AdminMenuText = originalPart.AdminMenuText;
101+
clonePart.AdminMenuPosition = originalPart.AdminMenuPosition;
102+
clonePart.OnAdminMenu = originalPart.OnAdminMenu;
103+
}
97104
}
98105
}

src/Orchard.Web/Core/Navigation/Drivers/MenuItemPartDriver.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Orchard.ContentManagement;
22
using Orchard.ContentManagement.Drivers;
3+
using Orchard.ContentManagement.Handlers;
34
using Orchard.Core.Navigation.Models;
45
using Orchard.Security;
56

@@ -29,9 +30,7 @@ protected override DriverResult Editor(MenuItemPart part, IUpdateModel updater,
2930
if (!_authorizationService.TryCheckAccess(Permissions.ManageMenus, currentUser, menu)) // tests if the current user has permissions to manage that specific menu
3031
return null;
3132

32-
if (updater != null) {
33-
updater.TryUpdateModel(part, Prefix, null, null);
34-
}
33+
updater?.TryUpdateModel(part, Prefix, null, null);
3534

3635
return Editor(part, shapeHelper);
3736
}
@@ -50,5 +49,9 @@ protected override void Importing(MenuItemPart part, ContentManagement.Handlers.
5049
protected override void Exporting(MenuItemPart part, ContentManagement.Handlers.ExportContentContext context) {
5150
context.Element(part.PartDefinition.Name).SetAttributeValue("Url", part.Url);
5251
}
52+
53+
protected override void Cloning(MenuItemPart originalPart, MenuItemPart clonePart, CloneContentContext context) {
54+
clonePart.Url = originalPart.Url;
55+
}
5356
}
5457
}

src/Orchard.Web/Core/Navigation/Drivers/MenuPartDriver.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Linq;
22
using Orchard.ContentManagement;
33
using Orchard.ContentManagement.Drivers;
4+
using Orchard.ContentManagement.Handlers;
45
using Orchard.Core.Navigation.Models;
56
using Orchard.Core.Navigation.Services;
67
using Orchard.Core.Navigation.ViewModels;
@@ -17,8 +18,8 @@ public class MenuPartDriver : ContentPartDriver<MenuPart> {
1718
private readonly IMenuService _menuService;
1819

1920
public MenuPartDriver(
20-
IAuthorizationService authorizationService,
21-
INavigationManager navigationManager,
21+
IAuthorizationService authorizationService,
22+
INavigationManager navigationManager,
2223
IOrchardServices orchardServices,
2324
IMenuService menuService) {
2425
_authorizationService = authorizationService;
@@ -58,7 +59,7 @@ protected override DriverResult Editor(MenuPart part, dynamic shapeHelper) {
5859
protected override DriverResult Editor(MenuPart part, IUpdateModel updater, dynamic shapeHelper) {
5960
var model = new MenuPartViewModel();
6061

61-
if(updater.TryUpdateModel(model, Prefix, null, null)) {
62+
if (updater.TryUpdateModel(model, Prefix, null, null)) {
6263
var menu = model.OnMenu ? _orchardServices.ContentManager.Get(model.CurrentMenuId) : null;
6364

6465
if (!_authorizationService.TryCheckAccess(Permissions.ManageMenus, _orchardServices.WorkContext.CurrentUser, menu))
@@ -103,7 +104,7 @@ protected override void Importing(MenuPart part, ContentManagement.Handlers.Impo
103104

104105
protected override void Exporting(MenuPart part, ContentManagement.Handlers.ExportContentContext context) {
105106
// is it on a menu ?
106-
if(part.Menu == null) {
107+
if (part.Menu == null) {
107108
return;
108109
}
109110

@@ -114,5 +115,11 @@ protected override void Exporting(MenuPart part, ContentManagement.Handlers.Expo
114115
context.Element(part.PartDefinition.Name).SetAttributeValue("MenuText", part.MenuText);
115116
context.Element(part.PartDefinition.Name).SetAttributeValue("MenuPosition", part.MenuPosition);
116117
}
118+
119+
protected override void Cloning(MenuPart originalPart, MenuPart clonePart, CloneContentContext context) {
120+
clonePart.MenuText = originalPart.MenuText;
121+
clonePart.MenuPosition = originalPart.MenuPosition;
122+
clonePart.Menu = originalPart.Menu;
123+
}
117124
}
118125
}

src/Orchard.Web/Core/Navigation/Drivers/MenuWidgetPartDriver.cs

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
using Orchard.Localization;
1212
using Orchard.UI.Navigation;
1313
using Orchard.Utility.Extensions;
14-
using Orchard.ContentManagement.Utilities;
1514

1615
namespace Orchard.Core.Navigation.Drivers {
1716
public class MenuWidgetPartDriver : ContentPartDriver<MenuWidgetPart> {
@@ -41,10 +40,10 @@ protected override string Prefix {
4140
}
4241

4342
protected override DriverResult Display(MenuWidgetPart part, string displayType, dynamic shapeHelper) {
44-
return ContentShape( "Parts_MenuWidget", () => {
43+
return ContentShape("Parts_MenuWidget", () => {
4544
var menu = _menuService.GetMenu(part.MenuContentItemId);
46-
47-
if(menu == null) {
45+
46+
if (menu == null) {
4847
return null;
4948
}
5049

@@ -57,9 +56,9 @@ protected override DriverResult Display(MenuWidgetPart part, string displayType,
5756
}
5857

5958
var localized = new List<MenuItem>();
60-
foreach(var menuItem in menuItems) {
59+
foreach (var menuItem in menuItems) {
6160
// if there is no associated content, it as culture neutral
62-
if(menuItem.Content == null) {
61+
if (menuItem.Content == null) {
6362
localized.Add(menuItem);
6463
}
6564

@@ -73,7 +72,7 @@ protected override DriverResult Display(MenuWidgetPart part, string displayType,
7372

7473
var request = _workContextAccessor.GetContext().HttpContext.Request;
7574
var routeData = request.RequestContext.RouteData;
76-
var selectedPath = NavigationHelper.SetSelectedPath(menuItems, request, routeData);
75+
var selectedPath = NavigationHelper.SetSelectedPath(menuItems, request, routeData);
7776
var menuShape = shapeHelper.Menu();
7877

7978
if (part.Breadcrumb) {
@@ -135,9 +134,9 @@ protected override DriverResult Display(MenuWidgetPart part, string displayType,
135134
}
136135

137136
// limit the number of levels to display (down from and including the start level)
138-
if(part.Levels > 0) {
137+
if (part.Levels > 0) {
139138
var current = topLevelItems.ToList();
140-
for (var i = 1; current.Any() && i < part.Levels; i++ ) {
139+
for (var i = 1; current.Any() && i < part.Levels; i++) {
141140
var temp = new List<MenuItem>();
142141
foreach (var menuItem in current) {
143142
temp.AddRange(menuItem.Items);
@@ -147,7 +146,7 @@ protected override DriverResult Display(MenuWidgetPart part, string displayType,
147146
// cut the sub-levels beneath any menu items that are at the lowest level being displayed
148147
foreach (var menuItem in current) {
149148
menuItem.Items = Enumerable.Empty<MenuItem>();
150-
}
149+
}
151150
}
152151
menuItems = topLevelItems;
153152
}
@@ -160,29 +159,29 @@ protected override DriverResult Display(MenuWidgetPart part, string displayType,
160159
return shapeHelper.Parts_MenuWidget(Menu: menuShape);
161160
});
162161
}
163-
162+
164163
protected override DriverResult Editor(MenuWidgetPart part, dynamic shapeHelper) {
165164
return ContentShape("Parts_MenuWidget_Edit", () => {
166165

167-
var model = new MenuWidgetViewModel {
168-
CurrentMenuId = part.MenuContentItemId,
169-
StartLevel = part.StartLevel,
170-
StopLevel = part.Levels,
171-
Breadcrumb = part.Breadcrumb,
172-
AddCurrentPage = part.AddCurrentPage,
173-
AddHomePage = part.AddHomePage,
174-
ShowFullMenu = part.ShowFullMenu,
175-
Menus = _menuService.GetMenus(),
176-
};
177-
178-
return shapeHelper.EditorTemplate(TemplateName: "Parts.MenuWidget.Edit", Model: model, Prefix: Prefix);
179-
});
166+
var model = new MenuWidgetViewModel {
167+
CurrentMenuId = part.MenuContentItemId,
168+
StartLevel = part.StartLevel,
169+
StopLevel = part.Levels,
170+
Breadcrumb = part.Breadcrumb,
171+
AddCurrentPage = part.AddCurrentPage,
172+
AddHomePage = part.AddHomePage,
173+
ShowFullMenu = part.ShowFullMenu,
174+
Menus = _menuService.GetMenus(),
175+
};
176+
177+
return shapeHelper.EditorTemplate(TemplateName: "Parts.MenuWidget.Edit", Model: model, Prefix: Prefix);
178+
});
180179
}
181180

182181
protected override DriverResult Editor(MenuWidgetPart part, IUpdateModel updater, dynamic shapeHelper) {
183182
var model = new MenuWidgetViewModel();
184183

185-
if(updater.TryUpdateModel(model, Prefix, null, null)) {
184+
if (updater.TryUpdateModel(model, Prefix, null, null)) {
186185
part.StartLevel = model.StartLevel;
187186
part.Levels = model.StopLevel;
188187
part.Breadcrumb = model.Breadcrumb;
@@ -223,5 +222,14 @@ protected override void Exporting(MenuWidgetPart part, ExportContentContext cont
223222
context.Element(part.PartDefinition.Name).SetAttributeValue("ShowFullMenu", part.ShowFullMenu);
224223
}
225224

225+
protected override void Cloning(MenuWidgetPart originalPart, MenuWidgetPart clonePart, CloneContentContext context) {
226+
clonePart.StartLevel = originalPart.StartLevel;
227+
clonePart.Levels = originalPart.Levels;
228+
clonePart.Breadcrumb = originalPart.Breadcrumb;
229+
clonePart.AddCurrentPage = originalPart.AddCurrentPage;
230+
clonePart.AddHomePage = originalPart.AddHomePage;
231+
clonePart.ShowFullMenu = originalPart.ShowFullMenu;
232+
clonePart.MenuContentItemId = originalPart.MenuContentItemId;
233+
}
226234
}
227235
}

0 commit comments

Comments
 (0)