using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Strings;
namespace Umbraco.Core.Models
{
///
/// Represents a Macro
///
[Serializable]
[DataContract(IsReference = true)]
public class Macro : EntityBase, IMacro
{
private readonly IShortStringHelper _shortStringHelper;
public Macro(IShortStringHelper shortStringHelper)
{
_shortStringHelper = shortStringHelper;
_properties = new MacroPropertyCollection();
_properties.CollectionChanged += PropertiesChanged;
_addedProperties = new List();
_removedProperties = new List();
}
///
/// Creates an item with pre-filled properties
///
///
///
///
///
///
///
///
///
///
///
public Macro(IShortStringHelper shortStringHelper, int id, Guid key, bool useInEditor, int cacheDuration, string @alias, string name, bool cacheByPage, bool cacheByMember, bool dontRender, string macroSource)
: this(shortStringHelper)
{
Id = id;
Key = key;
UseInEditor = useInEditor;
CacheDuration = cacheDuration;
Alias = alias.ToCleanString(shortStringHelper,CleanStringType.Alias);
Name = name;
CacheByPage = cacheByPage;
CacheByMember = cacheByMember;
DontRender = dontRender;
MacroSource = macroSource;
}
///
/// Creates an instance for persisting a new item
///
///
///
///
///
///
///
///
///
public Macro(IShortStringHelper shortStringHelper, string @alias, string name,
string macroSource,
bool cacheByPage = false,
bool cacheByMember = false,
bool dontRender = true,
bool useInEditor = false,
int cacheDuration = 0)
: this(shortStringHelper)
{
UseInEditor = useInEditor;
CacheDuration = cacheDuration;
Alias = alias.ToCleanString(shortStringHelper, CleanStringType.Alias);
Name = name;
CacheByPage = cacheByPage;
CacheByMember = cacheByMember;
DontRender = dontRender;
MacroSource = macroSource;
}
private string _alias;
private string _name;
private bool _useInEditor;
private int _cacheDuration;
private bool _cacheByPage;
private bool _cacheByMember;
private bool _dontRender;
private string _macroSource;
private MacroPropertyCollection _properties;
private List _addedProperties;
private List _removedProperties;
void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(nameof(Properties));
if (e.Action == NotifyCollectionChangedAction.Add)
{
//listen for changes
var prop = e.NewItems.Cast().First();
prop.PropertyChanged += PropertyDataChanged;
var alias = prop.Alias;
if (_addedProperties.Contains(alias) == false)
{
//add to the added props
_addedProperties.Add(alias);
}
}
else if (e.Action == NotifyCollectionChangedAction.Remove)
{
//remove listening for changes
var prop = e.OldItems.Cast().First();
prop.PropertyChanged -= PropertyDataChanged;
var alias = prop.Alias;
if (_removedProperties.Contains(alias) == false)
{
_removedProperties.Add(alias);
}
}
}
///
/// When some data of a property has changed ensure our Properties flag is dirty
///
///
///
void PropertyDataChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(nameof(Properties));
}
public override void ResetDirtyProperties(bool rememberDirty)
{
base.ResetDirtyProperties(rememberDirty);
_addedProperties.Clear();
_removedProperties.Clear();
foreach (var prop in Properties)
{
prop.ResetDirtyProperties(rememberDirty);
}
}
///
/// Used internally to check if we need to add a section in the repository to the db
///
internal IEnumerable AddedProperties => _addedProperties;
///
/// Used internally to check if we need to remove a section in the repository to the db
///
internal IEnumerable RemovedProperties => _removedProperties;
///
/// Gets or sets the alias of the Macro
///
[DataMember]
public string Alias
{
get => _alias;
set => SetPropertyValueAndDetectChanges(value.ToCleanString(_shortStringHelper, CleanStringType.Alias), ref _alias, nameof(Alias));
}
///
/// Gets or sets the name of the Macro
///
[DataMember]
public string Name
{
get => _name;
set => SetPropertyValueAndDetectChanges(value, ref _name, nameof(Name));
}
///
/// Gets or sets a boolean indicating whether the Macro can be used in an Editor
///
[DataMember]
public bool UseInEditor
{
get => _useInEditor;
set => SetPropertyValueAndDetectChanges(value, ref _useInEditor, nameof(UseInEditor));
}
///
/// Gets or sets the Cache Duration for the Macro
///
[DataMember]
public int CacheDuration
{
get => _cacheDuration;
set => SetPropertyValueAndDetectChanges(value, ref _cacheDuration, nameof(CacheDuration));
}
///
/// Gets or sets a boolean indicating whether the Macro should be Cached by Page
///
[DataMember]
public bool CacheByPage
{
get => _cacheByPage;
set => SetPropertyValueAndDetectChanges(value, ref _cacheByPage, nameof(CacheByPage));
}
///
/// Gets or sets a boolean indicating whether the Macro should be Cached Personally
///
[DataMember]
public bool CacheByMember
{
get => _cacheByMember;
set => SetPropertyValueAndDetectChanges(value, ref _cacheByMember, nameof(CacheByMember));
}
///
/// Gets or sets a boolean indicating whether the Macro should be rendered in an Editor
///
[DataMember]
public bool DontRender
{
get => _dontRender;
set => SetPropertyValueAndDetectChanges(value, ref _dontRender, nameof(DontRender));
}
///
/// Gets or set the path to the Partial View to render
///
[DataMember]
public string MacroSource
{
get => _macroSource;
set => SetPropertyValueAndDetectChanges(value, ref _macroSource, nameof(MacroSource));
}
///
/// Gets or sets a list of Macro Properties
///
[DataMember]
public MacroPropertyCollection Properties => _properties;
protected override void PerformDeepClone(object clone)
{
base.PerformDeepClone(clone);
var clonedEntity = (Macro)clone;
clonedEntity._addedProperties = new List();
clonedEntity._removedProperties = new List();
clonedEntity._properties = (MacroPropertyCollection)Properties.DeepClone();
//re-assign the event handler
clonedEntity._properties.CollectionChanged += clonedEntity.PropertiesChanged;
}
}
}