Helix Support Sitecore Field Extensions, allowing filtering by Base Templates
namespace Sitecore.Foundation.SitecoreExtensions.FieldTypes | |
{ | |
using System; | |
using System.Linq; | |
using Sitecore.Data.Items; | |
using Sitecore.Foundation.SitecoreExtensions.Extensions; | |
using Sitecore.Web.UI.HtmlControls; | |
using Sitecore.Web.UI.Sheer; | |
using Control = System.Web.UI.Control; | |
/// <summary> | |
/// Supporting class to allow additional paramters to filtered the tree | |
/// </summary> | |
internal class FilteredDataTreeView : DataTreeview | |
{ | |
public string[] ExcludeTemplatesForDisplay | |
{ | |
get { return this.GetViewStateProperty("ExcludeTemplatesForDisplay", null) as string[]; } | |
set { this.SetViewStateProperty("ExcludeTemplatesForDisplay", value, null); } | |
} | |
public string[] ExcludeTemplatesForSelection | |
{ | |
get { return this.GetViewStateProperty("ExcludeTemplatesForSelection", null) as string[]; } | |
set { this.SetViewStateProperty("ExcludeTemplatesForSelection", value, null); } | |
} | |
public string[] IncludeTemplatesForDisplay | |
{ | |
get { return this.GetViewStateProperty("IncludeTemplatesForDisplay", null) as string[]; } | |
set { this.SetViewStateProperty("IncludeTemplatesForDisplay", value, null); } | |
} | |
public string[] IncludeTemplatesForSelection | |
{ | |
get { return this.GetViewStateProperty("IncludeTemplatesForSelection", null) as string[]; } | |
set { this.SetViewStateProperty("IncludeTemplatesForSelection", value, null); } | |
} | |
public string[] IncludeBaseTemplatesForSelection | |
{ | |
get { return this.GetViewStateProperty("IncludeBaseTemplatesForSelections", null) as string[]; } | |
set { this.SetViewStateProperty("IncludeBaseTemplatesForSelections", value, null); } | |
} | |
public override void HandleMessage(Message message) | |
{ | |
if (message.Name == "event:keydown") | |
{ | |
Sitecore.Context.ClientPage.ClientResponse.ClosePopups(false); | |
message.CancelDispatch = true; | |
} | |
else | |
{ | |
base.HandleMessage(message); | |
} | |
} | |
protected override void Populate(DataContext dataContext, Control control, Item root, Item folder, string selectedIDs) | |
{ | |
if (this.ExcludeTemplatesForDisplay == null && this.IncludeTemplatesForDisplay == null) | |
{ | |
base.Populate(dataContext, control, root, folder, selectedIDs); | |
} | |
else | |
{ | |
if (this.IncludeTemplatesForDisplay != null && !this.IncludeTemplatesForDisplay.Contains(root.TemplateName) | |
|| this.ExcludeTemplatesForDisplay != null && this.ExcludeTemplatesForDisplay.Contains(root.TemplateName)) | |
{ | |
return; | |
} | |
base.Populate(dataContext, control, root, folder, selectedIDs); | |
foreach (var dataTreeNode in control.Controls.OfType<DataTreeNode>().Where(p => p.Visible && p.Expandable)) | |
{ | |
if (!String.IsNullOrEmpty(dataTreeNode.ItemID)) | |
{ | |
var obj = dataContext.GetItem(dataTreeNode.ItemID); | |
if (obj == null) | |
{ | |
continue; | |
} | |
var flag = false; | |
foreach (Item child in obj.Children) | |
{ | |
if (this.IncludeTemplatesForDisplay != null && this.IncludeTemplatesForDisplay.Contains(child.TemplateName)) | |
{ | |
flag = true; | |
break; | |
} | |
if (this.ExcludeTemplatesForDisplay != null && !this.ExcludeTemplatesForDisplay.Contains(child.TemplateName)) | |
{ | |
flag = true; | |
break; | |
} | |
} | |
if (!flag) | |
{ | |
dataTreeNode.Expandable = false; | |
dataTreeNode.Expanded = false; | |
} | |
} | |
} | |
} | |
} | |
protected override TreeNode GetTreeNode(Item item, Control parent) | |
{ | |
var treeNode = base.GetTreeNode(item, parent); | |
if (this.ExcludeTemplatesForSelection != null && this.ExcludeTemplatesForSelection.Contains(item.TemplateName)) | |
{ | |
treeNode.Enabled = false; | |
} | |
if (this.ExcludeTemplatesForDisplay != null && this.ExcludeTemplatesForDisplay.Contains(item.TemplateName)) | |
{ | |
treeNode.Visible = false; | |
} | |
if (this.IncludeTemplatesForSelection != null && !this.IncludeTemplatesForSelection.Contains(item.TemplateName)) | |
{ | |
treeNode.Enabled = false; | |
} | |
if (this.IncludeTemplatesForDisplay != null && !this.IncludeTemplatesForDisplay.Contains(item.TemplateName)) | |
{ | |
treeNode.Visible = false; | |
} | |
if (this.IncludeBaseTemplatesForSelection != null && | |
!this.IncludeBaseTemplatesForSelection.Any(t => item.IsDerived(Sitecore.Data.ID.Parse(t)))) | |
{ | |
treeNode.Enabled = false; | |
} | |
return treeNode; | |
} | |
protected override void NodeClicked(Message message, TreeNode node) | |
{ | |
var dataTreeNode = node as DataTreeNode; | |
if (dataTreeNode != null && !dataTreeNode.Enabled) | |
{ | |
Sitecore.Context.ClientPage.ClientResponse.ClosePopups(false); | |
message.CancelDispatch = true; | |
} | |
else | |
{ | |
base.NodeClicked(message, node); | |
} | |
} | |
} | |
} |
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/"> | |
<sitecore> | |
<controlSources> | |
<source patch:before="*[@namespace='Sitecore.Shell.Applications.ContentEditor']" mode="on" | |
namespace="Sitecore.Foundation.SitecoreExtensions.FieldTypes" assembly="Sitecore.Foundation.SitecoreExtensions" prefix="content" /> | |
</controlSources> | |
</sitecore> | |
</configuration> |
namespace Sitecore.Foundation.SitecoreExtensions.FieldTypes | |
{ | |
using System; | |
using System.Web.UI.WebControls; | |
using Sitecore; | |
using Sitecore.Diagnostics; | |
using Sitecore.Globalization; | |
using Sitecore.Web.UI.HtmlControls; | |
using Sitecore.Web.UI.Sheer; | |
/// <summary> | |
/// Extends the <see cref="Sitecore.Shell.Applications.ContentEditor.Tree"/> by | |
/// adding in support to filter the selectable templates in a Tree by the base templates | |
/// Syntax for the Field Source: Datasource={Insert Sitecore Query or Item Path}&IncludeBaseTemplatesForSelection={Insert GUID} | |
/// </summary> | |
public class Tree : Sitecore.Shell.Applications.ContentEditor.Tree | |
{ | |
#region Additional Fields for Filtering | |
public string ExcludeTemplatesForDisplay | |
{ | |
get | |
{ | |
return this.GetViewStateString("ExcludeTemplatesForDisplay"); | |
} | |
set | |
{ | |
Assert.ArgumentNotNull(value, "value"); | |
this.SetViewStateString("ExcludeTemplatesForDisplay", value); | |
} | |
} | |
public string ExcludeTemplatesForSelection | |
{ | |
get | |
{ | |
return this.GetViewStateString("ExcludeTemplatesForSelection"); | |
} | |
set | |
{ | |
Assert.ArgumentNotNull(value, "value"); | |
this.SetViewStateString("ExcludeTemplatesForSelection", value); | |
} | |
} | |
public string IncludeTemplatesForDisplay | |
{ | |
get | |
{ | |
return this.GetViewStateString("IncludeTemplatesForDisplay"); | |
} | |
set | |
{ | |
Assert.ArgumentNotNull(value, "value"); | |
this.SetViewStateString("IncludeTemplatesForDisplay", value); | |
} | |
} | |
public string IncludeTemplatesForSelection | |
{ | |
get | |
{ | |
return this.GetViewStateString("IncludeTemplatesForSelection"); | |
} | |
set | |
{ | |
Assert.ArgumentNotNull(value, "value"); | |
this.SetViewStateString("IncludeTemplatesForSelection", value); | |
} | |
} | |
public string IncludeBaseTemplatesForSelection | |
{ | |
get | |
{ | |
return this.GetViewStateString("IncludeBaseTemplatesForSelection"); | |
} | |
set | |
{ | |
Assert.ArgumentNotNull(value, "value"); | |
this.SetViewStateString("IncludeBaseTemplatesForSelection", value); | |
} | |
} | |
#endregion | |
/// <summary> | |
/// Overrides the source property to pull out the DataSource | |
/// and filterable properties | |
/// </summary> | |
public new string Source | |
{ | |
get { return base.Source; } | |
set | |
{ | |
if (value == null) | |
{ | |
base.Source = value; | |
} | |
else | |
{ | |
var contextItem = Client.ContentDatabase.GetItem(this.ItemID); | |
var datasourceValue = StringUtil.ExtractParameter("DataSource", value).Trim(); | |
if (datasourceValue.StartsWith("query:")) | |
{ | |
this.ExcludeTemplatesForSelection = StringUtil.ExtractParameter("ExcludeTemplatesForSelection", value).Trim(); | |
this.IncludeTemplatesForSelection = StringUtil.ExtractParameter("IncludeTemplatesForSelection", value).Trim(); | |
this.IncludeTemplatesForDisplay = StringUtil.ExtractParameter("IncludeTemplatesForDisplay", value).Trim(); | |
this.ExcludeTemplatesForDisplay = StringUtil.ExtractParameter("ExcludeTemplatesForDisplay", value).Trim(); | |
this.IncludeBaseTemplatesForSelection = StringUtil.ExtractParameter("IncludeBaseTemplatesForSelection", value).Trim(); | |
var queryItem = contextItem.Axes.SelectSingleItem(datasourceValue.Substring("query:".Length)); | |
if (queryItem != null) | |
{ | |
base.Source = queryItem.ID.ToString(); | |
} | |
} | |
else if (value.StartsWith("query:")) | |
{ | |
var queryItem = contextItem.Axes.SelectSingleItem(value.Substring("query:".Length)); | |
if (queryItem != null) | |
{ | |
base.Source = queryItem.ID.ToString(); | |
} | |
} | |
else | |
{ | |
base.Source = value; | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// Overrides the <see cref="DropDown"/>, and changing the DataTreeView to use a FilteredTreeView | |
/// </summary> | |
protected override void DropDown() | |
{ | |
base.DropDown(); | |
if (!string.IsNullOrEmpty(this.Value)) | |
{ | |
var dataContext = Sitecore.Context.ClientPage.FindSubControl(this.DataContext) as DataContext; | |
Assert.IsNotNull(dataContext, typeof(DataContext), "Datacontext \"{0}\" not found.", (object)this.DataContext); | |
dataContext.Folder = this.Value; | |
} | |
var hiddenHolder = UIUtil.GetHiddenHolder(this); | |
DataTreeNode dataTreeNode = null; | |
var scrollbox = new Scrollbox(); | |
Sitecore.Context.ClientPage.AddControl(hiddenHolder, scrollbox); | |
scrollbox.Width = 300; | |
scrollbox.Height = 400; | |
var dataTreeview = this.GetDataTreeview(); | |
dataTreeview.Class = "scTreeview scPopupTree"; | |
dataTreeview.DataContext = this.DataContext; | |
dataTreeview.ID = this.ID + "_treeview"; | |
dataTreeview.AllowDragging = false; | |
if (this.AllowNone) | |
{ | |
dataTreeNode = new DataTreeNode(); | |
Sitecore.Context.ClientPage.AddControl(dataTreeview, dataTreeNode); | |
dataTreeNode.ID = this.ID + "_none"; | |
dataTreeNode.Header = Translate.Text("[none]"); | |
dataTreeNode.Expandable = false; | |
dataTreeNode.Expanded = false; | |
dataTreeNode.Value = "none"; | |
dataTreeNode.Icon = "Applications/16x16/forbidden.png"; | |
} | |
Sitecore.Context.ClientPage.AddControl(scrollbox, dataTreeview); | |
dataTreeview.Width = new Unit(100.0, UnitType.Percentage); | |
dataTreeview.Click = this.ID + ".Select"; | |
dataTreeview.DataContext = this.DataContext; | |
if (string.IsNullOrEmpty(this.Value) && dataTreeNode != null) | |
{ | |
dataTreeview.ClearSelection(); | |
dataTreeNode.Selected = true; | |
} | |
SheerResponse.ShowPopup(this.ID, "below-right", scrollbox); | |
} | |
protected virtual DataTreeview GetDataTreeview() | |
{ | |
return new FilteredDataTreeView | |
{ | |
ExcludeTemplatesForDisplay = Tree.GetValues(this.ExcludeTemplatesForDisplay), | |
ExcludeTemplatesForSelection = Tree.GetValues(this.ExcludeTemplatesForSelection), | |
IncludeTemplatesForDisplay = Tree.GetValues(this.IncludeTemplatesForDisplay), | |
IncludeTemplatesForSelection = Tree.GetValues(this.IncludeTemplatesForSelection), | |
IncludeBaseTemplatesForSelection = Tree.GetValues(this.IncludeBaseTemplatesForSelection) | |
}; | |
} | |
private static string[] GetValues(string templates) | |
{ | |
if (String.IsNullOrEmpty(templates)) | |
{ | |
return null; | |
} | |
return templates.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); | |
} | |
} | |
} |
namespace Sitecore.Foundation.SitecoreExtensions.FieldTypes | |
{ | |
using System; | |
using System.ComponentModel; | |
using System.Linq; | |
using Sitecore; | |
using Sitecore.Data; | |
using Sitecore.Data.Items; | |
using Sitecore.Diagnostics; | |
using Sitecore.Foundation.SitecoreExtensions.Extensions; | |
using Sitecore.Globalization; | |
using Sitecore.Web.UI.HtmlControls; | |
using Sitecore.Web.UI.Sheer; | |
using Sitecore.Web.UI.WebControls; | |
/// <summary> | |
/// Extends the <see cref="Sitecore.Shell.Applications.ContentEditor.TreeList"/> by | |
/// adding in support to filter the selectable templates in a Tree by the base templates | |
/// Syntax for the Field Source: Datasource={Insert Sitecore Query or Item Path}&IncludeBaseTemplatesForSelection={Insert GUID} | |
/// </summary> | |
public class TreeList : Sitecore.Shell.Applications.ContentEditor.TreeList | |
{ | |
#region Additional Fields for Filtering | |
[Category("Data")] | |
[Description("Comma separated list of item ids.")] | |
public string IncludeBaseTemplatesForSelection | |
{ | |
get | |
{ | |
return this.GetViewStateString("IncludeBaseTemplatesForSelection"); | |
} | |
set | |
{ | |
Assert.ArgumentNotNull(value, "value"); | |
this.SetViewStateString("IncludeBaseTemplatesForSelection", value); | |
} | |
} | |
#endregion | |
/// <summary> | |
/// Overrides the source property to pull out DataSource property | |
/// </summary> | |
public new string Source | |
{ | |
get | |
{ | |
return base.Source; | |
} | |
set | |
{ | |
if (value == null) | |
{ | |
base.Source = null; | |
} | |
else | |
{ | |
var datasourceValue = StringUtil.ExtractParameter("DataSource", value).Trim(); | |
if (datasourceValue.StartsWith("query:")) | |
{ | |
base.Source = value.Replace(datasourceValue, this.ResolveQuery(datasourceValue)); | |
} | |
else if (value.StartsWith("query:")) | |
{ | |
base.Source = this.ResolveQuery(value); | |
} | |
else | |
{ | |
base.Source = value; | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// Overrides the <see cref="OnLoad"/> method to set our custom properties | |
/// </summary> | |
/// <param name="args"></param> | |
protected override void OnLoad(EventArgs args) | |
{ | |
if (!Sitecore.Context.ClientPage.IsEvent) | |
{ | |
this.SetProperties(); | |
} | |
base.OnLoad(args); | |
} | |
/// <summary> | |
/// Overrides the <see cref="Add"/> method to execute our custom logic | |
/// and determine if the selected item in the tree inherits from | |
/// a configured base template | |
/// </summary> | |
protected new void Add() | |
{ | |
if (this.Disabled) | |
{ | |
return; | |
} | |
var viewStateString = this.GetViewStateString("ID"); | |
var treeviewEx = this.FindControl(viewStateString + "_all") as TreeviewEx; | |
Assert.IsNotNull(treeviewEx, typeof(DataTreeview)); | |
var listbox = this.FindControl(viewStateString + "_selected") as Listbox; | |
Assert.IsNotNull(listbox, typeof(Listbox)); | |
var selectionItem = treeviewEx.GetSelectionItem(Language.Parse(this.ItemLanguage), Sitecore.Data.Version.Latest); | |
if (selectionItem == null) | |
{ | |
SheerResponse.Alert("Select an item in the Content Tree."); | |
} | |
else | |
{ | |
if (!this.HasIncludeBaseTemplatesForSelection(selectionItem)) | |
{ | |
return; | |
} | |
base.Add(); | |
} | |
} | |
/// <summary> | |
/// Resolves the Sitecore Query | |
/// </summary> | |
/// <param name="query">The Sitecore Query</param> | |
/// <returns></returns> | |
protected virtual string ResolveQuery(string query) | |
{ | |
var contextItem = Sitecore.Context.ContentDatabase.Items[this.ItemID]; | |
/** | |
* This area can be an additional extension point to allow for 'tokens' | |
* within the query, such as $site or $home. | |
*/ | |
var obj = contextItem?.Axes.SelectSingleItem(query.Substring("query:".Length)); | |
return obj != null | |
? obj.Paths.FullPath | |
: String.Empty; | |
} | |
private void SetProperties() | |
{ | |
this.IncludeBaseTemplatesForSelection = StringUtil.ExtractParameter("IncludeBaseTemplatesForSelection", this.Source).Trim(); | |
} | |
private bool HasIncludeBaseTemplatesForSelection(Item item) | |
{ | |
if (String.IsNullOrEmpty(this.IncludeBaseTemplatesForSelection)) | |
{ | |
return true; | |
} | |
var items = this.IncludeBaseTemplatesForSelection.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); | |
if (!items.Any()) | |
{ | |
return true; | |
} | |
return items.Any(id => item.IsDerived(new ID(id))); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment