← Back to team overview

anewt-developers team mailing list archive

[Branch ~sander-sinaasappel/anewt/anewt.new.cxs] Rev 1491: [form] Merged subform support from a private project.

 

------------------------------------------------------------
revno: 1491
committer: Sander van Schouwenburg <sander@xxxxxxxxxxxxx>
branch nick: anewt.new.cxs
timestamp: Thu 2010-02-25 20:43:58 +0100
message:
  [form] Merged subform support from a private project.
  
  See also bug #527946
added:
  form/controls/form.lib.php
modified:
  form/controls/base.lib.php
  form/controls/button.lib.php
  form/controls/choice.lib.php
  form/controls/main.lib.php
  form/controls/text.lib.php
  form/form.lib.php
  form/form.test.php
  form/renderer/base.lib.php
  form/renderer/default.lib.php


--
lp:~sander-sinaasappel/anewt/anewt.new.cxs
https://code.launchpad.net/~sander-sinaasappel/anewt/anewt.new.cxs

Your team Anewt developers is subscribed to branch lp:~sander-sinaasappel/anewt/anewt.new.cxs.
To unsubscribe from this branch go to https://code.launchpad.net/~sander-sinaasappel/anewt/anewt.new.cxs/+edit-subscription.
=== modified file 'form/controls/base.lib.php'
--- form/controls/base.lib.php	2009-07-20 15:48:26 +0000
+++ form/controls/base.lib.php	2010-02-25 19:43:58 +0000
@@ -159,12 +159,43 @@
 		$id = $this->_get('id');
 
 		if (is_null($id))
-			$id = $this->get('name');
+		{
+			$name_parts = $this->get('name-parts');
+			$id = join('-', $name_parts);
+		}
 
 		return $id;
 	}
 
 	/**
+	 * Returns a list of name parts. Mostly, this is an array with all
+	 * the prefixes from the form, followed by the name of this contro.
+	 */
+	function get_name_parts() {
+		if (isset($this->_form)) {
+			$parts = $this->_form->get('prefix');
+		} else {
+			$parts = array();
+		}
+		$parts[] = $this->get('name');
+
+		return $parts;
+	}
+
+	/**
+	 * Returns the rendered name as html. This is the name with an optional prefix.
+	 */
+	function get_rendered_name() {
+		$parts = $this->get('name-parts');
+
+		$name = array_shift($parts);
+		foreach ($parts as $part)
+			$name .= sprintf('[%s]', $part);
+
+		return $name;
+	}
+
+	/**
 	 * \private
 	 *
 	 * Make the control reference its containing form.

=== modified file 'form/controls/button.lib.php'
--- form/controls/button.lib.php	2009-07-20 15:50:43 +0000
+++ form/controls/button.lib.php	2010-02-25 19:43:58 +0000
@@ -70,7 +70,7 @@
 		);
 
 		if ($this->_get('render-name'))
-			$attr['name'] = $this->get('name');
+			$attr['name'] = $this->get('rendered-name');
 
 		$label = $this->get('label');
 		if (!is_null($label))

=== modified file 'form/controls/choice.lib.php'
--- form/controls/choice.lib.php	2010-01-04 13:03:15 +0000
+++ form/controls/choice.lib.php	2010-02-25 19:43:58 +0000
@@ -58,7 +58,7 @@
 	{
 		$id = $this->get('id');
 		$attr = array(
-			'name'  => $this->get('name'),
+			'name'  => $this->get('rendered-name'),
 			'id'	=> $id,
 			'type'  => 'checkbox',
 		);
@@ -515,7 +515,7 @@
 
 	function build_widget()
 	{
-		$name = $this->get('name');
+		$name = $this->get('rendered-name');
 		$id = $this->get('id');
 		$multiple = $this->_get('multiple');
 
@@ -764,7 +764,7 @@
 
 		$input_attr = array(
 			'type'  => 'checkbox',
-			'name'  => sprintf('%s[]', $this->_choice_control->_get('name')),
+			'name'  => sprintf('%s[]', $this->_choice_control->get('rendered-name')),
 			'value' => $value,
 		);
 
@@ -798,7 +798,7 @@
 
 		$input_attr = array(
 			'type'	 => 'radio',
-			'name'	 => $this->_choice_control->_get('name'),
+			'name'  => $this->_choice_control->get('rendered-name'),
 			'value'	=> $value,
 		);
 

=== added file 'form/controls/form.lib.php'
--- form/controls/form.lib.php	1970-01-01 00:00:00 +0000
+++ form/controls/form.lib.php	2010-02-25 19:43:58 +0000
@@ -0,0 +1,104 @@
+<?php
+
+/*
+ * Anewt, Almost No Effort Web Toolkit, form module
+ *
+ * This code is copyrighted and distributed under the terms of the GNU LGPL.
+ * See the README file for more information.
+ */
+
+
+/**
+ * Controls containing a subform.
+ *
+ * This control can render a subform. The #build_widget() will render the entire
+ * form without the <form> tags. Its controls will render with prefixed names
+ * such that name clashes between controls of multiple subforms are avoided.
+ * Of course, the name of this control must be unique in the main form.
+ *
+ * To do normal processing within this form, it is necessary that #process()
+ * be called in the \c process() of the main form.
+ */
+class AnewtFormControlSubform extends AnewtFormControl
+{
+	protected $_subform;		/**< The subform */
+
+	/**
+	 * Create a new subform control
+	 *
+	 * \param $name
+	 *   The name of this control.
+	 * \param $form
+	 *   The subform
+	 * \param $renderer
+	 *   A renderer for the form.
+	 */
+	function __construct($name, $subform, $renderer = null)
+	{
+		parent::__construct($name);
+		$this->seed(array(
+			'renderer'   => $renderer,
+			'class'      => null,
+		));
+		assert('$subform instanceof AnewtForm');
+		$this->_subform = $subform;
+	}
+
+	function set_prefix()
+	{
+		$prefix = $this->get('name-parts');
+		$this->_subform->set('prefix', $prefix);
+	}
+
+	function build_widget()
+	{
+		$renderer = $this->get('renderer');
+
+		$this->set_prefix();
+
+		if (is_null($renderer)) {
+			$renderer = new AnewtFormRendererDefault();
+			$renderer->set_form($this->_subform);
+			$this->set('renderer', $renderer);
+		}
+
+		$attr = array(
+			'class' => 'form-subform',
+			'id' => $this->get('id'),
+		);
+
+		$div = new AnewtXHTMLDiv(null, $attr);
+
+		$class = $this->_get('class');
+		if (!is_null($class))
+			$div->add_class($class);
+
+		$div->append_child($renderer->render_hidden_controls());
+		$div->append_child($renderer->render_base());
+
+		return $div;
+	}
+
+	function process() {
+		return $this->_subform->process();
+	}
+
+	function is_valid()
+	{
+		return $this->_subform->is_valid();
+	}
+
+	function get_value() {
+		return $this->_subform->get_control_values();
+	}
+
+	function set_value($value) {
+		$this->_subform->fill($value);
+	}
+
+	function get_subform() {
+		return $this->_subform;
+	}
+}
+
+?>

