Merge pull request #1146 from umbraco/temp-U4-7641
U4-7641 - enable content type copy
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
@@ -22,9 +23,9 @@ using Umbraco.Web.Models;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
//TODO: We'll need to be careful about the security on this controller, when we start implementing
|
||||
//TODO: We'll need to be careful about the security on this controller, when we start implementing
|
||||
// methods to modify content types we'll need to enforce security on the individual methods, we
|
||||
// cannot put security on the whole controller because things like
|
||||
// cannot put security on the whole controller because things like
|
||||
// GetAllowedChildren, GetPropertyTypeScaffold, GetAllPropertyTypeAliases are required for content editing.
|
||||
|
||||
/// <summary>
|
||||
@@ -129,7 +130,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
|
||||
[UmbracoTreeAuthorize(
|
||||
Constants.Trees.DocumentTypes, Constants.Trees.Content,
|
||||
Constants.Trees.DocumentTypes, Constants.Trees.Content,
|
||||
Constants.Trees.MediaTypes, Constants.Trees.Media,
|
||||
Constants.Trees.MemberTypes, Constants.Trees.Members)]
|
||||
public ContentPropertyDisplay GetPropertyTypeScaffold(int id)
|
||||
@@ -166,13 +167,13 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
|
||||
public HttpResponseMessage PostCreateContainer(int parentId, string name)
|
||||
{
|
||||
var result = Services.ContentTypeService.CreateContentTypeContainer(parentId, name, Security.CurrentUser.Id);
|
||||
|
||||
return result
|
||||
? Request.CreateResponse(HttpStatusCode.OK, result.Result) //return the id
|
||||
? Request.CreateResponse(HttpStatusCode.OK, result.Result) //return the id
|
||||
: Request.CreateNotificationValidationErrorResponse(result.Exception.Message);
|
||||
}
|
||||
|
||||
@@ -203,7 +204,7 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
//make sure the template alias is set on the default and allowed template so we can map it back
|
||||
ctSave.DefaultTemplate = template.Alias;
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -231,7 +232,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
else
|
||||
ct = new ContentType(parentId);
|
||||
|
||||
|
||||
ct.Icon = "icon-document";
|
||||
|
||||
var dto = Mapper.Map<IContentType, DocumentTypeDisplay>(ct);
|
||||
@@ -302,7 +303,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move the media type
|
||||
/// Move the content type
|
||||
/// </summary>
|
||||
/// <param name="move"></param>
|
||||
/// <returns></returns>
|
||||
@@ -314,6 +315,17 @@ namespace Umbraco.Web.Editors
|
||||
doMove: (type, i) => Services.ContentTypeService.MoveContentType(type, i));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Copy the content type
|
||||
/// </summary>
|
||||
/// <param name="copy"></param>
|
||||
/// <returns></returns>
|
||||
public HttpResponseMessage PostCopy(MoveOrCopy copy)
|
||||
{
|
||||
return PerformCopy(
|
||||
copy,
|
||||
getContentType: i => Services.ContentTypeService.GetContentType(i),
|
||||
doCopy: (type, i) => Services.ContentTypeService.CopyContentType(type, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ namespace Umbraco.Web.Editors
|
||||
/// <summary>
|
||||
/// Am abstract API controller providing functionality used for dealing with content and media types
|
||||
/// </summary>
|
||||
[PluginController("UmbracoApi")]
|
||||
[PluginController("UmbracoApi")]
|
||||
[PrefixlessBodyModelValidator]
|
||||
public abstract class ContentTypeControllerBase : UmbracoAuthorizedJsonController
|
||||
{
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
protected ContentTypeControllerBase()
|
||||
: this(UmbracoContext.Current)
|
||||
{
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -61,17 +61,17 @@ namespace Umbraco.Web.Editors
|
||||
/// This is required because in the case of creating/modifying a content type because new property types being added to it are not yet persisted so cannot
|
||||
/// be looked up via the db, they need to be passed in.
|
||||
/// </param>
|
||||
/// <param name="contentTypeId"></param>
|
||||
/// <param name="contentTypeId"></param>
|
||||
/// <returns></returns>
|
||||
protected IEnumerable<Tuple<EntityBasic, bool>> PerformGetAvailableCompositeContentTypes(int contentTypeId,
|
||||
UmbracoObjectTypes type,
|
||||
protected IEnumerable<Tuple<EntityBasic, bool>> PerformGetAvailableCompositeContentTypes(int contentTypeId,
|
||||
UmbracoObjectTypes type,
|
||||
string[] filterContentTypes,
|
||||
string[] filterPropertyTypes)
|
||||
{
|
||||
IContentTypeComposition source = null;
|
||||
|
||||
//below is all ported from the old doc type editor and comes with the same weaknesses /insanity / magic
|
||||
|
||||
|
||||
IContentTypeComposition[] allContentTypes;
|
||||
|
||||
switch (type)
|
||||
@@ -132,7 +132,7 @@ namespace Umbraco.Web.Editors
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected string TranslateItem(string text)
|
||||
{
|
||||
@@ -155,7 +155,7 @@ namespace Umbraco.Web.Editors
|
||||
Action<TContentTypeSave> beforeCreateNew = null)
|
||||
where TContentType : class, IContentTypeComposition
|
||||
where TContentTypeDisplay : ContentTypeCompositionDisplay
|
||||
where TContentTypeSave : ContentTypeSave<TPropertyType>
|
||||
where TContentTypeSave : ContentTypeSave<TPropertyType>
|
||||
where TPropertyType : PropertyTypeBasic
|
||||
{
|
||||
var ctId = Convert.ToInt32(contentTypeSave.Id);
|
||||
@@ -187,10 +187,10 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
group.Properties = group.Properties.Where(x => x.Alias.IsNullOrWhiteSpace() == false).ToList();
|
||||
}
|
||||
|
||||
|
||||
if (ctId > 0)
|
||||
{
|
||||
//its an update to an existing content type
|
||||
//its an update to an existing content type
|
||||
|
||||
//This mapping will cause a lot of content type validation to occur which we need to deal with
|
||||
try
|
||||
@@ -216,7 +216,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
beforeCreateNew(contentTypeSave);
|
||||
}
|
||||
|
||||
|
||||
//check if the type is trying to allow type 0 below itself - id zero refers to the currently unsaved type
|
||||
//always filter these 0 types out
|
||||
var allowItselfAsChild = false;
|
||||
@@ -227,12 +227,12 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
|
||||
//save as new
|
||||
|
||||
|
||||
TContentType newCt = null;
|
||||
try
|
||||
{
|
||||
//This mapping will cause a lot of content type validation to occur which we need to deal with
|
||||
newCt = Mapper.Map<TContentType>(contentTypeSave);
|
||||
newCt = Mapper.Map<TContentType>(contentTypeSave);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -260,9 +260,9 @@ namespace Umbraco.Web.Editors
|
||||
return newCt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Change the sort order for media
|
||||
/// Move
|
||||
/// </summary>
|
||||
/// <param name="move"></param>
|
||||
/// <param name="getContentType"></param>
|
||||
@@ -293,7 +293,52 @@ namespace Umbraco.Web.Editors
|
||||
case MoveOperationStatusType.FailedParentNotFound:
|
||||
return Request.CreateResponse(HttpStatusCode.NotFound);
|
||||
case MoveOperationStatusType.FailedCancelledByEvent:
|
||||
//returning an object of INotificationModel will ensure that any pending
|
||||
//returning an object of INotificationModel will ensure that any pending
|
||||
// notification messages are added to the response.
|
||||
return Request.CreateValidationErrorResponse(new SimpleNotificationModel());
|
||||
case MoveOperationStatusType.FailedNotAllowedByPath:
|
||||
var notificationModel = new SimpleNotificationModel();
|
||||
notificationModel.AddErrorNotification(Services.TextService.Localize("moveOrCopy/notAllowedByPath"), "");
|
||||
return Request.CreateValidationErrorResponse(notificationModel);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move
|
||||
/// </summary>
|
||||
/// <param name="move"></param>
|
||||
/// <param name="getContentType"></param>
|
||||
/// <param name="doCopy"></param>
|
||||
/// <returns></returns>
|
||||
protected HttpResponseMessage PerformCopy<TContentType>(
|
||||
MoveOrCopy move,
|
||||
Func<int, TContentType> getContentType,
|
||||
Func<TContentType, int, Attempt<OperationStatus<TContentType, MoveOperationStatusType>>> doCopy)
|
||||
where TContentType : IContentTypeComposition
|
||||
{
|
||||
var toMove = getContentType(move.Id);
|
||||
if (toMove == null)
|
||||
{
|
||||
return Request.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
var result = doCopy(toMove, move.ParentId);
|
||||
if (result.Success)
|
||||
{
|
||||
var copy = result.Result.Entity;
|
||||
var response = Request.CreateResponse(HttpStatusCode.OK);
|
||||
response.Content = new StringContent(copy.Path, Encoding.UTF8, "application/json");
|
||||
return response;
|
||||
}
|
||||
|
||||
switch (result.Result.StatusType)
|
||||
{
|
||||
case MoveOperationStatusType.FailedParentNotFound:
|
||||
return Request.CreateResponse(HttpStatusCode.NotFound);
|
||||
case MoveOperationStatusType.FailedCancelledByEvent:
|
||||
//returning an object of INotificationModel will ensure that any pending
|
||||
// notification messages are added to the response.
|
||||
return Request.CreateValidationErrorResponse(new SimpleNotificationModel());
|
||||
case MoveOperationStatusType.FailedNotAllowedByPath:
|
||||
@@ -312,14 +357,14 @@ namespace Umbraco.Web.Editors
|
||||
/// <param name="composition"></param>
|
||||
/// <returns></returns>
|
||||
private HttpResponseException CreateCompositionValidationExceptionIfInvalid<TContentTypeSave, TPropertyType, TContentTypeDisplay>(TContentTypeSave contentTypeSave, IContentTypeComposition composition)
|
||||
where TContentTypeSave : ContentTypeSave<TPropertyType>
|
||||
where TContentTypeSave : ContentTypeSave<TPropertyType>
|
||||
where TPropertyType : PropertyTypeBasic
|
||||
where TContentTypeDisplay : ContentTypeCompositionDisplay
|
||||
{
|
||||
var validateAttempt = Services.ContentTypeService.ValidateComposition(composition);
|
||||
if (validateAttempt == false)
|
||||
{
|
||||
//if it's not successful then we need to return some model state for the property aliases that
|
||||
//if it's not successful then we need to return some model state for the property aliases that
|
||||
// are duplicated
|
||||
var invalidPropertyAliases = validateAttempt.Result.Distinct();
|
||||
AddCompositionValidationErrors<TContentTypeSave, TPropertyType>(contentTypeSave, invalidPropertyAliases);
|
||||
@@ -340,7 +385,7 @@ namespace Umbraco.Web.Editors
|
||||
/// <param name="invalidPropertyAliases"></param>
|
||||
/// <returns></returns>
|
||||
private void AddCompositionValidationErrors<TContentTypeSave, TPropertyType>(TContentTypeSave contentTypeSave, IEnumerable<string> invalidPropertyAliases)
|
||||
where TContentTypeSave : ContentTypeSave<TPropertyType>
|
||||
where TContentTypeSave : ContentTypeSave<TPropertyType>
|
||||
where TPropertyType : PropertyTypeBasic
|
||||
{
|
||||
foreach (var propertyAlias in invalidPropertyAliases)
|
||||
@@ -369,8 +414,8 @@ namespace Umbraco.Web.Editors
|
||||
private HttpResponseException CreateInvalidCompositionResponseException<TContentTypeDisplay, TContentType, TContentTypeSave, TPropertyType>(
|
||||
Exception ex, TContentTypeSave contentTypeSave, TContentType ct, int ctId)
|
||||
where TContentType : class, IContentTypeComposition
|
||||
where TContentTypeDisplay : ContentTypeCompositionDisplay
|
||||
where TContentTypeSave : ContentTypeSave<TPropertyType>
|
||||
where TContentTypeDisplay : ContentTypeCompositionDisplay
|
||||
where TContentTypeSave : ContentTypeSave<TPropertyType>
|
||||
where TPropertyType : PropertyTypeBasic
|
||||
{
|
||||
InvalidCompositionException invalidCompositionException = null;
|
||||
@@ -431,7 +476,7 @@ namespace Umbraco.Web.Editors
|
||||
(_cultureDictionary = CultureDictionaryFactoryResolver.Current.Factory.CreateDictionary());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ using Umbraco.Web.Models;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
//TODO: We'll need to be careful about the security on this controller, when we start implementing
|
||||
//TODO: We'll need to be careful about the security on this controller, when we start implementing
|
||||
// methods to modify content types we'll need to enforce security on the individual methods, we
|
||||
// cannot put security on the whole controller because things like GetAllowedChildren are required for content editing.
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Umbraco.Web.Editors
|
||||
public MediaTypeController(UmbracoContext umbracoContext)
|
||||
: base(umbracoContext)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
public int GetCount()
|
||||
@@ -112,7 +112,7 @@ namespace Umbraco.Web.Editors
|
||||
contentType = x.Item1,
|
||||
allowed = x.Item2
|
||||
});
|
||||
return Request.CreateResponse(result);
|
||||
return Request.CreateResponse(result);
|
||||
}
|
||||
|
||||
public MediaTypeDisplay GetEmpty(int parentId)
|
||||
@@ -129,8 +129,8 @@ namespace Umbraco.Web.Editors
|
||||
/// Returns all member types
|
||||
/// </summary>
|
||||
public IEnumerable<ContentTypeBasic> GetAll()
|
||||
{
|
||||
|
||||
{
|
||||
|
||||
return Services.ContentTypeService.GetAllMediaTypes()
|
||||
.Select(Mapper.Map<IMediaType, ContentTypeBasic>);
|
||||
}
|
||||
@@ -154,7 +154,7 @@ namespace Umbraco.Web.Editors
|
||||
var result = Services.ContentTypeService.CreateMediaTypeContainer(parentId, name, Security.CurrentUser.Id);
|
||||
|
||||
return result
|
||||
? Request.CreateResponse(HttpStatusCode.OK, result.Result) //return the id
|
||||
? Request.CreateResponse(HttpStatusCode.OK, result.Result) //return the id
|
||||
: Request.CreateNotificationValidationErrorResponse(result.Exception.Message);
|
||||
}
|
||||
|
||||
@@ -228,10 +228,22 @@ namespace Umbraco.Web.Editors
|
||||
public HttpResponseMessage PostMove(MoveOrCopy move)
|
||||
{
|
||||
return PerformMove(
|
||||
move,
|
||||
getContentType: i => Services.ContentTypeService.GetMediaType(i),
|
||||
doMove: (type, i) => Services.ContentTypeService.MoveMediaType(type, i));
|
||||
move,
|
||||
getContentType: i => Services.ContentTypeService.GetMediaType(i),
|
||||
doMove: (type, i) => Services.ContentTypeService.MoveMediaType(type, i));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the media type
|
||||
/// </summary>
|
||||
/// <param name="copy"></param>
|
||||
/// <returns></returns>
|
||||
public HttpResponseMessage PostCopy(MoveOrCopy copy)
|
||||
{
|
||||
return PerformCopy(
|
||||
copy,
|
||||
getContentType: i => Services.ContentTypeService.GetMediaType(i),
|
||||
doCopy: (type, i) => Services.ContentTypeService.CopyMediaType(type, i));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -123,6 +123,7 @@ namespace Umbraco.Web.Trees
|
||||
menu.Items.Add<ActionMove>(Services.TextService.Localize(string.Format("actions/{0}", ActionMove.Instance.Alias)), true);
|
||||
}
|
||||
}
|
||||
menu.Items.Add<ActionCopy>(Services.TextService.Localize(string.Format("actions/{0}", ActionCopy.Instance.Alias)));
|
||||
menu.Items.Add<ActionExport>(Services.TextService.Localize(string.Format("actions/{0}", ActionExport.Instance.Alias)), true).ConvertLegacyMenuItem(new UmbracoEntity
|
||||
{
|
||||
Id = int.Parse(id),
|
||||
|
||||
@@ -92,6 +92,7 @@ namespace Umbraco.Web.Trees
|
||||
{
|
||||
menu.Items.Add<ActionDelete>(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)));
|
||||
menu.Items.Add<ActionMove>(Services.TextService.Localize(string.Format("actions/{0}", ActionMove.Instance.Alias)), hasSeparator: true);
|
||||
menu.Items.Add<ActionCopy>(Services.TextService.Localize(string.Format("actions/{0}", ActionCopy.Instance.Alias)));
|
||||
}
|
||||
|
||||
return menu;
|
||||
|
||||
Reference in New Issue
Block a user