Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/Umbraco.Core/Compose/RelateOnCopyComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ private static void ContentServiceCopied(IContentService sender, Events.CopyEven

if (relationType == null)
{
relationType = new RelationType(Constants.ObjectTypes.Document,
relationType = new RelationType(Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias,
Constants.Conventions.RelationTypes.RelateDocumentOnCopyName,
true,
Constants.ObjectTypes.Document,
Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias,
Constants.Conventions.RelationTypes.RelateDocumentOnCopyName) { IsBidirectional = true };
Constants.ObjectTypes.Document);

relationService.Save(relationType);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Umbraco.Core/Compose/RelateOnTrashComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private static void ContentService_Trashed(IContentService sender, MoveEventArgs
var documentObjectType = Constants.ObjectTypes.Document;
const string relationTypeName = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName;

relationType = new RelationType(documentObjectType, documentObjectType, relationTypeAlias, relationTypeName);
relationType = new RelationType(relationTypeName, relationTypeAlias, false, documentObjectType, documentObjectType);
relationService.Save(relationType);
}

Expand Down Expand Up @@ -106,7 +106,7 @@ private static void MediaService_Trashed(IMediaService sender, MoveEventArgs<IMe
{
var documentObjectType = Constants.ObjectTypes.Document;
const string relationTypeName = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName;
relationType = new RelationType(documentObjectType, documentObjectType, relationTypeAlias, relationTypeName);
relationType = new RelationType(relationTypeName, relationTypeAlias, false, documentObjectType, documentObjectType);
relationService.Save(relationType);
}
foreach (var item in e.MoveInfoCollection)
Expand Down
43 changes: 37 additions & 6 deletions src/Umbraco.Core/Constants-Conventions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -309,34 +309,65 @@ public static class Url
public static class RelationTypes
{
/// <summary>
/// ContentType name for default relation type "Relate Document On Copy".
/// Name for default relation type "Related Media".
/// </summary>
public const string RelatedMediaName = "Related Media";

/// <summary>
/// Alias for default relation type "Related Media"
/// </summary>
public const string RelatedMediaAlias = "umbMedia";

/// <summary>
/// Name for default relation type "Related Document".
/// </summary>
public const string RelatedDocumentName = "Related Document";

/// <summary>
/// Alias for default relation type "Related Document"
/// </summary>
public const string RelatedDocumentAlias = "umbDocument";

/// <summary>
/// Name for default relation type "Relate Document On Copy".
/// </summary>
public const string RelateDocumentOnCopyName = "Relate Document On Copy";

/// <summary>
/// ContentType alias for default relation type "Relate Document On Copy".
/// Alias for default relation type "Relate Document On Copy".
/// </summary>
public const string RelateDocumentOnCopyAlias = "relateDocumentOnCopy";

/// <summary>
/// ContentType name for default relation type "Relate Parent Document On Delete".
/// Name for default relation type "Relate Parent Document On Delete".
/// </summary>
public const string RelateParentDocumentOnDeleteName = "Relate Parent Document On Delete";

/// <summary>
/// ContentType alias for default relation type "Relate Parent Document On Delete".
/// Alias for default relation type "Relate Parent Document On Delete".
/// </summary>
public const string RelateParentDocumentOnDeleteAlias = "relateParentDocumentOnDelete";

/// <summary>
/// ContentType name for default relation type "Relate Parent Media Folder On Delete".
/// Name for default relation type "Relate Parent Media Folder On Delete".
/// </summary>
public const string RelateParentMediaFolderOnDeleteName = "Relate Parent Media Folder On Delete";

/// <summary>
/// ContentType alias for default relation type "Relate Parent Media Folder On Delete".
/// Alias for default relation type "Relate Parent Media Folder On Delete".
/// </summary>
public const string RelateParentMediaFolderOnDeleteAlias = "relateParentMediaFolderOnDelete";

/// <summary>
/// Returns the types of relations that are automatically tracked
/// </summary>
/// <remarks>
/// Developers should not manually use these relation types since they will all be cleared whenever an entity
/// (content, media or member) is saved since they are auto-populated based on property values.
/// </remarks>
public static string[] AutomaticRelationTypes = new[] { RelatedMediaAlias, RelatedDocumentAlias };

//TODO: return a list of built in types so we can use that to prevent deletion in the uI
}
}
}
Expand Down
19 changes: 16 additions & 3 deletions src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,27 @@ void InsertDataTypeDto(int id, string editorAlias, string dbType, string configu
private void CreateRelationTypeData()
{
var relationType = new RelationTypeDto { Id = 1, Alias = Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias, ChildObjectType = Constants.ObjectTypes.Document, ParentObjectType = Constants.ObjectTypes.Document, Dual = true, Name = Constants.Conventions.RelationTypes.RelateDocumentOnCopyName };
relationType.UniqueId = (relationType.Alias + "____" + relationType.Name).ToGuid();
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
_database.Insert(Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
relationType = new RelationTypeDto { Id = 2, Alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias, ChildObjectType = Constants.ObjectTypes.Document, ParentObjectType = Constants.ObjectTypes.Document, Dual = false, Name = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName };
relationType.UniqueId = (relationType.Alias + "____" + relationType.Name).ToGuid();
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
_database.Insert(Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
relationType = new RelationTypeDto { Id = 3, Alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias, ChildObjectType = Constants.ObjectTypes.Media, ParentObjectType = Constants.ObjectTypes.Media, Dual = false, Name = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName };
relationType.UniqueId = (relationType.Alias + "____" + relationType.Name).ToGuid();
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
_database.Insert(Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);

relationType = new RelationTypeDto { Id = 4, Alias = Constants.Conventions.RelationTypes.RelatedMediaAlias, ChildObjectType = null, ParentObjectType = null, Dual = false, Name = Constants.Conventions.RelationTypes.RelatedMediaName };
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
_database.Insert(Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);

relationType = new RelationTypeDto { Id = 5, Alias = Constants.Conventions.RelationTypes.RelatedDocumentAlias, ChildObjectType = null, ParentObjectType = null, Dual = false, Name = Constants.Conventions.RelationTypes.RelatedDocumentName };
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
_database.Insert(Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
}

internal static Guid CreateUniqueRelationTypeId(string alias, string name)
{
return (alias + "____" + name).ToGuid();
}

private void CreateKeyValueData()
Expand Down
5 changes: 5 additions & 0 deletions src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Umbraco.Core.Migrations.Upgrade.V_8_0_0;
using Umbraco.Core.Migrations.Upgrade.V_8_0_1;
using Umbraco.Core.Migrations.Upgrade.V_8_1_0;
using Umbraco.Core.Migrations.Upgrade.V_8_5_0;

namespace Umbraco.Core.Migrations.Upgrade
{
Expand Down Expand Up @@ -182,6 +183,10 @@ protected void DefinePlan()
To<RenameUserLoginDtoDateIndex>("{0372A42B-DECF-498D-B4D1-6379E907EB94}");
To<FixContentNuCascade>("{5B1E0D93-F5A3-449B-84BA-65366B84E2D4}");

// to 8.5.0...
To<UpdateRelationTypeTable>("{4759A294-9860-46BC-99F9-B4C975CAE580}");
To<AddNewRelationTypes>("{0BC866BC-0665-487A-9913-0290BD0169AD}");

//FINAL
}
}
Expand Down
33 changes: 33 additions & 0 deletions src/Umbraco.Core/Migrations/Upgrade/V_8_5_0/AddNewRelationTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Umbraco.Core.Migrations.Install;

namespace Umbraco.Core.Migrations.Upgrade.V_8_5_0
{
/// <summary>
/// Ensures the new relation types are created
/// </summary>
public class AddNewRelationTypes : MigrationBase
{
public AddNewRelationTypes(IMigrationContext context)
: base(context)
{ }

public override void Migrate()
{
CreateRelation(
Constants.Conventions.RelationTypes.RelatedMediaAlias,
Constants.Conventions.RelationTypes.RelatedMediaName);

CreateRelation(
Constants.Conventions.RelationTypes.RelatedDocumentAlias,
Constants.Conventions.RelationTypes.RelatedDocumentName);
}

private void CreateRelation(string alias, string name)
{
var uniqueId = DatabaseDataCreator.CreateUniqueRelationTypeId(alias ,name); //this is the same as how it installs so everything is consistent
Insert.IntoTable(Constants.DatabaseSchema.Tables.RelationType)
.Row(new { typeUniqueId = uniqueId, dual = 0, name, alias })
.Do();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Umbraco.Core.Persistence.Dtos;

namespace Umbraco.Core.Migrations.Upgrade.V_8_5_0
{

public class UpdateRelationTypeTable : MigrationBase
{
public UpdateRelationTypeTable(IMigrationContext context)
: base(context)
{ }

public override void Migrate()
{

Alter.Table(Constants.DatabaseSchema.Tables.RelationType).AlterColumn("parentObjectType").AsGuid().Nullable().Do();
Alter.Table(Constants.DatabaseSchema.Tables.RelationType).AlterColumn("childObjectType").AsGuid().Nullable().Do();

//TODO: We have to update this field to ensure it's not null, we can just copy across the name since that is not nullable

//drop index before we can alter the column
if (IndexExists("IX_umbracoRelationType_alias"))
Delete
.Index("IX_umbracoRelationType_alias")
.OnTable(Constants.DatabaseSchema.Tables.RelationType)
.Do();
//change the column to non nullable
Alter.Table(Constants.DatabaseSchema.Tables.RelationType).AlterColumn("alias").AsString(100).NotNullable().Do();
//re-create the index
Create
.Index("IX_umbracoRelationType_alias")
.OnTable(Constants.DatabaseSchema.Tables.RelationType)
.OnColumn("alias")
.Ascending()
.WithOptions().Unique().WithOptions().NonClustered()
.Do();
}
}
}
1 change: 1 addition & 0 deletions src/Umbraco.Core/Models/Editors/ContentPropertyFile.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace Umbraco.Core.Models.Editors
{

/// <summary>
/// Represents an uploaded file for a property.
/// </summary>
Expand Down
70 changes: 70 additions & 0 deletions src/Umbraco.Core/Models/Editors/UmbracoEntityReference.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;

namespace Umbraco.Core.Models.Editors
{
/// <summary>
/// Used to track reference to other entities in a property value
/// </summary>
public struct UmbracoEntityReference : IEquatable<UmbracoEntityReference>
{
private static readonly UmbracoEntityReference _empty = new UmbracoEntityReference(Udi.UnknownTypeUdi.Instance, string.Empty);

public UmbracoEntityReference(Udi udi, string relationTypeAlias)
{
Udi = udi ?? throw new ArgumentNullException(nameof(udi));
RelationTypeAlias = relationTypeAlias ?? throw new ArgumentNullException(nameof(relationTypeAlias));
}

public UmbracoEntityReference(Udi udi)
{
Udi = udi ?? throw new ArgumentNullException(nameof(udi));

switch (udi.EntityType)
{
case Constants.UdiEntityType.Media:
RelationTypeAlias = Constants.Conventions.RelationTypes.RelatedMediaAlias;
break;
default:
RelationTypeAlias = Constants.Conventions.RelationTypes.RelatedDocumentAlias;
break;
}
}

public static UmbracoEntityReference Empty() => _empty;

public static bool IsEmpty(UmbracoEntityReference reference) => reference == Empty();

public Udi Udi { get; }
public string RelationTypeAlias { get; }

public override bool Equals(object obj)
{
return obj is UmbracoEntityReference reference && Equals(reference);
}

public bool Equals(UmbracoEntityReference other)
{
return EqualityComparer<Udi>.Default.Equals(Udi, other.Udi) &&
RelationTypeAlias == other.RelationTypeAlias;
}

public override int GetHashCode()
{
var hashCode = -487348478;
hashCode = hashCode * -1521134295 + EqualityComparer<Udi>.Default.GetHashCode(Udi);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(RelationTypeAlias);
return hashCode;
}

public static bool operator ==(UmbracoEntityReference left, UmbracoEntityReference right)
{
return left.Equals(right);
}

public static bool operator !=(UmbracoEntityReference left, UmbracoEntityReference right)
{
return !(left == right);
}
}
}
9 changes: 8 additions & 1 deletion src/Umbraco.Core/Models/IRelation.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Runtime.Serialization;
using System;
using System.Runtime.Serialization;
using Umbraco.Core.Models.Entities;

namespace Umbraco.Core.Models
Expand All @@ -11,12 +12,18 @@ public interface IRelation : IEntity, IRememberBeingDirty
[DataMember]
int ParentId { get; set; }

[DataMember]
Guid ParentObjectType { get; set; }

/// <summary>
/// Gets or sets the Child Id of the Relation (Destination)
/// </summary>
[DataMember]
int ChildId { get; set; }

[DataMember]
Guid ChildObjectType { get; set; }

/// <summary>
/// Gets or sets the <see cref="RelationType"/> for the Relation
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions src/Umbraco.Core/Models/IRelationType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ public interface IRelationType : IEntity, IRememberBeingDirty
/// </summary>
/// <remarks>Corresponds to the NodeObjectType in the umbracoNode table</remarks>
[DataMember]
Guid ParentObjectType { get; set; }
Guid? ParentObjectType { get; set; }

/// <summary>
/// Gets or sets the Childs object type id
/// </summary>
/// <remarks>Corresponds to the NodeObjectType in the umbracoNode table</remarks>
[DataMember]
Guid ChildObjectType { get; set; }
Guid? ChildObjectType { get; set; }
}
}
Loading