=== modified file 'form/controls/main.lib.php'
--- form/controls/main.lib.php	2008-09-11 16:55:47 +0000
+++ form/controls/main.lib.php	2010-02-25 19:43:58 +0000
@@ -13,5 +13,6 @@
 anewt_include('form/controls/button');
 anewt_include('form/controls/choice');
 anewt_include('form/controls/fileupload');
+anewt_include('form/controls/form');
 
 ?>

=== modified file 'form/controls/text.lib.php'
--- form/controls/text.lib.php	2009-07-20 15:48:47 +0000
+++ form/controls/text.lib.php	2010-02-25 19:43:58 +0000
@@ -67,7 +67,7 @@
 		/* XML tag attributes used both for single line and multiline */
 
 		$attr = array(
-			'name'     => $this->get('name'),
+			'name'     => $this->get('rendered-name'),
 			'id'       => $this->get('id'),
 		);
 		if ($this->get('extra_attributes')) {
@@ -350,6 +350,7 @@
 				$name = sprintf("%s[%s]", $this->get('name'), $key);
 				$id = sprintf("%s-%s", $this->get('id'), $key);
 				$c = new AnewtFormControlHidden($name);
+				$c->_set_form($this->_form);
 				$c->set('value', $item);
 				$c->set('id', $id);
 
@@ -358,7 +359,7 @@
 			return ax_fragment($widget_list);
 		} else {
 			$attr = array(
-				'name'  => $this->get('name'),
+				'name'  => $this->get('rendered-name'),
 				'id'    => $this->get('id'),
 				'value' => (string) $this->get('value'),
 				'type'  => 'hidden',

=== modified file 'form/form.lib.php'
--- form/form.lib.php	2009-07-20 15:55:38 +0000
+++ form/form.lib.php	2010-02-25 19:43:58 +0000
@@ -74,6 +74,8 @@
 			'method'      => ANEWT_FORM_METHOD_POST,
 			'action'      => Request::relative_url(),
 
+			'prefix'      => array(),
+
 			'description' => null,
 			'error'       => null,
 		));
@@ -237,12 +239,18 @@
 	{
 		$form_method = $this->_get('method');
 		if (Request::is_get() && $form_method == ANEWT_FORM_METHOD_GET) {
-			return $this->fill($_GET);
+			$values = $_GET;
 		}
 		elseif (Request::is_post() && $form_method == ANEWT_FORM_METHOD_POST) {
-			return $this->fill($_POST);
-		}
-		return false;
+			$values = $_POST;
+		}
+		else {
+			return false;
+		}
+		foreach ($this->get('prefix') as $part) {
+			$values = $values[$part];
+		}
+		return $this->fill($values);
 	}
 
 	/**
@@ -481,6 +489,7 @@
 				$control_name = $fieldset->_children[$key]->get('name');
 				assert('!array_key_exists($control_name, $this->_controls_by_name); // control names must be unique');
 				$this->_controls_by_name[$control_name] = $fieldset->_children[$key];
+				$this->_controls_by_name[$control_name]->_set_form($this);
 			}
 		}
 	}
@@ -551,6 +560,20 @@
 	}
 
 	/**
+	 * Set's the prefix or list of prefixes for this control.
+	 */
+	function set_prefix($prefix) {
+		if (is_string($prefix))
+			$prefix = array($prefix);
+		elseif (is_null($prefix))
+			$prefix = array();
+
+		assert('is_array($prefix)');
+
+		$this->_set('prefix', $prefix);
+	}
+
+	/**
 	 * \protected
 	 *
 	 * Return all children on this form as a list.

=== modified file 'form/form.test.php'
--- form/form.test.php	2009-04-07 08:05:57 +0000
+++ form/form.test.php	2010-02-25 19:43:58 +0000
@@ -416,6 +416,12 @@
 		$this->add_hidden_control('hidden2', 'another && śèkŕ1t');
 
 
+		/* Subform */
+
+		$subform = new TestSubForm();
+		$subform_control = new AnewtFormControlSubform('mysubform', $subform);
+		$this->add_control($subform_control);
+
 		/* Buttons */
 
 		$button_fieldset = new AnewtFormFieldset('buttons');
@@ -448,6 +454,34 @@
 	}
 }
 
+class TestSubForm extends AnewtForm {
+	function __construct() {
+		parent::__construct();
+
+		$number = new AnewtFormControlText('number');
+		$number->set('label', 'A number');
+		$number->set('value', '45');
+		$number->add_validator(new AnewtValidatorInteger(), 'This must be a number');
+		$this->add_control($number);
+
+		$subform = new TestSubSubForm();
+		$subform_control = new AnewtFormControlSubform('mysubform', $subform);
+		$this->add_control($subform_control);
+	}
+}
+
+class TestSubSubForm extends AnewtForm {
+	function __construct() {
+		parent::__construct();
+
+		$subnumber = new AnewtFormControlText('subnumber');
+		$subnumber->set('label', 'A subnumber');
+		$subnumber->set('value', '13');
+		$subnumber->add_validator(new AnewtValidatorInteger(), 'This must be a number');
+		$this->add_control($subnumber);
+	}
+}
+
 
 /* Show a page and test the form */
 

=== modified file 'form/renderer/base.lib.php'
--- form/renderer/base.lib.php	2009-05-05 17:06:25 +0000
+++ form/renderer/base.lib.php	2010-02-25 19:43:58 +0000
@@ -91,17 +91,34 @@
 
 		$form = new AnewtXHTMLForm(null, $attributes);
 
+		$form->append_child($this->render_hidden_controls());
+
+		return $form;
+	}
+
+	/**
+	 * Renders the hidden controls.
+	 */
+	function render_hidden_controls() {
+
+		$fragment = new AnewtXHTMLFragment();
+
 		/* The HTML DTD does not allow <input> elements as direct childs of
 		 * a <form> element. Use a <fieldset> that is completely hidden from
 		 * view instead. */
-		$hidden_controls_fieldset = new AnewtXHTMLFieldset();
-		$hidden_controls_fieldset->set_attribute('style', 'display: none;');
-		foreach ($this->_form->_hidden_controls() as $hidden_control)
-			$hidden_controls_fieldset->append_child($hidden_control->build_widget());
-
-		$form->append_child($hidden_controls_fieldset);
-
-		return $form;
+		$hidden_controls = $this->_form->_hidden_controls();
+		if ($hidden_controls)
+		{
+			$hidden_controls_fieldset = new AnewtXHTMLFieldset();
+			$hidden_controls_fieldset->set_attribute('style', 'display: none;');
+
+			foreach ($hidden_controls as $hidden_control)
+				$hidden_controls_fieldset->append_child($hidden_control->build_widget());
+
+			$fragment->append_child($hidden_controls_fieldset);
+		}
+
+		return $fragment;
 	}
 
 	/**

=== modified file 'form/renderer/default.lib.php'
--- form/renderer/default.lib.php	2009-07-20 15:56:32 +0000
+++ form/renderer/default.lib.php	2010-02-25 19:43:58 +0000
@@ -49,8 +49,20 @@
 	{
 		$f = $this->build_form_element();
 
-		$f->append_child($this->_build_error_node($this->_form));
-		$f->append_child($this->_build_description_node($this->_form));
+		$f->append_child($this->render_base());
+
+		return $f;
+	}
+
+	/**
+	 * Render the form except for the <form> tags.
+	 */
+	function render_base()
+	{
+		$r = array();
+
+		$r[] = $this->_build_error_node($this->_form);
+		$r[] = $this->_build_description_node($this->_form);
 
 		/* Add all form children */
 
@@ -61,10 +73,9 @@
 			if ($children[$key] instanceof AnewtFormControlHidden)
 				continue;
 
-			$f->append_child($this->_build_child_node($children[$key]));
+			$r[] = $this->_build_child_node($children[$key]);
 		}
-
-		return $f;
+		return ax_fragment($r);
 	}
 
 	/**