using System;
using System.Collections;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using CMS.ExtendedControls;
using CMS.GlobalHelper;
using CMS.SettingsProvider;
using CMS.UIControls;
using CMS.SiteProvider;
using CMS.FormControls;
using CMS.CMSHelper;
namespace CMS.Ecommerce
{
///
/// Base class of the option category sku selector control.
///
public class ProductOptionSelector : CMSUserControl
{
#region "Variables"
private int mOptionCategoryId = 0;
private bool mShowOptionCategoryName = true;
private bool mShowOptionCategoryDescription = true;
private bool mUseDefaultCurrency = false;
private bool mShowPriceIncludingTax = false;
private Control mSelectionControl = null;
private OptionCategoryInfo mOptionCategory = null;
private ShoppingCartInfo mLocalShoppingCartObj = null;
private Hashtable mProductOptions = null;
private InfoDataSet mProductOptionsData = null;
private int mTextOptionSKUID = 0;
#endregion
#region "Public properties"
///
/// SKU ID
///
public int SKUID
{
get;
set;
}
///
/// Option category ID
///
public int OptionCategoryId
{
get
{
if ((mOptionCategoryId == 0) && (OptionCategory != null))
{
mOptionCategoryId = OptionCategory.CategoryID;
}
return mOptionCategoryId;
}
set
{
// Force loading new selection control
//mSelectionControl = null;
// Force creating new option category object
mOptionCategory = null;
mOptionCategoryId = value;
}
}
///
/// Indicates whether option category name should be displayed to the user.
///
public bool ShowOptionCategoryName
{
get
{
return mShowOptionCategoryName;
}
set
{
mShowOptionCategoryName = value;
}
}
///
/// Indicates whether option category description should be displayed to the user.
///
public bool ShowOptionCategoryDescription
{
get
{
return mShowOptionCategoryDescription;
}
set
{
mShowOptionCategoryDescription = value;
}
}
///
/// Selection control according to the current option category selection type.
///
public Control SelectionControl
{
get
{
if (mSelectionControl == null)
{
mSelectionControl = GetSelectionControl();
}
return mSelectionControl;
}
}
///
/// Option category object. It is loaded from option category datarow by default, if it is not specified it is loaded by option category id.
///
public OptionCategoryInfo OptionCategory
{
get
{
if (mOptionCategory == null)
{
mOptionCategory = OptionCategoryInfoProvider.GetOptionCategoryInfo(mOptionCategoryId);
}
return mOptionCategory;
}
set
{
mOptionCategory = value;
}
}
///
/// Shopping cart object required for price formatting. Use this property when in CMSDesk.
///
public ShoppingCartInfo LocalShoppingCartObj
{
get
{
return mLocalShoppingCartObj;
}
set
{
mLocalShoppingCartObj = value;
}
}
///
/// TRUE - default currency is used for price formatting and no discounts and taxes are applied to price, by default it is set to FALSE.
///
public bool UseDefaultCurrency
{
get
{
return mUseDefaultCurrency;
}
set
{
mUseDefaultCurrency = value;
}
}
///
/// TRUE - product option price is displayed including tax, FALSE - product option price is displayed without tax.
///
public bool ShowPriceIncludingTax
{
get
{
return mShowPriceIncludingTax;
}
set
{
mShowPriceIncludingTax = value;
}
}
///
/// SKU data of all product options of the current option category
///
public Hashtable ProductOptions
{
get
{
if (mProductOptions == null)
{
mProductOptions = GetProductOptions();
}
return mProductOptions;
}
}
#endregion
#region "Private properties"
public int TextOptionSKUID
{
get
{
if (mTextOptionSKUID <= 0)
{
if (!DataHelper.DataSourceIsEmpty(ProductOptionsData))
{
mTextOptionSKUID = ValidationHelper.GetInteger(ProductOptionsData.Items[0].SKUID, 0);
}
}
return mTextOptionSKUID;
}
set
{
mTextOptionSKUID = value;
}
}
#endregion
#region "Public methods"
///
/// Reloads selection control according to the option category selection type.
///
public void LoadCategorySelectionControl()
{
mSelectionControl = GetSelectionControl();
}
///
/// Reloads selection control data according to the option category data.
///
public void ReloadData()
{
DebugHelper.SetContext("ProductOptionSelector");
// Load actual product options
LoadSKUOptions();
// Mark default product options
SetDefaultSKUOptions();
DebugHelper.ReleaseContext();
}
///
/// Gets selected product options from the selection control.
///
public string GetSelectedSKUOptions()
{
if (SelectionControl != null)
{
// Dropdown list, Radiobutton list - single selection
if ((SelectionControl.GetType() == typeof(LocalizedDropDownList)) ||
(SelectionControl.GetType() == typeof(LocalizedRadioButtonList)))
{
return ((ListControl)SelectionControl).SelectedValue;
}
// Checkbox list - multiple selection
else if (SelectionControl.GetType() == typeof(LocalizedCheckBoxList))
{
string result = "";
foreach (ListItem item in ((CheckBoxList)SelectionControl).Items)
{
if (item.Selected)
{
result += item.Value + ",";
}
}
return result.TrimEnd(',');
}
// TextBox
else if (SelectionControl is TextBox)
{
return ((TextBox)(SelectionControl)).Text;
}
// Form control
else if (SelectionControl is FormEngineUserControl)
{
FormEngineUserControl fc = SelectionControl as FormEngineUserControl;
return ValidationHelper.GetString(fc.Value, string.Empty);
}
}
return null;
}
public List GetSelectedOptionsParameters()
{
List options = new List();
ShoppingCartItemParameters param = null;
if (SelectionControl != null)
{
// Dropdown list, Radiobutton list - single selection
if ((SelectionControl.GetType() == typeof(LocalizedDropDownList)) ||
(SelectionControl.GetType() == typeof(LocalizedRadioButtonList)))
{
param = new ShoppingCartItemParameters();
param.SKUID = ValidationHelper.GetInteger(((ListControl)SelectionControl).SelectedValue, 0);
if (param.SKUID > 0)
{
options.Add(param);
}
}
// Checkbox list - multiple selection
else if (SelectionControl.GetType() == typeof(LocalizedCheckBoxList))
{
foreach (ListItem item in ((CheckBoxList)SelectionControl).Items)
{
if (item.Selected)
{
param = new ShoppingCartItemParameters();
param.SKUID = ValidationHelper.GetInteger(item.Value, 0);
if (param.SKUID > 0)
{
options.Add(param);
}
}
}
}
else if (SelectionControl is TextBox)
{
// Bind data
if (SelectionControl is TextBoxWithLabel)
{
if (TextOptionSKUID > 0)
{
param = new ShoppingCartItemParameters();
param.SKUID = TextOptionSKUID;
param.Text = ((TextBox)(SelectionControl)).Text;
if (param.SKUID > 0)
{
options.Add(param);
}
}
}
}
else if (SelectionControl is FormEngineUserControl)
{
FormEngineUserControl fc = SelectionControl as FormEngineUserControl;
string val = ValidationHelper.GetString(fc.Value, string.Empty);
int[] optionsIds = ValidationHelper.GetIntegers(val.Split(','), 0);
// Add selected options to parameters
foreach (int id in optionsIds)
{
if (id > 0)
{
param = new ShoppingCartItemParameters();
param.SKUID = id;
options.Add(param);
}
}
}
}
return options;
}
///
/// Returns TRUE when selection control is empty or only '(none)' record is included, otherwise returns FALSE.
///
public bool IsSelectionControlEmpty()
{
if (SelectionControl != null)
{
// Text type
TextBox tb = SelectionControl as TextBox;
if (tb != null)
{
return string.IsNullOrEmpty(tb.Text);
}
// List control types
ListControl list = SelectionControl as ListControl;
if (list != null)
{
bool noItems = (list.Items.Count == 0);
bool onlyNoneRecord = ((list.Items.Count == 1) && (list.Items.FindByValue("0") != null));
return (noItems || onlyNoneRecord);
}
// Form controls
FormEngineUserControl formControl = SelectionControl as FormEngineUserControl;
if (formControl != null)
{
if (ValidationHelper.GetInteger(formControl.Value, 1) <= 0)
{
return true;
}
return (formControl.Value == null) || string.IsNullOrEmpty(formControl.Value.ToString());
}
return false;
}
return true;
}
///
/// Returns true if there is a choice of values in selection control.
///
public bool HasSelectableOptions()
{
if (SelectionControl != null)
{
// Text type or form control
if ((SelectionControl is TextBox) || (SelectionControl is FormEngineUserControl))
{
return true;
}
return !IsSelectionControlEmpty();
}
return true;
}
///
/// Validates selected/entered product option. If it is valid, returns true, otherwise returns false.
///
public virtual bool IsValid()
{
return true;
}
#endregion
#region "Private methods"
///
/// Returns initialized selection control according to the specified selection type.
///
private Control GetSelectionControl()
{
if (OptionCategory != null)
{
switch (OptionCategory.CategorySelectionType)
{
// Dropdownlist
case OptionCategorySelectionTypeEnum.Dropdownlist:
LocalizedDropDownList dropDown = new LocalizedDropDownList();
dropDown.ID = "dropdown";
dropDown.CssClass = "DropDownField";
dropDown.DataTextField = "SKUName";
dropDown.DataValueField = "SKUID";
dropDown.DataBound += new EventHandler(SelectionControl_DataBound);
return dropDown;
// Checkbox list with horizontal direction
case OptionCategorySelectionTypeEnum.CheckBoxesHorizontal:
LocalizedCheckBoxList boxListHorizontal = new LocalizedCheckBoxList();
boxListHorizontal.ID = "chkHorizontal";
boxListHorizontal.RepeatDirection = RepeatDirection.Horizontal;
boxListHorizontal.DataTextField = "SKUName";
boxListHorizontal.DataValueField = "SKUID";
boxListHorizontal.DataBound += new EventHandler(SelectionControl_DataBound);
return boxListHorizontal;
// Checkbox list with vertical direction
case OptionCategorySelectionTypeEnum.CheckBoxesVertical:
LocalizedCheckBoxList boxListVertical = new LocalizedCheckBoxList();
boxListVertical.ID = "chkVertical";
boxListVertical.RepeatDirection = RepeatDirection.Vertical;
boxListVertical.DataTextField = "SKUName";
boxListVertical.DataValueField = "SKUID";
boxListVertical.DataBound += new EventHandler(SelectionControl_DataBound);
return boxListVertical;
// Radiobuton list with horizontal direction
case OptionCategorySelectionTypeEnum.RadioButtonsHorizontal:
LocalizedRadioButtonList buttonListHorizontal = new LocalizedRadioButtonList();
buttonListHorizontal.ID = "radHorizontal";
buttonListHorizontal.RepeatDirection = RepeatDirection.Horizontal;
buttonListHorizontal.DataTextField = "SKUName";
buttonListHorizontal.DataValueField = "SKUID";
buttonListHorizontal.DataBound += new EventHandler(SelectionControl_DataBound);
return buttonListHorizontal;
// Radiobuton list with vertical direction
case OptionCategorySelectionTypeEnum.RadioButtonsVertical:
LocalizedRadioButtonList buttonListVertical = new LocalizedRadioButtonList();
buttonListVertical.ID = "radVertical";
buttonListVertical.RepeatDirection = RepeatDirection.Vertical;
buttonListVertical.DataTextField = "SKUName";
buttonListVertical.DataValueField = "SKUID";
buttonListVertical.DataBound += new EventHandler(SelectionControl_DataBound);
return buttonListVertical;
// Text box
case OptionCategorySelectionTypeEnum.TextBox:
TextBox text = new TextBoxWithLabel();
text.ID = "txtText";
text.CssClass = "TextBoxField";
return text;
// Text area
case OptionCategorySelectionTypeEnum.TextArea:
TextBox textarea = new TextBoxWithLabel();
textarea.ID = "txtArea";
textarea.CssClass = "TextAreaField";
textarea.TextMode = TextBoxMode.MultiLine;
return textarea;
// Form control
case OptionCategorySelectionTypeEnum.FormControl:
if (!string.IsNullOrEmpty(OptionCategory.CategoryFormControlName))
{
FormUserControlInfo fui = FormUserControlInfoProvider.GetFormUserControlInfo(OptionCategory.CategoryFormControlName);
if (fui != null)
{
// Load control
FormEngineUserControl fc = (FormEngineUserControl)Page.LoadUserControl(FormUserControlInfoProvider.GetFormUserControlUrl(fui));
if (fc != null)
{
fc.ID = "FormControlField";
return fc;
}
}
}
return null;
}
}
return null;
}
private void SelectionControl_DataBound(object sender, EventArgs e)
{
if (OptionCategory.CategoryDisplayPrice)
{
// Check if datasource has data
if (!DataHelper.DataSourceIsEmpty(((ListControl)sender).DataSource))
{
foreach (DataRow row in ((DataSet)((ListControl)sender).DataSource).Tables[0].Rows)
{
int skuId = ValidationHelper.GetInteger(row["SKUId"], 0);
ListItem item = ((ListControl)sender).Items.FindByValue(skuId.ToString());
// Append price to option's text
if (item != null)
{
item.Text += GetPrice(row);
}
}
}
}
}
///
/// Recalculates and formats price.
///
/// Data row to create price label for.
private string GetPrice(DataRow row)
{
SKUInfo sku = new SKUInfo(row);
CurrencyInfo currency = null;
double price = 0;
// Use product option currency
if (UseDefaultCurrency)
{
// Get site main currency
currency = CurrencyInfoProvider.GetMainCurrency(sku.SKUSiteID);
// Get product price
price = sku.SKUPrice;
}
// Use cart currency
else
{
// Get cart currency
currency = LocalShoppingCartObj.Currency;
// Get price in site main currency
price = SKUInfoProvider.GetSKUPrice(sku, LocalShoppingCartObj, true, ShowPriceIncludingTax);
// Get price in cart currency
price = LocalShoppingCartObj.ApplyExchangeRate(price);
}
string preffix = (price >= 0) ? "+ " : "- ";
price = Math.Abs(price);
// Round price
price = CurrencyInfoProvider.RoundTo(price, currency);
// Format price
string formattedPrice = CurrencyInfoProvider.GetFormattedPrice(price, currency);
return " (" + preffix + formattedPrice + ")";
}
///
/// Sets category default options as 'Selected' in selection control.
///
private void SetDefaultSKUOptions()
{
if ((SelectionControl != null) && (OptionCategory != null))
{
// Dropdown list - single selection
// Radiobutton list - single selection
if ((SelectionControl is LocalizedDropDownList) ||
(SelectionControl is LocalizedRadioButtonList))
{
try
{
((ListControl)SelectionControl).SelectedValue = OptionCategory.CategoryDefaultOptions;
}
catch
{
}
}
// Checkbox list - multiple selection
else if (SelectionControl is LocalizedCheckBoxList)
{
try
{
if (OptionCategory.CategoryDefaultOptions != "")
{
foreach (string skuId in OptionCategory.CategoryDefaultOptions.Split(','))
{
// Ensure value is not empty
string value = (skuId != "") ? skuId : "0";
ListItem item = ((CheckBoxList)SelectionControl).Items.FindByValue(value);
if (item != null)
{
item.Selected = true;
}
}
}
}
catch
{
}
}
// Text type
else if (SelectionControl is TextBoxWithLabel)
{
TextBoxWithLabel tb = SelectionControl as TextBoxWithLabel;
tb.Text = OptionCategory.CategoryDefaultOptions;
}
// Form control
else if (SelectionControl is FormEngineUserControl)
{
((FormEngineUserControl)SelectionControl).Value = OptionCategory.CategoryDefaultOptions;
}
}
}
///
/// Dataset with the product options data which should be loaded to the product options selector.
///
private InfoDataSet ProductOptionsData
{
get
{
if (mProductOptionsData == null)
{
if (IsLiveSite)
{
// Get cache minutes
int cacheMinutes = SettingsKeyProvider.GetIntValue(CMSContext.CurrentSiteName + ".CMSCacheMinutes");
// Try to get data from cache
using (CachedSection> cs = new CachedSection>(ref mProductOptionsData, cacheMinutes, true, null, "skuoptions", SKUID, OptionCategoryId))
{
if (cs.LoadData)
{
// Get the data
mProductOptionsData = SKUInfoProvider.GetSKUOptions(OptionCategoryId, true);
// Save to the cache
if (cs.Cached)
{
// Get dependencies
List dependencies = new List();
dependencies.Add("ecommerce.optioncategory|byid|" + OptionCategoryId);
dependencies.Add("ecommerce.sku|all");
// Set dependencies
cs.CacheDependency = CacheHelper.GetCacheDependency(dependencies);
}
cs.Data = mProductOptionsData;
}
}
}
else
{
// Get the data
mProductOptionsData = SKUInfoProvider.GetSKUOptions(OptionCategoryId, true);
}
}
return mProductOptionsData;
}
}
///
/// Loads data (SKU options) to the selection control.
///
private void LoadSKUOptions()
{
// Only for none-text types
if (SelectionControl != null)
{
if (SelectionControl is TextBoxWithLabel)
{
if (!DataHelper.DataSourceIsEmpty(ProductOptionsData))
{
DataRow dr = ProductOptionsData.Tables[0].Rows[0];
TextOptionSKUID = ValidationHelper.GetInteger(ProductOptionsData.Tables[0].Rows[0]["SKUID"], 0);
if (OptionCategory.CategoryDisplayPrice)
{
TextBoxWithLabel tb = SelectionControl as TextBoxWithLabel;
tb.LabelText = GetPrice(dr);
}
}
}
else if (SelectionControl is ListControl)
{
((ListControl)SelectionControl).DataSource = ProductOptionsData;
SelectionControl.DataBind();
// Add '(none)' record when it is allowed
if ((OptionCategory != null) && (OptionCategory.CategoryDefaultRecord != ""))
{
ListItem noneRecord = new ListItem(OptionCategory.CategoryDefaultRecord, "0");
((ListControl)SelectionControl).Items.Insert(0, noneRecord);
}
}
}
}
///
/// Returns hash table with product options.
///
private Hashtable GetProductOptions()
{
Hashtable optionsTable = new Hashtable();
// Get options and load them to the hashtable
foreach (SKUInfo sku in ProductOptionsData)
{
optionsTable.Add(sku.SKUID, sku);
}
return optionsTable;
}
#endregion
}
}