|
|
@ -8,17 +8,19 @@ |
|
|
|
|
|
|
|
|
using System; |
|
|
using System; |
|
|
using System.Collections.Generic; |
|
|
using System.Collections.Generic; |
|
|
|
|
|
using System.Collections.Immutable; |
|
|
|
|
|
using System.Diagnostics.Contracts; |
|
|
using System.Linq; |
|
|
using System.Linq; |
|
|
using Squidex.Infrastructure; |
|
|
using Squidex.Infrastructure; |
|
|
|
|
|
|
|
|
namespace Squidex.Domain.Apps.Core.Schemas |
|
|
namespace Squidex.Domain.Apps.Core.Schemas |
|
|
{ |
|
|
{ |
|
|
public sealed class Schema |
|
|
public sealed class Schema : Cloneable<Schema> |
|
|
{ |
|
|
{ |
|
|
private readonly string name; |
|
|
private readonly string name; |
|
|
private readonly List<Field> fieldsOrdered = new List<Field>(); |
|
|
private ImmutableList<Field> fieldsOrdered = ImmutableList<Field>.Empty; |
|
|
private readonly Dictionary<long, Field> fieldsById = new Dictionary<long, Field>(); |
|
|
private ImmutableDictionary<long, Field> fieldsById = ImmutableDictionary<long, Field>.Empty; |
|
|
private readonly Dictionary<string, Field> fieldsByName = new Dictionary<string, Field>(); |
|
|
private ImmutableDictionary<string, Field> fieldsByName = ImmutableDictionary<string, Field>.Empty; |
|
|
private SchemaProperties properties = new SchemaProperties(); |
|
|
private SchemaProperties properties = new SchemaProperties(); |
|
|
private bool isPublished; |
|
|
private bool isPublished; |
|
|
|
|
|
|
|
|
@ -52,43 +54,132 @@ namespace Squidex.Domain.Apps.Core.Schemas |
|
|
get { return properties; } |
|
|
get { return properties; } |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void Publish() |
|
|
public Schema(string name) |
|
|
{ |
|
|
{ |
|
|
isPublished = true; |
|
|
Guard.NotNullOrEmpty(name, nameof(name)); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void Unpublish() |
|
|
this.name = name; |
|
|
{ |
|
|
|
|
|
isPublished = false; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public Schema(string name) |
|
|
public Schema(string name, IEnumerable<Field> fields, SchemaProperties properties, bool isPublished) |
|
|
|
|
|
: this(name) |
|
|
{ |
|
|
{ |
|
|
Guard.NotNullOrEmpty(name, nameof(name)); |
|
|
Guard.NotNullOrEmpty(name, nameof(name)); |
|
|
|
|
|
|
|
|
this.name = name; |
|
|
this.isPublished = isPublished; |
|
|
|
|
|
|
|
|
|
|
|
this.properties = properties ?? new SchemaProperties(); |
|
|
|
|
|
this.properties.Freeze(); |
|
|
|
|
|
|
|
|
|
|
|
fieldsOrdered = ImmutableList<Field>.Empty.AddRange(fields); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected override void OnCloned() |
|
|
|
|
|
{ |
|
|
|
|
|
fieldsById = fieldsOrdered.ToImmutableDictionary(x => x.Id); |
|
|
|
|
|
fieldsByName = fieldsOrdered.ToImmutableDictionary(x => x.Name); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void Update(SchemaProperties newProperties) |
|
|
[Pure] |
|
|
|
|
|
public Schema Update(SchemaProperties newProperties) |
|
|
{ |
|
|
{ |
|
|
Guard.NotNull(newProperties, nameof(newProperties)); |
|
|
Guard.NotNull(newProperties, nameof(newProperties)); |
|
|
|
|
|
|
|
|
properties = newProperties; |
|
|
return Clone(clone => |
|
|
|
|
|
{ |
|
|
|
|
|
properties = newProperties; |
|
|
|
|
|
properties.Freeze(); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
[Pure] |
|
|
|
|
|
public Schema UpdateField(long fieldId, FieldProperties newProperties) |
|
|
|
|
|
{ |
|
|
|
|
|
return UpdateField(fieldId, field => |
|
|
|
|
|
{ |
|
|
|
|
|
return field.Update(newProperties); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
[Pure] |
|
|
|
|
|
public Schema LockField(long fieldId) |
|
|
|
|
|
{ |
|
|
|
|
|
return UpdateField(fieldId, field => |
|
|
|
|
|
{ |
|
|
|
|
|
return field.Lock(); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
[Pure] |
|
|
|
|
|
public Schema DisableField(long fieldId) |
|
|
|
|
|
{ |
|
|
|
|
|
return UpdateField(fieldId, field => |
|
|
|
|
|
{ |
|
|
|
|
|
return field.Disable(); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
[Pure] |
|
|
|
|
|
public Schema EnableField(long fieldId) |
|
|
|
|
|
{ |
|
|
|
|
|
return UpdateField(fieldId, field => |
|
|
|
|
|
{ |
|
|
|
|
|
return field.Enable(); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
[Pure] |
|
|
|
|
|
public Schema HideField(long fieldId) |
|
|
|
|
|
{ |
|
|
|
|
|
return UpdateField(fieldId, field => |
|
|
|
|
|
{ |
|
|
|
|
|
return field.Hide(); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
[Pure] |
|
|
|
|
|
public Schema ShowField(long fieldId) |
|
|
|
|
|
{ |
|
|
|
|
|
return UpdateField(fieldId, field => |
|
|
|
|
|
{ |
|
|
|
|
|
return field.Show(); |
|
|
|
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void DeleteField(long fieldId) |
|
|
[Pure] |
|
|
|
|
|
public Schema Publish() |
|
|
|
|
|
{ |
|
|
|
|
|
return Clone(clone => |
|
|
|
|
|
{ |
|
|
|
|
|
isPublished = true; |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
[Pure] |
|
|
|
|
|
public Schema Unpublish() |
|
|
|
|
|
{ |
|
|
|
|
|
return Clone(clone => |
|
|
|
|
|
{ |
|
|
|
|
|
isPublished = false; |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
[Pure] |
|
|
|
|
|
public Schema DeleteField(long fieldId) |
|
|
{ |
|
|
{ |
|
|
if (!fieldsById.TryGetValue(fieldId, out var field)) |
|
|
if (!fieldsById.TryGetValue(fieldId, out var field)) |
|
|
{ |
|
|
{ |
|
|
return; |
|
|
return this; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
fieldsById.Remove(fieldId); |
|
|
return Clone(clone => |
|
|
fieldsByName.Remove(field.Name); |
|
|
{ |
|
|
fieldsOrdered.Remove(field); |
|
|
clone.fieldsOrdered = fieldsOrdered.Remove(field); |
|
|
|
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void ReorderFields(List<long> ids) |
|
|
[Pure] |
|
|
|
|
|
public Schema ReorderFields(List<long> ids) |
|
|
{ |
|
|
{ |
|
|
Guard.NotNull(ids, nameof(ids)); |
|
|
Guard.NotNull(ids, nameof(ids)); |
|
|
|
|
|
|
|
|
@ -97,13 +188,14 @@ namespace Squidex.Domain.Apps.Core.Schemas |
|
|
throw new ArgumentException("Ids must cover all fields.", nameof(ids)); |
|
|
throw new ArgumentException("Ids must cover all fields.", nameof(ids)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
var fields = fieldsOrdered.ToList(); |
|
|
return Clone(clone => |
|
|
|
|
|
{ |
|
|
fieldsOrdered.Clear(); |
|
|
clone.fieldsOrdered = fieldsOrdered.OrderBy(f => ids.IndexOf(f.Id)).ToImmutableList(); |
|
|
fieldsOrdered.AddRange(fields.OrderBy(f => ids.IndexOf(f.Id))); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void AddField(Field field) |
|
|
[Pure] |
|
|
|
|
|
public Schema AddField(Field field) |
|
|
{ |
|
|
{ |
|
|
Guard.NotNull(field, nameof(field)); |
|
|
Guard.NotNull(field, nameof(field)); |
|
|
|
|
|
|
|
|
@ -112,9 +204,26 @@ namespace Squidex.Domain.Apps.Core.Schemas |
|
|
throw new ArgumentException($"A field with name '{field.Name}' already exists.", nameof(field)); |
|
|
throw new ArgumentException($"A field with name '{field.Name}' already exists.", nameof(field)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
fieldsById.Add(field.Id, field); |
|
|
return Clone(clone => |
|
|
fieldsByName.Add(field.Name, field); |
|
|
{ |
|
|
fieldsOrdered.Add(field); |
|
|
clone.fieldsOrdered = clone.fieldsOrdered.Add(field); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
[Pure] |
|
|
|
|
|
public Schema UpdateField(long fieldId, Func<Field, Field> updater) |
|
|
|
|
|
{ |
|
|
|
|
|
Guard.NotNull(updater, nameof(updater)); |
|
|
|
|
|
|
|
|
|
|
|
if (!fieldsById.TryGetValue(fieldId, out var field)) |
|
|
|
|
|
{ |
|
|
|
|
|
return this; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return Clone(clone => |
|
|
|
|
|
{ |
|
|
|
|
|
clone.fieldsOrdered = clone.fieldsOrdered.Replace(field, updater(field)); |
|
|
|
|
|
}); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |