← Back to team overview

anewt-developers team mailing list archive

[Branch ~uws/anewt/anewt.uws] Rev 1815: [form] Add null-value support to choice control

 

------------------------------------------------------------
revno: 1815
committer: Wouter Bolsterlee <uws@xxxxxxxxx>
branch nick: anewt
timestamp: Thu 2011-03-17 14:39:30 +0100
message:
  [form] Add null-value support to choice control
  
  AnewtFormControlChoice has a new 'null-value' property
  (defaults to the empty string). For single-select controls,
  this will be used to determine whether the control has a
  null value, and can be used for e.g. a "I don't know"
  option in a drop down list.
  
  The validation has some simple checks for this, and
  get('value') will return null if the special value is
  encountered.
modified:
  form/controls/choice.lib.php


--
lp:anewt
https://code.launchpad.net/~uws/anewt/anewt.uws

Your team Anewt developers is subscribed to branch lp:anewt.
To unsubscribe from this branch go to https://code.launchpad.net/~uws/anewt/anewt.uws/+edit-subscription
=== modified file 'form/controls/choice.lib.php'
--- form/controls/choice.lib.php	2011-03-17 13:25:41 +0000
+++ form/controls/choice.lib.php	2011-03-17 13:39:30 +0000
@@ -135,6 +135,24 @@
  * control forces a selection list instead of a dropdown select box in case the
  * threshold is exceeded.
  *
+ * Single select controls can be used to obtain null values in addition to the
+ * values the options (or option groups) have. By default empty string values
+ * will be treated as <code>null</code>. Make sure to add any options yourself,
+ * since AnewtFormControlChoice will not automatically add empty options
+ * (because it doesn't know which display name you want, how many of them you
+ * want, and where you want them to appear). Code to add a \c null value
+ * typically looks like this:
+ *
+ * <code>$choice_control->add_option_value_label('', 'I don't know or won\'t tell');</code>
+ *
+ * If required, the special value that is to be treated as \c null can be
+ * specified by setting the \c null-value property to another string value
+ * (the default is an empty string).
+ *
+ * For multiple-select options, no special null handling is required. The \c
+ * value for a multiple-select option is always an array, which can be empty, so
+ * there is no need for special handling there.
+ *
  * \see AnewtFormOption
  */
 class AnewtFormControlChoice extends AnewtFormControl
@@ -169,9 +187,10 @@
 	{
 		parent::__construct($name);
 		$this->_seed(array(
-			'multiple'  => false,
-			'threshold' => 7,
-			'size'      => null,
+			'multiple'   => false,
+			'threshold'  => 7,
+			'size'       => null,
+			'null-value' => '',
 		));
 	}
 
@@ -232,7 +251,15 @@
 
 		/* Return the first value (if any) for single-select controls */
 		if ($values)
+		{
+			/* If the value is the special null value, return null */
+			$null_value = $this->get('null-value');
+			if ($values[0] === $null_value)
+				return null;
+
+			/* Else this is a real selection */
 			return $values[0];
+		}
 
 		/* No value set; return null */
 		return null;
@@ -331,14 +358,52 @@
 	function is_valid()
 	{
 		$value = $this->get('value');
-		if (!$this->_get('multiple') && is_null($value))
+
+		/* Null values for single select controls are only allowed if one the
+		 * options actually allows for it. Otherwise the value is treated as
+		 * erroneous content (perhaps malicious even). */
+		if (!$this->_get('multiple')
+				&& is_null($value)
+				&& !$this->_has_option_with_null_value())
 		{
-			$this->set('error', 'Invalid value');
+			$this->set('error', 'Invalid value for choice control');
 			return false;
 		}
+
 		return parent::is_valid();
 	}
 
+	/**
+	 * Find out whether this control has an option with the special null value.
+	 */
+	private function _has_option_with_null_value()
+	{
+		$null_value = $this->_get('null-value');
+
+		foreach ($this->_options as $option_or_option_group)
+		{
+			if ($option_or_option_group instanceof AnewtFormOptionGroup)
+			{
+				/* Option group */
+				foreach ($option_or_option_group->_options as $option)
+				{
+					if ($option->_get('value') === $null_value)
+						return true;
+				}
+			}
+			else
+			{
+				/* Single option */
+				$option = $option_or_option_group;
+				assert('$option instanceof AnewtFormOption');
+				if ($option->_get('value') === $null_value)
+					return true;
+			}
+		}
+
+		return false;
+	}
+
 	/** \{
 	 * \name Option methods
 	 */