using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using Umbraco.Core.IO;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Strings;
namespace Umbraco.Core.Models
{
///
/// Represents a Macro
///
[Serializable]
[DataContract(IsReference = true)]
internal class Macro : Entity, IMacro
{
public Macro()
{
_properties = new MacroPropertyCollection();
_properties.CollectionChanged += PropertiesChanged;
_addedProperties = new List();
_removedProperties = new List();
}
///
/// Creates an item with pre-filled properties
///
///
///
///
///
///
///
///
///
///
///
///
///
public Macro(int id, bool useInEditor, int cacheDuration, string @alias, string name, string controlType, string controlAssembly, string xsltPath, bool cacheByPage, bool cacheByMember, bool dontRender, string scriptPath)
: this()
{
Id = id;
UseInEditor = useInEditor;
CacheDuration = cacheDuration;
Alias = alias.ToCleanString(CleanStringType.Alias);
Name = name;
ControlType = controlType;
ControlAssembly = controlAssembly;
XsltPath = xsltPath;
CacheByPage = cacheByPage;
CacheByMember = cacheByMember;
DontRender = dontRender;
ScriptPath = scriptPath;
}
///
/// Creates an instance for persisting a new item
///
///
///
///
///
///
///
///
///
///
///
///
public Macro(string @alias, string name,
string controlType = "",
string controlAssembly = "",
string xsltPath = "",
string scriptPath = "",
bool cacheByPage = false,
bool cacheByMember = false,
bool dontRender = true,
bool useInEditor = false,
int cacheDuration = 0)
: this()
{
UseInEditor = useInEditor;
CacheDuration = cacheDuration;
Alias = alias.ToCleanString(CleanStringType.Alias);
Name = name;
ControlType = controlType;
ControlAssembly = controlAssembly;
XsltPath = xsltPath;
CacheByPage = cacheByPage;
CacheByMember = cacheByMember;
DontRender = dontRender;
ScriptPath = scriptPath;
}
private string _alias;
private string _name;
private bool _useInEditor;
private int _cacheDuration;
private bool _cacheByPage;
private bool _cacheByMember;
private bool _dontRender;
private string _scriptFile;
private string _scriptAssembly;
private string _scriptPath;
private string _xslt;
private MacroPropertyCollection _properties;
private List _addedProperties;
private List _removedProperties;
private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo(x => x.Alias);
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name);
private static readonly PropertyInfo UseInEditorSelector = ExpressionHelper.GetPropertyInfo(x => x.UseInEditor);
private static readonly PropertyInfo CacheDurationSelector = ExpressionHelper.GetPropertyInfo(x => x.CacheDuration);
private static readonly PropertyInfo CacheByPageSelector = ExpressionHelper.GetPropertyInfo(x => x.CacheByPage);
private static readonly PropertyInfo CacheByMemberSelector = ExpressionHelper.GetPropertyInfo(x => x.CacheByMember);
private static readonly PropertyInfo DontRenderSelector = ExpressionHelper.GetPropertyInfo(x => x.DontRender);
private static readonly PropertyInfo ControlPathSelector = ExpressionHelper.GetPropertyInfo(x => x.ControlType);
private static readonly PropertyInfo ControlAssemblySelector = ExpressionHelper.GetPropertyInfo(x => x.ControlAssembly);
private static readonly PropertyInfo ScriptPathSelector = ExpressionHelper.GetPropertyInfo(x => x.ScriptPath);
private static readonly PropertyInfo XsltPathSelector = ExpressionHelper.GetPropertyInfo(x => x.XsltPath);
private static readonly PropertyInfo PropertiesSelector = ExpressionHelper.GetPropertyInfo(x => x.Properties);
void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(PropertiesSelector);
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(PropertiesSelector);
}
public override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
{
_addedProperties.Clear();
_removedProperties.Clear();
base.ResetDirtyProperties(rememberPreviouslyChangedProperties);
foreach (var prop in Properties)
{
((TracksChangesEntityBase)prop).ResetDirtyProperties(rememberPreviouslyChangedProperties);
}
}
///
/// Used internally to check if we need to add a section in the repository to the db
///
internal IEnumerable AddedProperties
{
get { return _addedProperties; }
}
///
/// Used internally to check if we need to remove a section in the repository to the db
///
internal IEnumerable RemovedProperties
{
get { return _removedProperties; }
}
///
/// Gets or sets the alias of the Macro
///
[DataMember]
public string Alias
{
get { return _alias; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_alias = value.ToCleanString(CleanStringType.Alias);
return _alias;
}, _alias, AliasSelector);
}
}
///
/// Gets or sets the name of the Macro
///
[DataMember]
public string Name
{
get { return _name; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_name = value;
return _name;
}, _name, NameSelector);
}
}
///
/// Gets or sets a boolean indicating whether the Macro can be used in an Editor
///
[DataMember]
public bool UseInEditor
{
get { return _useInEditor; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_useInEditor = value;
return _useInEditor;
}, _useInEditor, UseInEditorSelector);
}
}
///
/// Gets or sets the Cache Duration for the Macro
///
[DataMember]
public int CacheDuration
{
get { return _cacheDuration; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_cacheDuration = value;
return _cacheDuration;
}, _cacheDuration, CacheDurationSelector);
}
}
///
/// Gets or sets a boolean indicating whether the Macro should be Cached by Page
///
[DataMember]
public bool CacheByPage
{
get { return _cacheByPage; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_cacheByPage = value;
return _cacheByPage;
}, _cacheByPage, CacheByPageSelector);
}
}
///
/// Gets or sets a boolean indicating whether the Macro should be Cached Personally
///
[DataMember]
public bool CacheByMember
{
get { return _cacheByMember; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_cacheByMember = value;
return _cacheByMember;
}, _cacheByMember, CacheByMemberSelector);
}
}
///
/// Gets or sets a boolean indicating whether the Macro should be rendered in an Editor
///
[DataMember]
public bool DontRender
{
get { return _dontRender; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_dontRender = value;
return _dontRender;
}, _dontRender, DontRenderSelector);
}
}
///
/// Gets or sets the path to user control or the Control Type to render
///
[DataMember]
public string ControlType
{
get { return _scriptFile; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_scriptFile = value;
return _scriptFile;
}, _scriptFile, ControlPathSelector);
}
}
///
/// Gets or sets the name of the assembly, which should be used by the Macro
///
/// Will usually only be filled if the ControlType is a Usercontrol
[DataMember]
public string ControlAssembly
{
get { return _scriptAssembly; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_scriptAssembly = value;
return _scriptAssembly;
}, _scriptAssembly, ControlAssemblySelector);
}
}
///
/// Gets or set the path to the Python file in use
///
/// Optional: Can only be one of three Script, Python or Xslt
[DataMember]
public string ScriptPath
{
get { return _scriptPath; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_scriptPath = value;
return _scriptPath;
}, _scriptPath, ScriptPathSelector);
}
}
///
/// Gets or sets the path to the Xslt file in use
///
/// Optional: Can only be one of three Script, Python or Xslt
[DataMember]
public string XsltPath
{
get { return _xslt; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_xslt = value;
return _xslt;
}, _xslt, XsltPathSelector);
}
}
///
/// Gets or sets a list of Macro Properties
///
[DataMember]
public MacroPropertyCollection Properties
{
get { return _properties; }
}
public override object DeepClone()
{
var clone = (Macro)base.DeepClone();
clone._addedProperties = new List();
clone._removedProperties = new List();
clone._properties = (MacroPropertyCollection)Properties.DeepClone();
//re-assign the event handler
clone._properties.CollectionChanged += clone.PropertiesChanged;
clone.ResetDirtyProperties(false);
return clone;
}
}
}