265 lines
10 KiB
C#
265 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Web.UI;
|
|
using System.Web.UI.WebControls;
|
|
|
|
using umbraco.cms.businesslogic.datatype; // DefaultData
|
|
using umbraco.cms.businesslogic.property; // Property
|
|
using umbraco.cms.businesslogic.relation; // RelationType
|
|
using umbraco.interfaces; // IDataEditor
|
|
using UmbracoContent = umbraco.cms.businesslogic.Content; // UmbracoContent defined here so as to differentiate with System.Web.UI.WebControls.Content
|
|
|
|
namespace umbraco.editorControls.PickerRelations
|
|
{
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public class PickerRelationsDataEditor : CompositeControl, IDataEditor
|
|
{
|
|
/// <summary>
|
|
/// value stored by a datatype instance
|
|
/// </summary>
|
|
private IData data;
|
|
|
|
/// <summary>
|
|
/// configuration options for this datatype, as defined by the PreValueEditor
|
|
/// </summary>
|
|
private PickerRelationsOptions options;
|
|
|
|
/// <summary>
|
|
/// Literal used to render status (Enabled || Disabled)
|
|
/// this datatype is only enabled and active if it can find the property alias on the current node (as defined in PreValueEditor) and
|
|
/// the relation type parent object type (or child if reverse index used) matches the object type of the current node which this datatype is on
|
|
/// </summary>
|
|
private Literal statusLiteral = new Literal();
|
|
|
|
|
|
private Literal jsLiteral = new Literal();
|
|
|
|
/// <summary>
|
|
/// Gets a value indicating whether this is an RTE - this Property expected by Umbraco
|
|
/// </summary>
|
|
public virtual bool TreatAsRichTextEditor
|
|
{
|
|
get { return false; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a value indicating whether the label should be shown when editing - this Property exected by Umbraco
|
|
/// </summary>
|
|
public virtual bool ShowLabel
|
|
{
|
|
get { return true; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the DataEditor - Property expected by Umbraco
|
|
/// </summary>
|
|
public Control Editor { get { return this; } }
|
|
|
|
/// <summary>
|
|
/// Gets the id of the current (content || media || member) node on which this datatype is a property
|
|
/// </summary>
|
|
private int CurrentContentId
|
|
{
|
|
get
|
|
{
|
|
return ((umbraco.cms.businesslogic.datatype.DefaultData)this.data).NodeId;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the UmbracoObjectType on which this datatype is a property of
|
|
/// </summary>
|
|
private uQuery.UmbracoObjectType CurrentContextObjectType
|
|
{
|
|
get
|
|
{
|
|
return uQuery.GetUmbracoObjectType(
|
|
uQuery.SqlHelper.ExecuteScalar<Guid>(
|
|
"SELECT nodeObjectType FROM umbracoNode WHERE id = @id",
|
|
uQuery.SqlHelper.CreateParameter("@id", this.CurrentContentId)));
|
|
}
|
|
}
|
|
|
|
/////// NOT CURRENTLY USED, BUT MIGHT BE USEFUL TO MARK BIDIRECTIONAL RELATIONS
|
|
/////// <summary>
|
|
/////// string to identify a particular instance of this datatype
|
|
/////// </summary>
|
|
////private string InstanceIdentifier
|
|
////{
|
|
//// get
|
|
//// {
|
|
//// Property pickerRelationsProperty = new Property(((DefaultData)this.data).PropertyId);
|
|
//// return "[" + pickerRelationsProperty.PropertyType.Id.ToString() + "]";
|
|
//// }
|
|
////}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of PickerRelationsDataEditor
|
|
/// </summary>
|
|
/// <param name="data">data stored by this instance of this datatype (not currently used)</param>
|
|
/// <param name="options">configuration options for this datatype as set by the PreValueEditor</param>
|
|
internal PickerRelationsDataEditor(IData data, PickerRelationsOptions options)
|
|
{
|
|
this.data = data;
|
|
this.options = options;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates the child controls
|
|
/// </summary>
|
|
protected override void CreateChildControls()
|
|
{
|
|
this.statusLiteral.ID = "pickerRelations";
|
|
this.Controls.Add(this.statusLiteral); // displays if this datatype is valid in this context, and if so, which pickerProperty and relationtype it wires up
|
|
this.Controls.Add(this.jsLiteral);
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="e"></param>
|
|
protected override void OnLoad(EventArgs e)
|
|
{
|
|
base.OnLoad(e);
|
|
this.EnsureChildControls();
|
|
|
|
this.statusLiteral.Text = "<span id=\"" + this.statusLiteral.ClientID + "\">";
|
|
|
|
try
|
|
{
|
|
this.statusLiteral.Text += "Mapping: " + this.GetMappingDetails();
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
this.statusLiteral.Text += "Error: " + ex.Message;
|
|
}
|
|
|
|
this.statusLiteral.Text += "</span>";
|
|
|
|
if (this.options.HideDataEditor)
|
|
{
|
|
this.jsLiteral.Text = @"
|
|
<script type=""text/javascript"">
|
|
jQuery(document).ready(function () {
|
|
jQuery('span#" + this.statusLiteral.ClientID + @"').parents('div.propertypane').first().hide();
|
|
});
|
|
</script>";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called by Umbraco when saving the node, this datatype doens't do anythign here, but with an event handler instead,
|
|
/// as needs to know the saved values of a sibling pickerProperty
|
|
/// </summary>
|
|
public void Save()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// returns a string "Property '[propertyAlias]' with RelationType '[relationTypeName]"
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private string GetMappingDetails()
|
|
{
|
|
string mappingDetails = string.Empty;
|
|
|
|
UmbracoContent currentContentNode = new UmbracoContent(this.CurrentContentId);
|
|
Property pickerProperty = currentContentNode.getProperty(this.options.PropertyAlias);
|
|
|
|
if (pickerProperty != null)
|
|
{
|
|
RelationType relationType = new RelationType(this.options.RelationTypeId); // Does it still exist ? TODO: check
|
|
|
|
if (this.IsContextUmbracoObjectTypeValid(this.CurrentContextObjectType, relationType))
|
|
{
|
|
mappingDetails = "Property '<strong>" + pickerProperty.PropertyType.Name + "</strong>' with " +
|
|
"Relation Type '<strong>" + relationType.Name + "</strong>'";
|
|
|
|
if(this.options.ReverseIndexing)
|
|
{
|
|
mappingDetails += " <i>(Reverse Index)</i>";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Conflict with this Content Object Type and that expected by the Relation Type '" + relationType.Name + "'");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Can't find a Property with the Alias '" + this.options.PropertyAlias + "'");
|
|
}
|
|
|
|
return mappingDetails;
|
|
}
|
|
|
|
/// <summary>
|
|
/// returns the UmbracoObjectType associated as defined by the supplied relation type, and if reverse indexing has been enabled
|
|
/// </summary>
|
|
/// <param name="relationType">associated RealationType</param>
|
|
/// <returns></returns>
|
|
public uQuery.UmbracoObjectType GetPickerUmbracoObjectType(RelationType relationType)
|
|
{
|
|
uQuery.UmbracoObjectType pickerUmbracoObjectType = uQuery.UmbracoObjectType.Unknown;
|
|
|
|
if (!relationType.Dual && this.options.ReverseIndexing)
|
|
{
|
|
pickerUmbracoObjectType = relationType.GetParentUmbracoObjectType();
|
|
}
|
|
else
|
|
{
|
|
pickerUmbracoObjectType = relationType.GetChildUmbracoObjectType();
|
|
}
|
|
|
|
return pickerUmbracoObjectType;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check to see if the content id side of the relation type is valid (doesn't check the node picker id side)
|
|
/// </summary>
|
|
/// <param name="contextUmbracoObjectType">Type of the content object (content/ media or member)</param>
|
|
/// <param name="relationType">Type of the relation.</param>
|
|
/// <returns>
|
|
/// <c>true</c> if [is content object type valid] [the specified content object type]; otherwise, <c>false</c>.
|
|
/// </returns>
|
|
public bool IsContextUmbracoObjectTypeValid(uQuery.UmbracoObjectType contextUmbracoObjectType, RelationType relationType)
|
|
{
|
|
bool isContextObjectTypeValid = false;
|
|
|
|
if (!relationType.Dual && this.options.ReverseIndexing)
|
|
{
|
|
// expects the current context to be the child in the relation
|
|
if (contextUmbracoObjectType == relationType.GetChildUmbracoObjectType())
|
|
{
|
|
isContextObjectTypeValid = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// expects the current context to be the parent in the relation
|
|
if (contextUmbracoObjectType == relationType.GetParentUmbracoObjectType())
|
|
{
|
|
isContextObjectTypeValid = true;
|
|
}
|
|
}
|
|
|
|
return isContextObjectTypeValid;
|
|
}
|
|
|
|
///// <summary>
|
|
///// Insted of rendering the current name of this property, use a consistant label
|
|
///// </summary>
|
|
///// <param name="writer"></param>
|
|
//protected override void Render(HtmlTextWriter writer)
|
|
//{
|
|
// writer.WriteLine("<div class='propertyItemheader'>MultiNode Relations</div>");
|
|
// writer.WriteLine("<div class='propertyItemContent'>");
|
|
// base.Render(writer);
|
|
// writer.WriteLine("</div>");
|
|
//}
|
|
}
|
|
}
|