backports data type service updates and fixes unit tests with correct seeding value.
This commit is contained in:
29
src/Umbraco.Core/Models/PreValue.cs
Normal file
29
src/Umbraco.Core/Models/PreValue.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a stored pre-value field value
|
||||
/// </summary>
|
||||
public class PreValue
|
||||
{
|
||||
public PreValue(int id, string value)
|
||||
{
|
||||
Value = value;
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public PreValue(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The value stored for the pre-value field
|
||||
/// </summary>
|
||||
public string Value { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The database id for the pre-value field value
|
||||
/// </summary>
|
||||
public int Id { get; private set; }
|
||||
}
|
||||
}
|
||||
86
src/Umbraco.Core/Models/PreValueCollection.cs
Normal file
86
src/Umbraco.Core/Models/PreValueCollection.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the pre-value data for a DataType
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Due to the legacy nature of the data that can be stored for pre-values, we have this class which encapsulates the 2 different
|
||||
/// ways that pre-values are stored: A string array or a Dictionary.
|
||||
///
|
||||
/// Most legacy property editors won't support the dictionary format but new property editors should always use the dictionary format.
|
||||
/// In order to get overrideable pre-values working we need a dictionary since we'll have to reference a pre-value by a key.
|
||||
/// </remarks>
|
||||
public class PreValueCollection
|
||||
{
|
||||
private IDictionary<string, PreValue> _preValuesAsDictionary;
|
||||
private IEnumerable<PreValue> _preValuesAsArray;
|
||||
public IEnumerable<PreValue> PreValuesAsArray
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_preValuesAsArray == null)
|
||||
{
|
||||
throw new InvalidOperationException("The current pre-value collection is dictionary based, use the PreValuesAsDictionary property instead");
|
||||
}
|
||||
return _preValuesAsArray;
|
||||
}
|
||||
set { _preValuesAsArray = value; }
|
||||
}
|
||||
|
||||
public IDictionary<string, PreValue> PreValuesAsDictionary
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_preValuesAsDictionary == null)
|
||||
{
|
||||
throw new InvalidOperationException("The current pre-value collection is array based, use the PreValuesAsArray property instead");
|
||||
}
|
||||
return _preValuesAsDictionary;
|
||||
}
|
||||
set { _preValuesAsDictionary = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if it is a dictionary based collection
|
||||
/// </summary>
|
||||
public bool IsDictionaryBased
|
||||
{
|
||||
get { return _preValuesAsDictionary != null; }
|
||||
}
|
||||
|
||||
public PreValueCollection(IEnumerable<PreValue> preVals)
|
||||
{
|
||||
_preValuesAsArray = preVals;
|
||||
}
|
||||
|
||||
public PreValueCollection(IDictionary<string, PreValue> preVals)
|
||||
{
|
||||
_preValuesAsDictionary = preVals;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Regardless of how the pre-values are stored this will return as a dictionary, it will convert an array based to a dictionary
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IDictionary<string, PreValue> FormatAsDictionary()
|
||||
{
|
||||
if (IsDictionaryBased)
|
||||
{
|
||||
return PreValuesAsDictionary;
|
||||
}
|
||||
|
||||
//it's an array so need to format it, the alias will just be an iteration
|
||||
var result = new Dictionary<string, PreValue>();
|
||||
var asArray = PreValuesAsArray.ToArray();
|
||||
for (var i = 0; i < asArray.Length; i++)
|
||||
{
|
||||
result.Add(i.ToInvariantString(), asArray[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,39 +84,58 @@ namespace Umbraco.Core.Persistence.UnitOfWork
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commits all batched changes within the scope of a PetaPoco transaction <see cref="Transaction"/>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Unlike a typical unit of work, this UOW will let you commit more than once since a new transaction is creaed per
|
||||
/// Commit() call instead of having one Transaction per UOW.
|
||||
/// </remarks>
|
||||
public void Commit()
|
||||
{
|
||||
using (var transaction = Database.GetTransaction())
|
||||
{
|
||||
foreach (var operation in _operations.OrderBy(o => o.ProcessDate))
|
||||
{
|
||||
switch (operation.Type)
|
||||
{
|
||||
case TransactionType.Insert:
|
||||
operation.Repository.PersistNewItem(operation.Entity);
|
||||
break;
|
||||
case TransactionType.Delete:
|
||||
operation.Repository.PersistDeletedItem(operation.Entity);
|
||||
break;
|
||||
case TransactionType.Update:
|
||||
operation.Repository.PersistUpdatedItem(operation.Entity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
transaction.Complete();
|
||||
}
|
||||
/// <summary>
|
||||
/// Commits all batched changes within the scope of a PetaPoco transaction <see cref="Transaction"/>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Unlike a typical unit of work, this UOW will let you commit more than once since a new transaction is creaed per
|
||||
/// Commit() call instead of having one Transaction per UOW.
|
||||
/// </remarks>
|
||||
public void Commit()
|
||||
{
|
||||
Commit(null);
|
||||
}
|
||||
|
||||
// Clear everything
|
||||
_operations.Clear();
|
||||
_key = Guid.NewGuid();
|
||||
}
|
||||
/// <summary>
|
||||
/// Commits all batched changes within the scope of a PetaPoco transaction <see cref="Transaction"/>
|
||||
/// </summary>
|
||||
/// <param name="transactionCompleting">
|
||||
/// Allows you to set a callback which is executed before the transaction is committed, allow you to add additional SQL
|
||||
/// operations to the overall commit process after the queue has been processed.
|
||||
/// </param>
|
||||
internal void Commit(Action<UmbracoDatabase> transactionCompleting)
|
||||
{
|
||||
using (var transaction = Database.GetTransaction())
|
||||
{
|
||||
foreach (var operation in _operations.OrderBy(o => o.ProcessDate))
|
||||
{
|
||||
switch (operation.Type)
|
||||
{
|
||||
case TransactionType.Insert:
|
||||
operation.Repository.PersistNewItem(operation.Entity);
|
||||
break;
|
||||
case TransactionType.Delete:
|
||||
operation.Repository.PersistDeletedItem(operation.Entity);
|
||||
break;
|
||||
case TransactionType.Update:
|
||||
operation.Repository.PersistUpdatedItem(operation.Entity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Execute the callback if there is one
|
||||
if (transactionCompleting != null)
|
||||
{
|
||||
transactionCompleting(Database);
|
||||
}
|
||||
|
||||
transaction.Complete();
|
||||
}
|
||||
|
||||
// Clear everything
|
||||
_operations.Clear();
|
||||
_key = Guid.NewGuid();
|
||||
}
|
||||
|
||||
public object Key
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
@@ -18,16 +19,16 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public class DataTypeService : IDataTypeService
|
||||
{
|
||||
private readonly RepositoryFactory _repositoryFactory;
|
||||
private readonly RepositoryFactory _repositoryFactory;
|
||||
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
|
||||
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
|
||||
|
||||
public DataTypeService()
|
||||
: this(new RepositoryFactory())
|
||||
{}
|
||||
{ }
|
||||
|
||||
public DataTypeService(RepositoryFactory repositoryFactory)
|
||||
: this(new PetaPocoUnitOfWorkProvider(), repositoryFactory)
|
||||
: this(new PetaPocoUnitOfWorkProvider(), repositoryFactory)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -36,9 +37,9 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
}
|
||||
|
||||
public DataTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory)
|
||||
public DataTypeService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory)
|
||||
{
|
||||
_repositoryFactory = repositoryFactory;
|
||||
_repositoryFactory = repositoryFactory;
|
||||
_uowProvider = provider;
|
||||
}
|
||||
|
||||
@@ -74,7 +75,7 @@ namespace Umbraco.Core.Services
|
||||
/// <summary>
|
||||
/// Gets a <see cref="IDataTypeDefinition"/> by its control Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the DataType control</param>
|
||||
/// <param name="id">Id of the property editor</param>
|
||||
/// <returns>Collection of <see cref="IDataTypeDefinition"/> objects with a matching contorl id</returns>
|
||||
public IEnumerable<IDataTypeDefinition> GetDataTypeDefinitionByControlId(Guid id)
|
||||
{
|
||||
@@ -109,27 +110,25 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
{
|
||||
var dtos = uow.Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new {Id = id});
|
||||
var dtos = uow.Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = id });
|
||||
var list = dtos.Select(x => x.Value).ToList();
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all prevalues for an <see cref="IDataTypeDefinition"/>
|
||||
/// Returns the PreValueCollection for the specified data type
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method should be kept internal until a proper PreValue object model is introduced.
|
||||
/// </remarks>
|
||||
/// <param name="id">Id of the <see cref="IDataTypeDefinition"/> to retrieve prevalues from</param>
|
||||
/// <returns>An enumerable list of Tuples containing Id, Alias, SortOrder, Value</returns>
|
||||
internal IEnumerable<Tuple<int, string, int, string>> GetDetailedPreValuesByDataTypeId(int id)
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public PreValueCollection GetPreValuesCollectionByDataTypeId(int id)
|
||||
{
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
{
|
||||
var dtos = uow.Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = id });
|
||||
var list = dtos.Select(x => new Tuple<int, string, int, string>(x.Id, x.Alias, x.SortOrder, x.Value)).ToList();
|
||||
return list;
|
||||
var list = dtos.Select(x => new Tuple<PreValue, string, int>(new PreValue(x.Id, x.Value), x.Alias, x.SortOrder)).ToList();
|
||||
|
||||
return PreValueConverter.ConvertToPreValuesCollection(list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,8 +153,8 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="userId">Id of the user issueing the save</param>
|
||||
public void Save(IDataTypeDefinition dataTypeDefinition, int userId = 0)
|
||||
{
|
||||
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition), this))
|
||||
return;
|
||||
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition), this))
|
||||
return;
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
@@ -206,8 +205,11 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the DataTypeDefinition to save PreValues for</param>
|
||||
/// <param name="values">List of string values to save</param>
|
||||
[Obsolete("This should no longer be used, use the alternative SavePreValues or SaveDataTypeAndPreValues methods instead. This will only insert pre-values without keys")]
|
||||
public void SavePreValues(int id, IEnumerable<string> values)
|
||||
{
|
||||
//TODO: Should we raise an event here since we are really saving values for the data type?
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
@@ -236,6 +238,111 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves/updates the pre-values
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="values"></param>
|
||||
/// <remarks>
|
||||
/// We need to actually look up each pre-value and maintain it's id if possible - this is because of silly property editors
|
||||
/// like 'dropdown list publishing keys'
|
||||
/// </remarks>
|
||||
public void SavePreValues(int id, IDictionary<string, PreValue> values)
|
||||
{
|
||||
//TODO: Should we raise an event here since we are really saving values for the data type?
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
{
|
||||
using (var transaction = uow.Database.GetTransaction())
|
||||
{
|
||||
AddOrUpdatePreValues(id, values, uow);
|
||||
transaction.Complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will save a data type and it's pre-values in one transaction
|
||||
/// </summary>
|
||||
/// <param name="dataTypeDefinition"></param>
|
||||
/// <param name="values"></param>
|
||||
/// <param name="userId"></param>
|
||||
public void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary<string, PreValue> values, int userId = 0)
|
||||
{
|
||||
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition), this))
|
||||
return;
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var uow = (PetaPocoUnitOfWork)_uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow))
|
||||
{
|
||||
dataTypeDefinition.CreatorId = userId;
|
||||
repository.AddOrUpdate(dataTypeDefinition);
|
||||
|
||||
//complete the transaction, but run the delegate before the db transaction is finalized
|
||||
uow.Commit(database => AddOrUpdatePreValues(dataTypeDefinition.Id, values, uow));
|
||||
|
||||
Saved.RaiseEvent(new SaveEventArgs<IDataTypeDefinition>(dataTypeDefinition, false), this);
|
||||
}
|
||||
}
|
||||
|
||||
Audit.Add(AuditTypes.Save, string.Format("Save DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id);
|
||||
}
|
||||
|
||||
private void AddOrUpdatePreValues(int id, IDictionary<string, PreValue> preValueCollection, IDatabaseUnitOfWork uow)
|
||||
{
|
||||
//first just get all pre-values for this data type so we can compare them to see if we need to insert or update or replace
|
||||
var sql = new Sql().Select("*")
|
||||
.From<DataTypePreValueDto>()
|
||||
.Where<DataTypePreValueDto>(dto => dto.DataTypeNodeId == id)
|
||||
.OrderBy<DataTypePreValueDto>(dto => dto.SortOrder);
|
||||
var currentVals = uow.Database.Fetch<DataTypePreValueDto>(sql).ToArray();
|
||||
|
||||
//already existing, need to be updated
|
||||
var valueIds = preValueCollection.Where(x => x.Value.Id > 0).Select(x => x.Value.Id).ToArray();
|
||||
var existingByIds = currentVals.Where(x => valueIds.Contains(x.Id)).ToArray();
|
||||
|
||||
//These ones need to be removed from the db, they no longer exist in the new values
|
||||
var deleteById = currentVals.Where(x => valueIds.Contains(x.Id) == false);
|
||||
|
||||
foreach (var d in deleteById)
|
||||
{
|
||||
uow.Database.Execute(
|
||||
"DELETE FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId AND id=@Id",
|
||||
new { DataTypeId = id, Id = d.Id });
|
||||
}
|
||||
|
||||
var sortOrder = 1;
|
||||
|
||||
foreach (var pre in preValueCollection)
|
||||
{
|
||||
var existing = existingByIds.FirstOrDefault(valueDto => valueDto.Id == pre.Value.Id);
|
||||
if (existing != null)
|
||||
{
|
||||
existing.Value = pre.Value.Value;
|
||||
existing.SortOrder = sortOrder;
|
||||
uow.Database.Update(existing);
|
||||
}
|
||||
else
|
||||
{
|
||||
var dto = new DataTypePreValueDto
|
||||
{
|
||||
DataTypeNodeId = id,
|
||||
Value = pre.Value.Value,
|
||||
SortOrder = sortOrder,
|
||||
Alias = pre.Key
|
||||
};
|
||||
uow.Database.Insert(dto);
|
||||
}
|
||||
|
||||
sortOrder++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an <see cref="IDataTypeDefinition"/>
|
||||
/// </summary>
|
||||
@@ -246,43 +353,43 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="dataTypeDefinition"><see cref="IDataTypeDefinition"/> to delete</param>
|
||||
/// <param name="userId">Optional Id of the user issueing the deletion</param>
|
||||
public void Delete(IDataTypeDefinition dataTypeDefinition, int userId = 0)
|
||||
{
|
||||
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IDataTypeDefinition>(dataTypeDefinition), this))
|
||||
return;
|
||||
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
|
||||
{
|
||||
//Find ContentTypes using this IDataTypeDefinition on a PropertyType
|
||||
var query = Query<PropertyType>.Builder.Where(x => x.DataTypeDefinitionId == dataTypeDefinition.Id);
|
||||
var contentTypes = repository.GetByQuery(query);
|
||||
{
|
||||
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IDataTypeDefinition>(dataTypeDefinition), this))
|
||||
return;
|
||||
|
||||
//Loop through the list of results and remove the PropertyTypes that references the DataTypeDefinition that is being deleted
|
||||
foreach (var contentType in contentTypes)
|
||||
{
|
||||
if (contentType == null) continue;
|
||||
var uow = _uowProvider.GetUnitOfWork();
|
||||
using (var repository = _repositoryFactory.CreateContentTypeRepository(uow))
|
||||
{
|
||||
//Find ContentTypes using this IDataTypeDefinition on a PropertyType
|
||||
var query = Query<PropertyType>.Builder.Where(x => x.DataTypeDefinitionId == dataTypeDefinition.Id);
|
||||
var contentTypes = repository.GetByQuery(query);
|
||||
|
||||
foreach (var group in contentType.PropertyGroups)
|
||||
{
|
||||
var types = @group.PropertyTypes.Where(x => x.DataTypeDefinitionId == dataTypeDefinition.Id).ToList();
|
||||
foreach (var propertyType in types)
|
||||
{
|
||||
@group.PropertyTypes.Remove(propertyType);
|
||||
}
|
||||
}
|
||||
//Loop through the list of results and remove the PropertyTypes that references the DataTypeDefinition that is being deleted
|
||||
foreach (var contentType in contentTypes)
|
||||
{
|
||||
if (contentType == null) continue;
|
||||
|
||||
repository.AddOrUpdate(contentType);
|
||||
}
|
||||
foreach (var group in contentType.PropertyGroups)
|
||||
{
|
||||
var types = @group.PropertyTypes.Where(x => x.DataTypeDefinitionId == dataTypeDefinition.Id).ToList();
|
||||
foreach (var propertyType in types)
|
||||
{
|
||||
@group.PropertyTypes.Remove(propertyType);
|
||||
}
|
||||
}
|
||||
|
||||
var dataTypeRepository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow);
|
||||
dataTypeRepository.Delete(dataTypeDefinition);
|
||||
repository.AddOrUpdate(contentType);
|
||||
}
|
||||
|
||||
uow.Commit();
|
||||
var dataTypeRepository = _repositoryFactory.CreateDataTypeDefinitionRepository(uow);
|
||||
dataTypeRepository.Delete(dataTypeDefinition);
|
||||
|
||||
Deleted.RaiseEvent(new DeleteEventArgs<IDataTypeDefinition>(dataTypeDefinition, false), this);
|
||||
}
|
||||
uow.Commit();
|
||||
|
||||
Audit.Add(AuditTypes.Delete, string.Format("Delete DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id);
|
||||
Deleted.RaiseEvent(new DeleteEventArgs<IDataTypeDefinition>(dataTypeDefinition, false), this);
|
||||
}
|
||||
|
||||
Audit.Add(AuditTypes.Delete, string.Format("Delete DataTypeDefinition performed by user"), userId, dataTypeDefinition.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -290,6 +397,7 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the DataType, which corresponds to the Guid Id of the control</param>
|
||||
/// <returns><see cref="IDataType"/> object</returns>
|
||||
[Obsolete("IDataType is obsolete and is no longer used, it will be removed from the codebase in future versions")]
|
||||
public IDataType GetDataTypeById(Guid id)
|
||||
{
|
||||
return DataTypesResolver.Current.GetById(id);
|
||||
@@ -299,6 +407,7 @@ namespace Umbraco.Core.Services
|
||||
/// Gets a complete list of all registered <see cref="IDataType"/>'s
|
||||
/// </summary>
|
||||
/// <returns>An enumerable list of <see cref="IDataType"/> objects</returns>
|
||||
[Obsolete("IDataType is obsolete and is no longer used, it will be removed from the codebase in future versions")]
|
||||
public IEnumerable<IDataType> GetAllDataTypes()
|
||||
{
|
||||
return DataTypesResolver.Current.DataTypes;
|
||||
@@ -308,22 +417,58 @@ namespace Umbraco.Core.Services
|
||||
/// <summary>
|
||||
/// Occurs before Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IDataTypeService, DeleteEventArgs<IDataTypeDefinition>> Deleting;
|
||||
public static event TypedEventHandler<IDataTypeService, DeleteEventArgs<IDataTypeDefinition>> Deleting;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IDataTypeService, DeleteEventArgs<IDataTypeDefinition>> Deleted;
|
||||
public static event TypedEventHandler<IDataTypeService, DeleteEventArgs<IDataTypeDefinition>> Deleted;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IDataTypeService, SaveEventArgs<IDataTypeDefinition>> Saving;
|
||||
public static event TypedEventHandler<IDataTypeService, SaveEventArgs<IDataTypeDefinition>> Saving;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Save
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IDataTypeService, SaveEventArgs<IDataTypeDefinition>> Saved;
|
||||
public static event TypedEventHandler<IDataTypeService, SaveEventArgs<IDataTypeDefinition>> Saved;
|
||||
#endregion
|
||||
|
||||
internal static class PreValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts the tuple to a pre-value collection
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
internal static PreValueCollection ConvertToPreValuesCollection(IEnumerable<Tuple<PreValue, string, int>> list)
|
||||
{
|
||||
//now we need to determine if they are dictionary based, otherwise they have to be array based
|
||||
var dictionary = new Dictionary<string, PreValue>();
|
||||
|
||||
//need to check all of the keys, if there's only one and it is empty then it's an array
|
||||
var keys = list.Select(x => x.Item2).Distinct().ToArray();
|
||||
if (keys.Length == 1 && keys[0].IsNullOrWhiteSpace())
|
||||
{
|
||||
return new PreValueCollection(list.OrderBy(x => x.Item3).Select(x => x.Item1));
|
||||
}
|
||||
|
||||
foreach (var item in list
|
||||
.OrderBy(x => x.Item3) //we'll order them first so we maintain the order index in the dictionary
|
||||
.GroupBy(x => x.Item2)) //group by alias
|
||||
{
|
||||
if (item.Count() > 1)
|
||||
{
|
||||
//if there's more than 1 item per key, then it cannot be a dictionary, just return the array
|
||||
return new PreValueCollection(list.OrderBy(x => x.Item3).Select(x => x.Item1));
|
||||
}
|
||||
|
||||
dictionary.Add(item.Key, item.First().Item1);
|
||||
}
|
||||
|
||||
return new PreValueCollection(dictionary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,13 +83,36 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>An enumerable list of string values</returns>
|
||||
IEnumerable<string> GetPreValuesByDataTypeId(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a pre-value collection by data type id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
PreValueCollection GetPreValuesCollectionByDataTypeId(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a list of PreValues for a given DataTypeDefinition
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the DataTypeDefinition to save PreValues for</param>
|
||||
/// <param name="values">List of string values to save</param>
|
||||
[Obsolete("This should no longer be used, use the alternative SavePreValues or SaveDataTypeAndPreValues methods instead. This will only insert pre-values without keys")]
|
||||
void SavePreValues(int id, IEnumerable<string> values);
|
||||
|
||||
/// <summary>
|
||||
/// Saves a list of PreValues for a given DataTypeDefinition
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the DataTypeDefinition to save PreValues for</param>
|
||||
/// <param name="values">List of key/value pairs to save</param>
|
||||
void SavePreValues(int id, IDictionary<string, PreValue> values);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the data type and it's prevalues
|
||||
/// </summary>
|
||||
/// <param name="dataTypeDefinition"></param>
|
||||
/// <param name="values"></param>
|
||||
/// <param name="userId"></param>
|
||||
void SaveDataTypeAndPreValues(IDataTypeDefinition dataTypeDefinition, IDictionary<string, PreValue> values, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific PreValue by its Id
|
||||
/// </summary>
|
||||
|
||||
@@ -707,20 +707,23 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
var prevalues = new XElement("PreValues");
|
||||
|
||||
var prevalueList = ((DataTypeService)_dataTypeService).GetDetailedPreValuesByDataTypeId(dataTypeDefinition.Id);
|
||||
foreach (var tuple in prevalueList)
|
||||
var prevalueList = _dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeDefinition.Id)
|
||||
.FormatAsDictionary();
|
||||
|
||||
var sort = 0;
|
||||
foreach (var pv in prevalueList)
|
||||
{
|
||||
var prevalue = new XElement("PreValue");
|
||||
prevalue.Add(new XAttribute("Id", tuple.Item1));
|
||||
prevalue.Add(new XAttribute("Value", tuple.Item4));
|
||||
prevalue.Add(new XAttribute("Alias", tuple.Item2));
|
||||
prevalue.Add(new XAttribute("SortOrder", tuple.Item3));
|
||||
prevalue.Add(new XAttribute("Id", pv.Value.Id));
|
||||
prevalue.Add(new XAttribute("Value", pv.Value.Value));
|
||||
prevalue.Add(new XAttribute("Alias", pv.Key));
|
||||
prevalue.Add(new XAttribute("SortOrder", sort));
|
||||
prevalues.Add(prevalue);
|
||||
sort++;
|
||||
}
|
||||
|
||||
var xml = new XElement("DataType", prevalues);
|
||||
xml.Add(new XAttribute("Name", dataTypeDefinition.Name));
|
||||
//The 'ID' when exporting is actually the property editor alias (in pre v7 it was the IDataType GUID id)
|
||||
xml.Add(new XAttribute("Id", dataTypeDefinition.ControlId));
|
||||
xml.Add(new XAttribute("Definition", dataTypeDefinition.Key));
|
||||
xml.Add(new XAttribute("DatabaseType", dataTypeDefinition.DatabaseType.ToString()));
|
||||
|
||||
@@ -439,6 +439,16 @@ namespace Umbraco.Core
|
||||
return String.Format(CultureInfo.InvariantCulture, format, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an integer to an invariant formatted string
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToInvariantString(this int str)
|
||||
{
|
||||
return str.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares 2 strings with invariant culture and case ignored
|
||||
/// </summary>
|
||||
|
||||
@@ -189,6 +189,8 @@
|
||||
<Compile Include="Models\ContentTypeCompositionBase.cs" />
|
||||
<Compile Include="Models\ContentTypeExtensions.cs" />
|
||||
<Compile Include="Models\ContentTypeSort.cs" />
|
||||
<Compile Include="Models\PreValue.cs" />
|
||||
<Compile Include="Models\PreValueCollection.cs" />
|
||||
<Compile Include="Models\PublishedContent\IPublishedContentExtended.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedPropertyBase.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentModelFactoryImpl.cs" />
|
||||
|
||||
Reference in New Issue
Block a user