<?php

class Tag_Form extends Tag
{
	protected $report_name_element = NULL; // Tag_Hidden instance, created at instantiation, optional

	public function __construct($name='', $action='', $method='post', $attributes=array())
	{
		parent::__construct('form', $attributes, TAG_CR | TAG_CLOSE);
		if( $name )
		{
			$this->attr('name', $name);
			$this->attr('id', $name);
			$this->report_name_element = new Tag_Hidden('form_name', $this->attr('name'));
		}
		if($method)
			$this->attr('method', $method);
		if($action)
			$this->attr('action', $action);
	}

	/** Alias function for addChild() or addChildren() */
	public function addElements()
	{
		if(func_num_args() == 1)
		{
			$this->addChild(func_get_arg(0));
		}
		else
		{
			foreach(func_get_args() as $arg)
				$this->addChild($arg);
		}
	}

	/** Alias function for getChildren */
	public function &getElements()
	{
		return $this->getChildren();
	}

	/** Renders all children as markup to the browser without rendering form tags */
	public function renderElements($return=0)
	{
		$elements = Tag::renderTags($this->getChildren());
		$html = implode("\n",$elements);
		if( $return )
			return $html;
		else
			echo $html;
	}

	/** Alias of Tag::setValues executed on the form's children */
	public function setValues(array $values)
	{
		$this->children = Tag::setTagValues($this->children, $values);
	}

	/** Function which renders the starting markup for the form, returns or renders to browser */
	public function start($return=0)
	{
		$html = parent::openTag(1);
		
		// If a report name element is explicitly defined, render it with the opening FORM tag
		if( !is_null($this->report_name_element) )
			$html .= $this->report_name_element->render(true);
		
		// Return or render the resulting markup
		if( $return )
			return $html;
		else
			echo $html;
	}

	/** Function which renders finishing markup for the form, returns or renders to the browser */
	public function end($return=0)
	{
		return parent::closeTag();
	}

	/** Depreciated override of the openTag method */
	public function openTag()
	{
		return $this->start(1);
	}

	/** Depreciated opening render function */
	public function renderOpenTag($return=false)
	{
		return $this->start($return);
	}

	/** Depreciated closing function */
	public function renderCloseTag($return=false)
	{
		return $this->end($return);
	}

	public static function submitted($form_name, $method='post')
	{
		switch($method)
		{
			case 'get':
			case 'GET':
			case 'G':
			case 'g':
				$values = &$_GET;
				break;
			case 'session':
			case 'SESSION':
			case 'S':
			case 's':
				$values = &$_SESSION;
				break;
			case 'post':
			case 'POST':
			case 'P':
			case 'p':
			default:
				$values = &$_POST;
		}
		return (isset($values['form_name']) && $values['form_name'] == $form_name);
	}

	/** 
	 * Reindexes the elements in an array so that the "id" attribute is used as a key in the array, where before it was sequential numeric.
	 * 
	 * Takes an array containing instances of Tag_Field with numeric keys,
	 * and then changes the elements over to an assoc array using the "id" attribute
	 * of the input objects included as array keys
	 * ie.
	 * $elements = array( new Tag_Field('First Name', new Tag_Text('first_name')) );
	 * $elements = Tag_Form::reindexElements($elements);
	 * print_r(array_keys($elements),1)
	 * : ['first_name'=>Tag_Field Instance]
	 */
	public static function reindexElements($elements)
	{
		foreach(array_keys($elements) as $i)
		{
			$name = NULL;

			if( is_numeric($i) ) // String Keys are NOT affected
			{
				if( ($elements[$i] instanceof Tag_Field && $elements[$i]->field instanceof Tag) )
				{
					$element = $elements[$i]->field;
				}
				elseif( $elements[$i] instanceof Tag && !($elements[$i] instanceof Tag_Field) )
				{
					$element = $elements[$i];
				}
				else // Not a Tag Field, not a Tag, a base value, DON'T CHANGE ANYTHING
				{
					continue;
				}

				if( $element->attr('name') )
					$name = $element->attr('name');
				elseif( $element->attr('id') )
					$name = $element->attr('id');

				if( $name )
				{
					$elements[$name] = $elements[$i];
					unset($elements[$i]);
				}
			}
		}
		return $elements;
	}

}
