diff --git a/src/Umbraco.Core/Constants-Conventions.cs b/src/Umbraco.Core/Constants-Conventions.cs index ea0303eadc..9c069c4c2f 100644 --- a/src/Umbraco.Core/Constants-Conventions.cs +++ b/src/Umbraco.Core/Constants-Conventions.cs @@ -279,6 +279,22 @@ namespace Umbraco.Core /// public const string AltTemplate = "altTemplate"; } + + /// + /// Defines the alias identifiers for Umbraco relation types. + /// + public static class RelationTypes + { + /// + /// ContentType name for default relation type "Relate Document On Copy". + /// + public const string RelateDocumentOnCopyName = "Relate Document On Copy"; + + /// + /// ContentType alias for default relation type "Relate Document On Copy". + /// + public const string RelateDocumentOnCopyAlias = "relateDocumentOnCopy"; + } } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Events/CopyEventArgs.cs b/src/Umbraco.Core/Events/CopyEventArgs.cs index f53f8a536e..16f4fae982 100644 --- a/src/Umbraco.Core/Events/CopyEventArgs.cs +++ b/src/Umbraco.Core/Events/CopyEventArgs.cs @@ -1,35 +1,47 @@ namespace Umbraco.Core.Events { - public class CopyEventArgs : CancellableObjectEventArgs - { - public CopyEventArgs(TEntity original, TEntity copy, bool canCancel, int parentId) : base(original, canCancel) - { - Copy = copy; - ParentId = parentId; - } + public class CopyEventArgs : CancellableObjectEventArgs + { + public CopyEventArgs(TEntity original, TEntity copy, bool canCancel, int parentId) + : base(original, canCancel) + { + Copy = copy; + ParentId = parentId; + } - public CopyEventArgs(TEntity eventObject, TEntity copy, int parentId) : base(eventObject) - { - Copy = copy; - ParentId = parentId; - } + public CopyEventArgs(TEntity eventObject, TEntity copy, int parentId) + : base(eventObject) + { + Copy = copy; + ParentId = parentId; + } - /// - /// The copied entity - /// - public TEntity Copy { get; set; } + public CopyEventArgs(TEntity eventObject, TEntity copy, bool canCancel, int parentId, bool relateToOriginal) + : base(eventObject, canCancel) + { + Copy = copy; + ParentId = parentId; + RelateToOriginal = relateToOriginal; + } - /// - /// The original entity - /// - public TEntity Original - { - get { return EventObject; } - } + /// + /// The copied entity + /// + public TEntity Copy { get; set; } - /// - /// Gets or Sets the Id of the objects new parent. - /// - public int ParentId { get; private set; } - } + /// + /// The original entity + /// + public TEntity Original + { + get { return EventObject; } + } + + /// + /// Gets or Sets the Id of the objects new parent. + /// + public int ParentId { get; private set; } + + public bool RelateToOriginal { get; set; } + } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index 0186b9387c..35730cebbe 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -255,7 +255,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial private void CreateUmbracoRelationTypeData() { - _database.Insert("umbracoRelationType", "id", false, new RelationTypeDto { Id = 1, Alias = "relateDocumentOnCopy", ChildObjectType = new Guid(Constants.ObjectTypes.Document), ParentObjectType = new Guid("C66BA18E-EAF3-4CFF-8A22-41B16D66A972"), Dual = true, Name = "Relate Document On Copy" }); + _database.Insert("umbracoRelationType", "id", false, new RelationTypeDto { Id = 1, Alias = Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias, ChildObjectType = new Guid(Constants.ObjectTypes.Document), ParentObjectType = new Guid("C66BA18E-EAF3-4CFF-8A22-41B16D66A972"), Dual = true, Name = Constants.Conventions.RelationTypes.RelateDocumentOnCopyName }); } private void CreateCmsTaskTypeData() diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 9ac8ba4162..be81292bb0 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -2,12 +2,10 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Linq.Expressions; using System.Threading; using System.Xml.Linq; using Umbraco.Core.Auditing; using Umbraco.Core.Events; -using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; @@ -16,7 +14,6 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Caching; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Publishing; @@ -80,7 +77,7 @@ namespace Umbraco.Core.Services { var uow = _uowProvider.GetUnitOfWork(); using (var repository = _repositoryFactory.CreateContentRepository(uow)) - { + { return repository.Count(contentTypeAlias); } } @@ -755,7 +752,7 @@ namespace Umbraco.Core.Services { var result = SaveAndPublishDo(content, userId); LogHelper.Info("Call was made to ContentService.Publish, use PublishWithStatus instead since that method will provide more detailed information on the outcome"); - return result.Success; + return result.Success; } /// @@ -785,7 +782,7 @@ namespace Umbraco.Core.Services if (!result.Any(x => x.Result.ContentItem.Id == content.Id)) return false; - return result.Single(x => x.Result.ContentItem.Id == content.Id).Success; + return result.Single(x => x.Result.ContentItem.Id == content.Id).Success; } /// @@ -822,7 +819,7 @@ namespace Umbraco.Core.Services public bool SaveAndPublish(IContent content, int userId = 0, bool raiseEvents = true) { var result = SaveAndPublishDo(content, userId, raiseEvents); - return result.Success; + return result.Success; } /// @@ -886,7 +883,7 @@ namespace Umbraco.Core.Services repository.AddOrUpdate(content); //add or update preview - repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, c)); + repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, c)); } } else @@ -897,7 +894,7 @@ namespace Umbraco.Core.Services repository.AddOrUpdate(content); //add or update preview repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, c)); - } + } } uow.Commit(); @@ -1138,7 +1135,7 @@ namespace Umbraco.Core.Services MoveToRecycleBin(content, userId); return; } - + if (Moving.IsRaisedEventCancelled( new MoveEventArgs( new MoveEventInfo(content, content.Path, parentId)), this)) @@ -1231,37 +1228,15 @@ namespace Umbraco.Core.Services //don't copy tags data in tags table if the item is in the recycle bin if (parentId != Constants.System.RecycleBinContent) { - + var tags = uow.Database.Fetch("WHERE nodeId = @Id", new { Id = content.Id }); foreach (var tag in tags) { uow.Database.Insert(new TagRelationshipDto { NodeId = copy.Id, TagId = tag.TagId, PropertyTypeId = tag.PropertyTypeId }); - } + } } } - - //NOTE This 'Relation' part should eventually be delegated to a RelationService - //TODO: This should be part of a single commit - if (relateToOriginal) - { - IRelationType relationType = null; - using (var relationTypeRepository = _repositoryFactory.CreateRelationTypeRepository(uow)) - { - relationType = relationTypeRepository.Get(1); - } - - using (var relationRepository = _repositoryFactory.CreateRelationRepository(uow)) - { - var relation = new Relation(content.Id, copy.Id, relationType); - relationRepository.AddOrUpdate(relation); - uow.Commit(); - } - - Audit.Add(AuditTypes.Copy, - string.Format("Copied content with Id: '{0}' related to original content with Id: '{1}'", - copy.Id, content.Id), copy.WriterId, copy.Id); - } - + //Look for children and copy those as well var children = GetChildren(content.Id); foreach (var child in children) @@ -1271,10 +1246,10 @@ namespace Umbraco.Core.Services Copy(child, copy.Id, relateToOriginal, userId); } - Copied.RaiseEvent(new CopyEventArgs(content, copy, false, parentId), this); + Copied.RaiseEvent(new CopyEventArgs(content, copy, false, parentId, relateToOriginal), this); Audit.Add(AuditTypes.Copy, "Copy Content performed by user", content.WriterId, content.Id); - + //TODO: Don't think we need this here because cache should be cleared by the event listeners // and the correct ICacheRefreshers!? RuntimeCacheProvider.Current.Clear(); @@ -1403,9 +1378,9 @@ namespace Umbraco.Core.Services //add or update a preview repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, c)); } - + foreach (var content in shouldBePublished) - { + { //Create and Save ContentXml DTO repository.AddOrUpdateContentXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, c)); } @@ -1596,7 +1571,7 @@ namespace Umbraco.Core.Services //bulk insert it into the database uow.Database.BulkInsertRecords(xmlItems, tr); - tr.Complete(); + tr.Complete(); } Audit.Add(AuditTypes.Publish, "RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1); @@ -1783,7 +1758,7 @@ namespace Umbraco.Core.Services //Generate a new preview repository.AddOrUpdatePreviewXml(content, c => _entitySerializer.Serialize(this, _dataTypeService, c)); - + if (published) { //Content Xml @@ -1923,7 +1898,7 @@ namespace Umbraco.Core.Services } return PublishStatusType.Success; - } + } private IContentType FindContentTypeByAlias(string contentTypeAlias) { diff --git a/src/Umbraco.Web/Strategies/RelateOnCopyHandler.cs b/src/Umbraco.Web/Strategies/RelateOnCopyHandler.cs new file mode 100644 index 0000000000..98cad3e639 --- /dev/null +++ b/src/Umbraco.Web/Strategies/RelateOnCopyHandler.cs @@ -0,0 +1,44 @@ +using System; +using System.Linq; +using Umbraco.Core; +using Umbraco.Core.Auditing; +using Umbraco.Core.Models; +using Umbraco.Core.Services; + +namespace Umbraco.Web.Strategies +{ + public sealed class RelateOnCopyHandler : ApplicationEventHandler + { + protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) + { + ContentService.Copied += ContentServiceCopied; + } + + private void ContentServiceCopied(IContentService sender, Core.Events.CopyEventArgs e) + { + if (e.RelateToOriginal) + { + var relationService = ApplicationContext.Current.Services.RelationService; + + var relationType = relationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias); + + if (relationType == null) + { + relationType = new RelationType(new Guid(Constants.ObjectTypes.Document), + new Guid(Constants.ObjectTypes.Document), + Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias, + Constants.Conventions.RelationTypes.RelateDocumentOnCopyName) { IsBidirectional = true }; + + relationService.Save(relationType); + } + + var relation = new Relation(e.Original.Id, e.Copy.Id, relationType); + relationService.Save(relation); + + Audit.Add(AuditTypes.Copy, + string.Format("Copied content with Id: '{0}' related to original content with Id: '{1}'", + e.Copy.Id, e.Original.Id), e.Copy.WriterId, e.Copy.Id); + } + } + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 3a8a7c3c38..e9cdb203a5 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -467,6 +467,7 @@ + diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx.cs index af7a4e7658..9961fc7449 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/NewRelationType.aspx.cs @@ -2,7 +2,7 @@ using System.Web.UI.WebControls; using umbraco.BasePages; using umbraco.BusinessLogic; -using umbraco.cms.businesslogic.relation; +using Umbraco.Core.Models; namespace umbraco.cms.presentation.developer.RelationTypes { @@ -40,7 +40,8 @@ namespace umbraco.cms.presentation.developer.RelationTypes /// to set validation respose protected void AliasCustomValidator_ServerValidate(object source, ServerValidateEventArgs args) { - args.IsValid = RelationType.GetByAlias(this.aliasTextBox.Text.Trim()) == null; + var relationService = Services.RelationService; + args.IsValid = relationService.GetRelationTypeByAlias(this.aliasTextBox.Text.Trim()) == null; } /// @@ -54,19 +55,18 @@ namespace umbraco.cms.presentation.developer.RelationTypes { var newRelationTypeAlias = this.aliasTextBox.Text.Trim(); - uQuery.SqlHelper.ExecuteNonQuery( - string.Format("INSERT INTO umbracoRelationType ([dual], parentObjectType, childObjectType, name, alias) VALUES ({0}, '{1}', '{2}', '{3}', '{4}')", - this.dualRadioButtonList.SelectedValue, - uQuery.GetUmbracoObjectType(this.parentDropDownList.SelectedValue).GetGuid().ToString(), - uQuery.GetUmbracoObjectType(this.childDropDownList.SelectedValue).GetGuid().ToString(), - this.descriptionTextBox.Text, - newRelationTypeAlias)); + var relationService = Services.RelationService; + var relationType = new RelationType(new Guid(this.childDropDownList.SelectedValue), + new Guid(this.parentDropDownList.SelectedValue), newRelationTypeAlias, this.descriptionTextBox.Text) + { + IsBidirectional = bool.Parse(this.dualRadioButtonList.SelectedValue) + }; - var newRelationTypeId = uQuery.SqlHelper.ExecuteScalar("SELECT id FROM umbracoRelationType WHERE alias = '" + newRelationTypeAlias + "'"); + relationService.Save(relationType); - // base.speechBubble(BasePage.speechBubbleIcon.success, "New Relation Type", "relation type created"); + var newRelationTypeId = relationService.GetRelationTypeByAlias(newRelationTypeAlias); - ClientTools.ChangeContentFrameUrl("/umbraco/developer/RelationTypes/EditRelationType.aspx?id=" + newRelationTypeId.ToString()).CloseModalWindow().ChildNodeCreated(); + ClientTools.ChangeContentFrameUrl("/umbraco/developer/RelationTypes/EditRelationType.aspx?id=" + newRelationTypeId).CloseModalWindow().ChildNodeCreated(); } }