Content cloning and translation

Fixes #5535, #5089, #4983, #4970, #4538, #5031
This commit is contained in:
Thierry Fleury
2016-05-27 18:44:26 +02:00
committed by Sébastien Ros
parent 147b4fd05b
commit 87a394854d
34 changed files with 260 additions and 173 deletions

View File

@@ -11,6 +11,7 @@ using Orchard.Core.Common.ViewModels;
using Orchard.Services;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.ContentManagement.Handlers;
namespace Orchard.Core.Common.Drivers {
public class BodyPartDriver : ContentPartDriver<BodyPart> {
@@ -75,6 +76,10 @@ namespace Orchard.Core.Common.Drivers {
context.Element(part.PartDefinition.Name).SetAttributeValue("Text", part.Text);
}
protected override void Cloning(BodyPart originalPart, BodyPart clonePart, CloneContentContext context) {
clonePart.Text = originalPart.Text;
}
private static BodyEditorViewModel BuildEditorViewModel(BodyPart part,RequestContext requestContext) {
return new BodyEditorViewModel {
BodyPart = part,

View File

@@ -123,5 +123,9 @@ namespace Orchard.Core.Common.Drivers {
.SetAttributeValue("ModifiedUtc", XmlConvert.ToString(part.ModifiedUtc.Value, XmlDateTimeSerializationMode.Utc));
}
}
protected override void Cloning(CommonPart originalPart, CommonPart clonePart, CloneContentContext context) {
clonePart.Container = originalPart.Container;
}
}
}

View File

@@ -88,6 +88,10 @@ namespace Orchard.Core.Common.Drivers {
context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Text", field.Value);
}
protected override void Cloning(ContentPart part, TextField originalField, TextField cloneField, CloneContentContext context) {
cloneField.Value = originalField.Value;
}
protected override void Describe(DescribeMembersContext context) {
context
.Member(null, typeof(string), T("Value"), T("The text associated with the field."))

View File

@@ -383,26 +383,24 @@ namespace Orchard.Core.Contents.Controllers {
}
[HttpPost]
public ActionResult Clone(int id, string returnUrl) {
var contentItem = _contentManager.GetLatest(id);
public ActionResult Clone(int id) {
var originalContentItem = _contentManager.GetLatest(id);
if (contentItem == null)
return HttpNotFound();
if (!Services.Authorizer.Authorize(Permissions.EditContent, contentItem, T("Couldn't clone content")))
if (!Services.Authorizer.Authorize(Permissions.ViewContent, originalContentItem, T("Couldn't open original content")))
return new HttpUnauthorizedResult();
try {
Services.ContentManager.Clone(contentItem);
}
catch (InvalidOperationException) {
Services.Notifier.Warning(T("Could not clone the content item."));
return this.RedirectLocal(returnUrl, () => RedirectToAction("List"));
}
// pass a dummy content to the authorization check to check for "own" variations
var dummyContent = _contentManager.New(originalContentItem.ContentType);
if (!Services.Authorizer.Authorize(Permissions.EditContent, dummyContent, T("Couldn't create clone content")))
return new HttpUnauthorizedResult();
var cloneContentItem = _contentManager.Clone(originalContentItem);
Services.Notifier.Success(T("Successfully cloned. The clone was saved as a draft."));
return this.RedirectLocal(returnUrl, () => RedirectToAction("List"));
var adminRouteValues = _contentManager.GetItemMetadata(cloneContentItem).AdminRouteValues;
return RedirectToRoute(adminRouteValues);
}
[HttpPost]

View File

@@ -1,10 +1,9 @@
@using Orchard.ContentManagement
@using Orchard.Core.Contents
@using Orchard.Utility.Extensions
@{
ContentPart contentPart = Model.ContentPart;
}
@if (Authorizer.Authorize(Permissions.EditContent, contentPart)) {
<a href="@Url.Action("Clone", "Admin", new { Id = Model.ContentItem.Id, ReturnUrl = Request.ToUrlString(), Area = "Contents" })" itemprop="UnsafeUrl">@T("Clone")</a>
<a href="@Url.Action("Clone", "Admin", new { Id = Model.ContentItem.Id, Area = "Contents" })" itemprop="UnsafeUrl">@T("Clone")</a>
@T(" | ")
}

View File

@@ -52,5 +52,9 @@ namespace Orchard.Core.Title.Drivers {
protected override void Exporting(TitlePart part, ExportContentContext context) {
context.Element(part.PartDefinition.Name).SetAttributeValue("Title", part.Title);
}
protected override void Cloning(TitlePart originalPart, TitlePart clonePart, CloneContentContext context) {
clonePart.Title = originalPart.Title;
}
}
}

View File

@@ -6,6 +6,7 @@ using Orchard.Comments.Settings;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using System.Collections.Generic;
using Orchard.ContentManagement.Handlers;
namespace Orchard.Comments.Drivers {
public class CommentsPartDriver : ContentPartDriver<CommentsPart> {
@@ -110,7 +111,7 @@ namespace Orchard.Comments.Drivers {
return Editor(part, shapeHelper);
}
protected override void Importing(CommentsPart part, ContentManagement.Handlers.ImportContentContext context) {
protected override void Importing(CommentsPart part, ImportContentContext context) {
// Don't do anything if the tag is not specified.
if (context.Data.Element(part.PartDefinition.Name) == null) {
return;
@@ -129,10 +130,16 @@ namespace Orchard.Comments.Drivers {
);
}
protected override void Exporting(CommentsPart part, ContentManagement.Handlers.ExportContentContext context) {
protected override void Exporting(CommentsPart part, ExportContentContext context) {
context.Element(part.PartDefinition.Name).SetAttributeValue("CommentsShown", part.CommentsShown);
context.Element(part.PartDefinition.Name).SetAttributeValue("CommentsActive", part.CommentsActive);
context.Element(part.PartDefinition.Name).SetAttributeValue("ThreadedComments", part.ThreadedComments);
}
protected override void Cloning(CommentsPart originalPart, CommentsPart clonePart, CloneContentContext context) {
clonePart.CommentsShown = originalPart.CommentsShown;
clonePart.CommentsActive = originalPart.CommentsActive;
// ThreadedComments will be overrided with settings default
}
}
}

View File

@@ -7,6 +7,7 @@ using Orchard.ContentManagement.Handlers;
using Orchard.ContentPicker.ViewModels;
using Orchard.Localization;
using Orchard.Utility.Extensions;
using Orchard.ContentPicker.Fields;
namespace Orchard.ContentPicker.Drivers {
public class ContentPickerFieldDriver : ContentFieldDriver<Fields.ContentPickerField> {
@@ -98,6 +99,10 @@ namespace Orchard.ContentPicker.Drivers {
}
}
protected override void Cloning(ContentPart part, ContentPickerField originalField, ContentPickerField cloneField, CloneContentContext context) {
cloneField.Ids = originalField.Ids;
}
protected override void Describe(DescribeMembersContext context) {
context
.Member(null, typeof(string), T("Ids"), T("A formatted list of the ids, e.g., {1},{42}"));

View File

@@ -66,6 +66,10 @@ namespace Orchard.Fields.Drivers {
context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value);
}
protected override void Cloning(ContentPart part, BooleanField originalField, BooleanField cloneField, CloneContentContext context) {
cloneField.Value = originalField.Value;
}
protected override void Describe(DescribeMembersContext context) {
context
.Member(null, typeof(Boolean), T("Value"), T("The boolean value of the field."))

View File

@@ -174,6 +174,10 @@ namespace Orchard.Fields.Drivers {
context.Element(GetPrefix(field, part)).SetAttributeValue("Value", XmlConvert.ToString(value, XmlDateTimeSerializationMode.Utc));
}
protected override void Cloning(ContentPart part, DateTimeField originalField, DateTimeField cloneField, CloneContentContext context) {
cloneField.DateTime = originalField.DateTime;
}
protected override void Describe(DescribeMembersContext context) {
context
.Member(null, typeof(DateTime), T("Value"), T("The date and time value of the field."))

View File

@@ -67,6 +67,10 @@ namespace Orchard.Fields.Drivers {
context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value);
}
protected override void Cloning(ContentPart part, EnumerationField originalField, EnumerationField cloneField, CloneContentContext context) {
cloneField.Value = originalField.Value;
}
protected override void Describe(DescribeMembersContext context) {
context
.Member(null, typeof(string), T("Value"), T("The selected values of the field."))

View File

@@ -65,6 +65,10 @@ namespace Orchard.Fields.Drivers {
context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value);
}
protected override void Cloning(ContentPart part, InputField originalField, InputField cloneField, CloneContentContext context) {
cloneField.Value = originalField.Value;
}
protected override void Describe(DescribeMembersContext context) {
context
.Member(null, typeof(string), T("Value"), T("The value of the field."))

View File

@@ -78,6 +78,12 @@ namespace Orchard.Fields.Drivers {
}
}
protected override void Cloning(ContentPart part, LinkField originalField, LinkField cloneField, CloneContentContext context) {
cloneField.Text = originalField.Text;
cloneField.Value = originalField.Value;
cloneField.Target = originalField.Target;
}
protected override void Describe(DescribeMembersContext context) {
context
.Member("Text", typeof(string), T("Text"), T("The text of the link."))

View File

@@ -110,6 +110,10 @@ namespace Orchard.Fields.Drivers {
context.Element(field.FieldDefinition.Name + "." + field.Name).SetAttributeValue("Value", field.Value.Value.ToString(CultureInfo.InvariantCulture));
}
protected override void Cloning(ContentPart part, NumericField originalField, NumericField cloneField, CloneContentContext context) {
cloneField.Value = originalField.Value;
}
protected override void Describe(DescribeMembersContext context) {
context
.Member(null, typeof(decimal), T("Value"), T("The value of the field."))

View File

@@ -213,5 +213,10 @@ namespace Orchard.Layouts.Drivers {
var layoutDataString = JsonConvert.SerializeObject(layoutData, Formatting.None);
return layoutDataString;
}
protected override void Cloning(LayoutPart originalPart, LayoutPart clonePart, CloneContentContext context) {
clonePart.LayoutData = originalPart.LayoutData;
clonePart.TemplateId = originalPart.TemplateId;
}
}
}

View File

@@ -1,28 +1,29 @@
using System;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.Core.Contents.Settings;
using Orchard.ContentManagement;
using Orchard.Core.Contents;
using Orchard.DisplayManagement;
using Orchard.Localization.Models;
using Orchard.Localization.Services;
using Orchard.Localization.ViewModels;
using Orchard.Mvc;
using Orchard.UI.Notify;
using System;
using System.Web.Mvc;
namespace Orchard.Localization.Controllers {
namespace Orchard.Localization.Controllers
{
[ValidateInput(false)]
public class AdminController : Controller, IUpdateModel {
public class AdminController : Controller {
private readonly IContentManager _contentManager;
private readonly ILocalizationService _localizationService;
private readonly ICultureManager _cultureManager;
public AdminController(
IOrchardServices orchardServices,
IContentManager contentManager,
ILocalizationService localizationService,
ICultureManager cultureManager,
IShapeFactory shapeFactory) {
_contentManager = contentManager;
_localizationService = localizationService;
_cultureManager = cultureManager;
T = NullLocalizer.Instance;
Services = orchardServices;
Shape = shapeFactory;
@@ -32,16 +33,20 @@ namespace Orchard.Localization.Controllers {
public Localizer T { get; set; }
public IOrchardServices Services { get; set; }
[HttpPost]
public ActionResult Translate(int id, string to) {
var masterContentItem = _contentManager.Get(id, VersionOptions.Latest);
if (masterContentItem == null)
return HttpNotFound();
if (!Services.Authorizer.Authorize(Permissions.ViewContent, masterContentItem, T("Couldn't open original content")))
return new HttpUnauthorizedResult();
var masterLocalizationPart = masterContentItem.As<LocalizationPart>();
if (masterLocalizationPart == null)
return HttpNotFound();
// Check is current item stll exists, and redirect.
// Check if current item still exists, and redirect.
var existingTranslation = _localizationService.GetLocalizedContentItem(masterContentItem, to);
if (existingTranslation != null) {
var existingTranslationMetadata = _contentManager.GetItemMetadata(existingTranslation);
@@ -50,76 +55,24 @@ namespace Orchard.Localization.Controllers {
existingTranslationMetadata.EditorRouteValues);
}
var contentItemTranslation = _contentManager.New<LocalizationPart>(masterContentItem.ContentType);
contentItemTranslation.MasterContentItem = masterContentItem;
// pass a dummy content to the authorization check to check for "own" variations
var dummyContent = _contentManager.New(masterContentItem.ContentType);
var content = _contentManager.BuildEditor(contentItemTranslation);
return View(content);
}
var contentItemTranslation = _contentManager.Clone(masterContentItem);
[HttpPost, ActionName("Translate")]
[FormValueRequired("submit.Save")]
public ActionResult TranslatePOST(int id) {
return TranslatePOST(id, contentItem => {
if (!contentItem.Has<IPublishingControlAspect>() && !contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
Services.ContentManager.Publish(contentItem);
});
}
if (!Services.Authorizer.Authorize(Permissions.EditContent, contentItemTranslation, T("Couldn't create translated content")))
return new HttpUnauthorizedResult();
[HttpPost, ActionName("Translate")]
[FormValueRequired("submit.Publish")]
public ActionResult TranslateAndPublishPOST(int id) {
return TranslatePOST(id, contentItem => Services.ContentManager.Publish(contentItem));
}
public ActionResult TranslatePOST(int id, Action<ContentItem> conditionallyPublish) {
var masterContentItem = _contentManager.Get(id, VersionOptions.Latest);
if (masterContentItem == null)
return HttpNotFound();
var masterLocalizationPart = masterContentItem.As<LocalizationPart>();
if (masterLocalizationPart == null)
return HttpNotFound();
var model = new EditLocalizationViewModel();
TryUpdateModel(model, "Localization");
var existingTranslation = _localizationService.GetLocalizedContentItem(masterContentItem, model.SelectedCulture);
if (existingTranslation != null) {
var existingTranslationMetadata = _contentManager.GetItemMetadata(existingTranslation);
return RedirectToAction(
Convert.ToString(existingTranslationMetadata.EditorRouteValues["action"]),
existingTranslationMetadata.EditorRouteValues);
var localizationPart = contentItemTranslation.As<LocalizationPart>();
if(localizationPart != null) {
localizationPart.MasterContentItem = masterContentItem;
localizationPart.Culture = string.IsNullOrWhiteSpace(to) ? null : _cultureManager.GetCultureByName(to);
}
var contentItemTranslation = _contentManager
.Create<LocalizationPart>(masterContentItem.ContentType, VersionOptions.Draft, part => {
part.MasterContentItem = masterContentItem;
});
Services.Notifier.Success(T("Successfully cloned. The translated content was saved as a draft."));
var content = _contentManager.UpdateEditor(contentItemTranslation, this);
if (!ModelState.IsValid) {
Services.TransactionManager.Cancel();
return View(content);
}
conditionallyPublish(contentItemTranslation.ContentItem);
Services.Notifier.Success(T("Created content item translation."));
var metadata = _contentManager.GetItemMetadata(contentItemTranslation);
return RedirectToAction(Convert.ToString(metadata.EditorRouteValues["action"]), metadata.EditorRouteValues);
}
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
}
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
ModelState.AddModelError(key, errorMessage.ToString());
var adminRouteValues = _contentManager.GetItemMetadata(contentItemTranslation).AdminRouteValues;
return RedirectToRoute(adminRouteValues);
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Linq;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.Localization.Models;
using Orchard.Localization.Services;
using Orchard.Localization.ViewModels;
@@ -89,25 +90,23 @@ namespace Orchard.Localization.Drivers {
private IEnumerable<LocalizationPart> GetDisplayLocalizations(LocalizationPart part, VersionOptions versionOptions) {
return _localizationService.GetLocalizations(part.ContentItem, versionOptions)
.Where(c => c.Culture != null)
.Select(c => {
var localized = c.ContentItem.As<LocalizationPart>();
if (localized.Culture == null)
localized.Culture = _cultureManager.GetCultureByName(_cultureManager.GetSiteCulture());
return c;
}).ToList();
}
private IEnumerable<LocalizationPart> GetEditorLocalizations(LocalizationPart part) {
return _localizationService.GetLocalizations(part.ContentItem, VersionOptions.Latest)
.Where(c => c.Culture != null)
.Select(c => {
var localized = c.ContentItem.As<LocalizationPart>();
if (localized.Culture == null)
localized.Culture = _cultureManager.GetCultureByName(_cultureManager.GetSiteCulture());
return c;
}).ToList();
}
protected override void Importing(LocalizationPart part, ContentManagement.Handlers.ImportContentContext context) {
protected override void Importing(LocalizationPart part, ImportContentContext context) {
// Don't do anything if the tag is not specified.
if (context.Data.Element(part.PartDefinition.Name) == null) {
return;
@@ -131,7 +130,7 @@ namespace Orchard.Localization.Drivers {
});
}
protected override void Exporting(LocalizationPart part, ContentManagement.Handlers.ExportContentContext context) {
protected override void Exporting(LocalizationPart part, ExportContentContext context) {
if (part.MasterContentItem != null) {
var masterContentItemIdentity = _contentManager.GetItemMetadata(part.MasterContentItem).Identity;
context.Element(part.PartDefinition.Name).SetAttributeValue("MasterContentItem", masterContentItemIdentity.ToString());
@@ -141,5 +140,9 @@ namespace Orchard.Localization.Drivers {
context.Element(part.PartDefinition.Name).SetAttributeValue("Culture", part.Culture.Culture);
}
}
protected override void Cloned(LocalizationPart originalPart, LocalizationPart clonePart, CloneContentContext context) {
clonePart.Culture = originalPart.Culture;
}
}
}

View File

@@ -31,7 +31,7 @@ namespace Orchard.Localization.Handlers {
protected static void PropertySetHandlers(ActivatedContentContext context, LocalizationPart localizationPart) {
localizationPart.CultureField.Setter(cultureRecord => {
localizationPart.Record.CultureId = cultureRecord.Id;
localizationPart.Record.CultureId = cultureRecord != null ? cultureRecord.Id : 0;
return cultureRecord;
});

View File

@@ -135,9 +135,6 @@
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="Views\Admin\Translate.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\EditorTemplates\Parts\Localization.ContentTranslations.Edit.cshtml" />
</ItemGroup>

View File

@@ -1,8 +0,0 @@
@{
Layout.Title = T("Translate Content").ToString();
}
@using (Html.BeginFormAntiForgeryPost()) {
@Html.ValidationSummary()
@Display(Model)
}

View File

@@ -6,58 +6,60 @@
<fieldset class="localization culture-selection">
<label for="@Html.FieldIdFor(m => m.SelectedCulture)">@T("Content Localization")</label>
<div>
@*Brand new content item*@
@if (Model.ContentItem.ContentItem.Id == 0) {
if (Model.MasterContentItem == null) {
@T("This is the <em>{0}</em> variation of the content",
BuildSelectedCultureList(
Html.FieldIdFor(m => m.SelectedCulture),
Html.FieldNameFor(m => m.SelectedCulture),
Model.MissingCultures,
Model.SelectedCulture))
@if (!string.IsNullOrEmpty(Model.SelectedCulture))
{
@T("This is the <em>{0}</em> variation of the content",
Html.Encode(Model.SelectedCulture))
if (Model.ContentLocalizations.Localizations.Any())
{
<dl class="content-localization">
<dt>@T("Other translations:")</dt>
<dd class="content-localizations">
@Html.UnorderedList(Model.ContentLocalizations.Localizations, (c, i) =>
Html.ItemEditLink(c.Culture.Culture, c), "localizations")
</dd>
</dl>
}
else {
@T("This is the <em>{0}</em> variation of {1}",
if (Model.MissingCultures.Any())
{
var contentItemId = Model.MasterContentItem != null ? Model.MasterContentItem.Id : Model.ContentItem.Id;
<div class="add-localization">@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = contentItemId }, new { itemprop = "UnsafeUrl" })</div>
}
@Html.Hidden(Html.FieldNameFor(m => m.SelectedCulture), Model.SelectedCulture)
}
else if (Model.MasterContentItem != null)
{
@T("This is the <em>{0}</em> variation of {1}",
BuildSelectedCultureList(
Html.FieldIdFor(m => m.SelectedCulture),
Html.FieldNameFor(m => m.SelectedCulture),
Model.MissingCultures,
Model.SelectedCulture),
Html.ItemEditLink(Model.MasterContentItem))
if (Model.ContentLocalizations.Localizations.Any())
{
<dl class="content-localization">
<dt>@T("Other translations:")</dt>
<dd class="content-localizations">
@Html.UnorderedList(Model.ContentLocalizations.Localizations, (c, i) =>
Html.ItemEditLink(c.Culture.Culture, c), "localizations")
</dd>
</dl>
}
}
@if (Model.ContentItem.ContentItem.Id > 0) {
if (string.IsNullOrEmpty(Model.SelectedCulture)) {
@T("This content currently has no culture associated to it, please select a culture to associate to this piece of content: {0}",
BuildSelectedCultureList(
Html.FieldIdFor(m => m.SelectedCulture),
Html.FieldNameFor(m => m.SelectedCulture),
Model.MissingCultures,
Model.SelectedCulture))
}
else {
@T("This is the <em>{0}</em> variation of the content",
Html.Encode(Model.SelectedCulture))
if (Model.ContentLocalizations.Localizations.Any()) {
<dl class="content-localization">
<dt>@T("Other translations:")</dt>
<dd class="content-localizations">
@Html.UnorderedList(Model.ContentLocalizations.Localizations, (c, i) =>
Html.ItemEditLink(c.Culture.Culture, c), "localizations")
</dd>
</dl>
}
if (Model.MissingCultures.Any()) {
var contentItemId = Model.MasterContentItem != null ? Model.MasterContentItem.Id : Model.ContentItem.Id;
<div class="add-localization">@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new {area = "Orchard.Localization", id = contentItemId}, null)</div>
}
@Html.Hidden(Html.FieldNameFor(m => m.SelectedCulture), Model.SelectedCulture)
}
else
{
@T("This is the <em>{0}</em> variation of the content",
BuildSelectedCultureList(
Html.FieldIdFor(m => m.SelectedCulture),
Html.FieldNameFor(m => m.SelectedCulture),
Model.MissingCultures,
Model.SelectedCulture))
}
</div>
</fieldset>

View File

@@ -16,7 +16,7 @@ var localizationLinks = Html.UnorderedList(localizations, (c, i) => Html.ItemEdi
}
@if (Model.Culture != null && !((IEnumerable<string>)Model.SiteCultures).All(c => c == Model.Culture || localizations.Any(l => c == l.Culture.Culture)))
{
<div class="add-localization">@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = Model.Id }, null)</div>
<div class="add-localization">@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = Model.Id }, new { itemprop = "UnsafeUrl" })</div>
}
</div>
}

View File

@@ -7,6 +7,7 @@ using Orchard.ContentManagement.Handlers;
using Orchard.MediaLibrary.ViewModels;
using Orchard.Localization;
using Orchard.Utility.Extensions;
using Orchard.MediaLibrary.Fields;
namespace Orchard.MediaLibrary.Drivers {
public class MediaLibraryPickerFieldDriver : ContentFieldDriver<Fields.MediaLibraryPickerField> {
@@ -95,6 +96,10 @@ namespace Orchard.MediaLibrary.Drivers {
}
}
protected override void Cloning(ContentPart part, MediaLibraryPickerField originalField, MediaLibraryPickerField cloneField, CloneContentContext context) {
cloneField.Ids = originalField.Ids;
}
protected override void Describe(DescribeMembersContext context) {
context
.Member(null, typeof(string), T("Ids"), T("A formatted list of the ids, e.g., {1},{42}"));

View File

@@ -341,6 +341,17 @@ namespace Orchard.Projections.Drivers {
}
}
protected override void Cloning(ProjectionPart originalPart, ProjectionPart clonePart, CloneContentContext context) {
clonePart.Record.Items = originalPart.Record.Items;
clonePart.Record.ItemsPerPage = originalPart.Record.ItemsPerPage;
clonePart.Record.Skip = originalPart.Record.Skip;
clonePart.Record.PagerSuffix = originalPart.Record.PagerSuffix;
clonePart.Record.MaxItems = originalPart.Record.MaxItems;
clonePart.Record.DisplayPager = originalPart.Record.DisplayPager;
clonePart.Record.QueryPartRecord = originalPart.Record.QueryPartRecord;
clonePart.Record.LayoutRecord = originalPart.Record.LayoutRecord;
}
private class ViewDataContainer : IViewDataContainer {
public ViewDataDictionary ViewData { get; set; }
}

View File

@@ -89,5 +89,9 @@ namespace Orchard.Tags.Drivers {
protected override void Exporting(TagsPart part, ExportContentContext context) {
context.Element(part.PartDefinition.Name).SetAttributeValue("Tags", String.Join(",", part.CurrentTags));
}
protected override void Cloning(TagsPart originalPart, TagsPart clonePart, CloneContentContext context) {
clonePart.CurrentTags = originalPart.CurrentTags;
}
}
}

View File

@@ -141,6 +141,10 @@ namespace Orchard.Taxonomies.Drivers {
_taxonomyService.UpdateTerms(part.ContentItem, terms.Select(x => x.As<TermPart>()), field.Name);
}
protected override void Cloning(ContentPart part, TaxonomyField originalField, TaxonomyField cloneField, CloneContentContext context) {
_taxonomyService.UpdateTerms(context.CloneContentItem, originalField.Terms, cloneField.Name);
}
private TermPart GetOrCreateTerm(TermEntry entry, int taxonomyId, TaxonomyField field) {
var term = default(TermPart);