1<?php
2/**
3 * MyBB 1.8
4 * Copyright 2014 MyBB Group, All Rights Reserved
5 *
6 * Website: http://www.mybb.com
7 * License: http://www.mybb.com/about/license
8 *
9 */
10
11/**
12 * Generate a form on the page.
13 */
14class DefaultForm
15{
16	/**
17	 * @var boolean Should this form be returned instead of output to the browser?
18	 */
19	private $_return = false;
20
21	/**
22	 * @var string Contents of the form if $_return is true from __construct
23	 */
24	public $construct_return = "";
25
26	/**
27	 * Constructor. Outputs the form tag with the specified options.
28	 *
29	 * @param string $script The action for the form.
30	 * @param string $method The method (get or post) for this form.
31	 * @param string $id The ID of the form.
32	 * @param boolean $allow_uploads Should file uploads be allowed for this form?
33	 * @param string $name The name of the form
34	 * @param boolean $return Should this form be returned instead of output to the browser?
35	 * @param string $onsubmit The onsubmit action of the form
36	 */
37	function __construct($script='', $method='', $id="", $allow_uploads=false, $name="", $return=false, $onsubmit="")
38	{
39		global $mybb;
40		$form = "<form action=\"{$script}\" method=\"{$method}\"";
41		if($allow_uploads != false)
42		{
43			$form .= " enctype=\"multipart/form-data\"";
44		}
45
46		if($name != "")
47		{
48			$form .= " name=\"{$name}\"";
49		}
50
51		if($id != "")
52		{
53			$form .= " id=\"{$id}\"";
54		}
55
56		if($onsubmit != "")
57		{
58			$form .= " onsubmit=\"{$onsubmit}\"";
59		}
60		$form .= ">\n";
61		$form .= $this->generate_hidden_field("my_post_key", $mybb->post_code)."\n";
62		if($return == false)
63		{
64			echo $form;
65		}
66		else
67		{
68			$this->_return = true;
69			$this->construct_return = $form;
70		}
71	}
72
73	/**
74	 * Generate and return a hidden field.
75	 *
76	 * @param string $name The name of the hidden field.
77	 * @param string $value The value of the hidden field.
78	 * @param array $options Optional array of options (id)
79	 * @return string The generated hidden
80	 */
81	function generate_hidden_field($name, $value, $options=array())
82	{
83		$input = "<input type=\"hidden\" name=\"{$name}\" value=\"".htmlspecialchars_uni($value)."\"";
84		if(isset($options['id']))
85		{
86			$input .= " id=\"".$options['id']."\"";
87		}
88		$input .= " />";
89		return $input;
90	}
91
92	/**
93	 * Generate a text box field.
94	 *
95	 * @param string $name The name of the text box.
96	 * @param string $value The value of the text box.
97	 * @param array $options Array of options for the text box (class, style, id)
98	 * @return string The generated text box.
99	 */
100	function generate_text_box($name, $value="", $options=array())
101	{
102		$input = "<input type=\"text\" name=\"".$name."\" value=\"".htmlspecialchars_uni($value)."\"";
103		if(isset($options['class']))
104		{
105			$input .= " class=\"text_input ".$options['class']."\"";
106		}
107		else
108		{
109			$input .= " class=\"text_input\"";
110		}
111		if(isset($options['style']))
112		{
113			$input .= " style=\"".$options['style']."\"";
114		}
115		if(isset($options['id']))
116		{
117			$input .= " id=\"".$options['id']."\"";
118		}
119		$input .= " />";
120		return $input;
121	}
122
123	/**
124	 * Generate a numeric field.
125	 *
126	 * @param string $name The name of the numeric box.
127	 * @param int $value The value of the numeric box.
128	 * @param array $options Array of options for the numeric box (min, max, step, class, style, id)
129	 * @return string The generated numeric box.
130	 */
131	function generate_numeric_field($name, $value=0, $options=array())
132	{
133		if(is_numeric($value))
134		{
135			$value = (float)$value;
136		}
137		else
138		{
139			$value = '';
140		}
141
142		$input = "<input type=\"number\" name=\"{$name}\" value=\"{$value}\"";
143		if(isset($options['min']))
144		{
145			$input .= " min=\"".$options['min']."\"";
146		}
147		if(isset($options['max']))
148		{
149			$input .= " max=\"".$options['max']."\"";
150		}
151		if(isset($options['step']))
152		{
153			$input .= " step=\"".$options['step']."\"";
154		}
155		if(isset($options['class']))
156		{
157			$input .= " class=\"text_input ".$options['class']."\"";
158		}
159		else
160		{
161			$input .= " class=\"text_input\"";
162		}
163		if(isset($options['style']))
164		{
165			$input .= " style=\"".$options['style']."\"";
166		}
167		if(isset($options['id']))
168		{
169			$input .= " id=\"".$options['id']."\"";
170		}
171		$input .= " />";
172		return $input;
173	}
174
175	/**
176	 * Generate a password input box.
177	 *
178	 * @param string $name The name of the password box.
179	 * @param string $value The value of the password box.
180	 * @param array $options Array of options for the password box (class, id, autocomplete)
181	 * @return string The generated password input box.
182	 */
183	function generate_password_box($name, $value="", $options=array())
184	{
185		$input = "<input type=\"password\" name=\"".$name."\" value=\"".htmlspecialchars_uni($value)."\"";
186		if(isset($options['class']))
187		{
188			$input .= " class=\"text_input ".$options['class']."\"";
189		}
190		else
191		{
192			$input .= " class=\"text_input\"";
193		}
194		if(isset($options['id']))
195		{
196			$input .= " id=\"".$options['id']."\"";
197		}
198		if(isset($options['autocomplete']))
199		{
200			$input .= " autocomplete=\"".$options['autocomplete']."\"";
201		}
202		$input .= " />";
203		return $input;
204	}
205
206	/**
207	 * Generate a file upload field.
208	 *
209	 * @param string $name The name of the file upload field.
210	 * @param array $options Array of options for the file upload field (class, id, style)
211	 * @return string The generated file upload field.
212	 */
213	function generate_file_upload_box($name, $options=array())
214	{
215		$input = "<input type=\"file\" name=\"".$name."\"";
216		if(isset($options['class']))
217		{
218			$input .= " class=\"text_input ".$options['class']."\"";
219		}
220		else
221		{
222			$input .= " class=\"text_input\"";
223		}
224		if(isset($options['style']))
225		{
226			$input .= " style=\"".$options['style']."\"";
227		}
228		if(isset($options['id']))
229		{
230			$input .= " id=\"".$options['id']."\"";
231		}
232		$input .= " />";
233		return $input;
234
235	}
236
237	/**
238	 * Generate a text area.
239	 *
240	 * @param string $name The name of of the text area.
241	 * @param string $value The value of the text area field.
242	 * @param array $options Array of options for text area (class, id, rows, cols, style, disabled, maxlength, readonly)
243	 * @return string The generated text area field.
244	 */
245	function generate_text_area($name, $value="", $options=array())
246	{
247		$textarea = "<textarea";
248		if(!empty($name))
249		{
250			$textarea .= " name=\"{$name}\"";
251		}
252		if(isset($options['class']))
253		{
254			$textarea .= " class=\"{$options['class']}\"";
255		}
256		if(isset($options['id']))
257		{
258			$textarea .= " id=\"{$options['id']}\"";
259		}
260		if(isset($options['style']))
261		{
262			$textarea .= " style=\"{$options['style']}\"";
263		}
264		if(isset($options['disabled']) && $options['disabled'] !== false)
265		{
266			$textarea .= " disabled=\"disabled\"";
267		}
268		if(isset($options['readonly']) && $options['readonly'] !== false)
269		{
270			$textarea .= " readonly=\"readonly\"";
271		}
272		if(isset($options['maxlength']))
273		{
274			$textarea .= " maxlength=\"{$options['maxlength']}\"";
275		}
276		if(!isset($options['rows']))
277		{
278			$options['rows'] = 5;
279		}
280		if(!isset($options['cols']))
281		{
282			$options['cols'] = 45;
283		}
284		$textarea .= " rows=\"{$options['rows']}\" cols=\"{$options['cols']}\">";
285		$textarea .= htmlspecialchars_uni($value);
286		$textarea .= "</textarea>";
287		return $textarea;
288	}
289
290	/**
291	 * Generate a radio button.
292	 *
293	 * @param string $name The name of the radio button.
294	 * @param string $value The value of the radio button
295	 * @param string $label The label of the radio button if there is one.
296	 * @param array $options Array of options for the radio button (id, class, checked)
297	 * @return string The generated radio button.
298	 */
299	function generate_radio_button($name, $value="", $label="", $options=array())
300	{
301		$input = "<label";
302		if(isset($options['id']))
303		{
304			$input .= " for=\"{$options['id']}\"";
305		}
306		if(isset($options['class']))
307		{
308			$input .= " class=\"label_{$options['class']}\"";
309		}
310		$input .= "><input type=\"radio\" name=\"{$name}\" value=\"".htmlspecialchars_uni($value)."\"";
311		if(isset($options['class']))
312		{
313			$input .= " class=\"radio_input ".$options['class']."\"";
314		}
315		else
316		{
317			$input .= " class=\"radio_input\"";
318		}
319		if(isset($options['id']))
320		{
321			$input .= " id=\"".$options['id']."\"";
322		}
323		if(isset($options['checked']) && $options['checked'] != 0)
324		{
325			$input .= " checked=\"checked\"";
326		}
327		$input .= " />";
328		if($label != "")
329		{
330			$input .= $label;
331		}
332		$input .= "</label>";
333		return $input;
334	}
335
336	/**
337	 * Generate a checkbox.
338	 *
339	 * @param string $name The name of the check box.
340	 * @param string $value The value of the check box.
341	 * @param string $label The label of the check box if there is one.
342	 * @param array $options Array of options for the check box (id, class, checked, onclick)
343	 * @return string The generated check box.
344	 */
345	function generate_check_box($name, $value="", $label="", $options=array())
346	{
347		$input = "<label";
348		if(isset($options['id']))
349		{
350			$input .= " for=\"{$options['id']}\"";
351		}
352		if(isset($options['class']))
353		{
354			$input .= " class=\"label_{$options['class']}\"";
355		}
356		$input .= "><input type=\"checkbox\" name=\"{$name}\" value=\"".htmlspecialchars_uni($value)."\"";
357		if(isset($options['class']))
358		{
359			$input .= " class=\"checkbox_input ".$options['class']."\"";
360		}
361		else
362		{
363			$input .= " class=\"checkbox_input\"";
364		}
365		if(isset($options['id']))
366		{
367			$input .= " id=\"".$options['id']."\"";
368		}
369		if(isset($options['checked']) && ($options['checked'] === true || $options['checked'] == 1))
370		{
371			$input .= " checked=\"checked\"";
372		}
373		if(isset($options['onclick']))
374		{
375			$input .= " onclick=\"{$options['onclick']}\"";
376		}
377		$input .= " /> ";
378		if($label != "")
379		{
380			$input .= $label;
381		}
382		$input .= "</label>";
383		return $input;
384	}
385
386	/**
387	 * Generate a select box.
388	 *
389	 * @param string $name The name of the select box.
390	 * @param array $option_list Array of options in key => val format.
391	 * @param string|array $selected Either a string containing the selected item or an array containing multiple selected items (options['multiple'] must be true)
392	 * @param array $options Array of options for the select box (multiple, class, id, size)
393	 * @return string The select box.
394	 */
395	function generate_select_box($name, $option_list=array(), $selected=array(), $options=array())
396	{
397		if(!isset($options['multiple']))
398		{
399			$select = "<select name=\"{$name}\"";
400		}
401		else
402		{
403			$select = "<select name=\"{$name}\" multiple=\"multiple\"";
404			if(!isset($options['size']))
405			{
406				$options['size'] = count($option_list);
407			}
408		}
409		if(isset($options['class']))
410		{
411			$select .= " class=\"{$options['class']}\"";
412		}
413		if(isset($options['id']))
414		{
415			$select .= " id=\"{$options['id']}\"";
416		}
417		if(isset($options['size']))
418		{
419			$select .= " size=\"{$options['size']}\"";
420		}
421		$select .= ">\n";
422		foreach($option_list as $value => $option)
423		{
424			$select_add = '';
425			if((!is_array($selected) || !empty($selected)) && ((is_array($selected) && in_array((string)$value, $selected)) || (!is_array($selected) && (string)$value === (string)$selected)))
426			{
427				$select_add = " selected=\"selected\"";
428			}
429			$select .= "<option value=\"{$value}\"{$select_add}>{$option}</option>\n";
430		}
431		$select .= "</select>\n";
432		return $select;
433	}
434
435	/**
436	 * Generate a forum selection box.
437	 *
438	 * @param string $name The name of the selection box.
439	 * @param array|string $selected Array/string of the selected items.
440	 * @param array Array of options (pid, main_option, multiple, depth)
441	 * @param boolean|int $is_first Is this our first iteration of this function?
442	 * @return string The built select box.
443	 */
444	function generate_forum_select($name, $selected, $options=array(), $is_first=1)
445	{
446		global $fselectcache, $forum_cache, $selectoptions;
447
448		if(!$selectoptions)
449		{
450			$selectoptions = '';
451		}
452
453		if(!isset($options['depth']))
454		{
455			$options['depth'] = 0;
456		}
457
458		$options['depth'] = (int)$options['depth'];
459
460		if(!isset($options['pid']))
461		{
462			$options['pid'] = 0;
463		}
464
465		$pid = (int)$options['pid'];
466
467		if(!is_array($fselectcache))
468		{
469			if(!is_array($forum_cache))
470			{
471				$forum_cache = cache_forums();
472			}
473
474			foreach($forum_cache as $fid => $forum)
475			{
476				$fselectcache[$forum['pid']][$forum['disporder']][$forum['fid']] = $forum;
477			}
478		}
479
480		if(isset($options['main_option']) && $is_first)
481		{
482			$select_add = '';
483			if($selected == -1)
484			{
485				$select_add = " selected=\"selected\"";
486			}
487
488			$selectoptions .= "<option value=\"-1\"{$select_add}>{$options['main_option']}</option>\n";
489		}
490
491		if(isset($fselectcache[$pid]))
492		{
493			foreach($fselectcache[$pid] as $main)
494			{
495				foreach($main as $forum)
496				{
497					if($forum['fid'] != "0" && $forum['linkto'] == '')
498					{
499						$select_add = '';
500
501						if(!empty($selected) && ($forum['fid'] == $selected || (is_array($selected) && in_array($forum['fid'], $selected))))
502						{
503							$select_add = " selected=\"selected\"";
504						}
505
506						$sep = '';
507						if(isset($options['depth']))
508						{
509							$sep = str_repeat("&nbsp;", $options['depth']);
510						}
511
512						$style = "";
513						if($forum['active'] == 0)
514						{
515							$style = " style=\"font-style: italic;\"";
516						}
517
518						$selectoptions .= "<option value=\"{$forum['fid']}\"{$style}{$select_add}>".$sep.htmlspecialchars_uni(strip_tags($forum['name']))."</option>\n";
519
520						if($forum_cache[$forum['fid']])
521						{
522							$options['depth'] += 5;
523							$options['pid'] = $forum['fid'];
524							$this->generate_forum_select($forum['fid'], $selected, $options, 0);
525							$options['depth'] -= 5;
526						}
527					}
528				}
529			}
530		}
531
532		if($is_first == 1)
533		{
534			if(!isset($options['multiple']))
535			{
536				$select = "<select name=\"{$name}\"";
537			}
538			else
539			{
540				$select = "<select name=\"{$name}\" multiple=\"multiple\"";
541			}
542			if(isset($options['class']))
543			{
544				$select .= " class=\"{$options['class']}\"";
545			}
546			if(isset($options['id']))
547			{
548				$select .= " id=\"{$options['id']}\"";
549			}
550			if(isset($options['size']))
551			{
552				$select .= " size=\"{$options['size']}\"";
553			}
554			$select .= ">\n".$selectoptions."</select>\n";
555			$selectoptions = '';
556			return $select;
557		}
558	}
559
560	/**
561	 * Generate a group selection box.
562	 *
563	 * @param string $name The name of the selection box.
564	 * @param array|string $selected Array/string of the selected items.
565	 * @param array $options Array of options (class, id, multiple, size)
566	 * @return string The built select box.
567	 */
568	function generate_group_select($name, $selected=array(), $options=array())
569	{
570		global $cache;
571
572		$select = "<select name=\"{$name}\"";
573
574		if(isset($options['multiple']))
575		{
576			$select .= " multiple=\"multiple\"";
577		}
578
579		if(isset($options['class']))
580		{
581			$select .= " class=\"{$options['class']}\"";
582		}
583
584		if(isset($options['id']))
585		{
586			$select .= " id=\"{$options['id']}\"";
587		}
588
589		if(isset($options['size']))
590		{
591			$select .= " size=\"{$options['size']}\"";
592		}
593
594		$select .= ">\n";
595
596		$groups_cache = $cache->read('usergroups');
597
598		if(!is_array($selected))
599		{
600			$selected = array($selected);
601		}
602
603		foreach($groups_cache as $group)
604		{
605			$selected_add = "";
606
607
608			if(in_array($group['gid'], $selected))
609			{
610				$selected_add = " selected=\"selected\"";
611			}
612
613			$select .= "<option value=\"{$group['gid']}\"{$selected_add}>".htmlspecialchars_uni($group['title'])."</option>";
614		}
615
616		$select .= "</select>";
617
618		return $select;
619	}
620
621	/**
622	 * Generate a prefix selection box.
623	 *
624	 * @param string $name The name of the selection box.
625	 * @param array|string $selected Array/string of the selected items.
626	 * @param array $options Array of options (class, id, multiple, size)
627	 * @return string The built select box.
628	 */
629	function generate_prefix_select($name, $selected=array(), $options=array())
630	{
631		global $cache;
632		$select = "<select name=\"{$name}\"";
633		if(isset($options['multiple']))
634		{
635			$select .= " multiple=\"multiple\"";
636		}
637		if(isset($options['class']))
638		{
639			$select .= " class=\"{$options['class']}\"";
640		}
641		if(isset($options['id']))
642		{
643			$select .= " id=\"{$options['id']}\"";
644		}
645		if(isset($options['size']))
646		{
647			$select .= " size=\"{$options['size']}\"";
648		}
649		$select .= ">\n";
650		$prefix_cache = $cache->read('threadprefixes');
651
652		if(!is_array($selected))
653		{
654			$selected = array($selected);
655		}
656
657		foreach($prefix_cache as $prefix)
658		{
659			$selected_add = "";
660
661
662			if(in_array($prefix['pid'], $selected))
663			{
664				$selected_add = " selected=\"selected\"";
665			}
666			$select .= "<option value=\"{$prefix['pid']}\"{$selected_add}>".htmlspecialchars_uni($prefix['prefix'])."</option>";
667		}
668		$select .= "</select>";
669		return $select;
670	}
671
672	/**
673	 * Generate a submit button.
674	 *
675	 * @param string $value The value for the submit button.
676	 * @param array $options Array of options for the submit button (class, id, name, dsiabled, onclick)
677	 * @return string The generated submit button.
678	 */
679	function generate_submit_button($value, $options=array())
680	{
681		$input = "<input type=\"submit\" value=\"".htmlspecialchars_uni($value)."\"";
682
683		if(isset($options['class']))
684		{
685			$input .= " class=\"submit_button ".$options['class']."\"";
686		}
687		else
688		{
689			$input .= " class=\"submit_button\"";
690		}
691		if(isset($options['id']))
692		{
693			$input .= " id=\"".$options['id']."\"";
694		}
695		if(isset($options['name']))
696		{
697			$input .= " name=\"".$options['name']."\"";
698		}
699		if(isset($options['disabled']))
700		{
701			$input .= " disabled=\"disabled\"";
702		}
703		if(isset($options['onclick']))
704		{
705			$input .= " onclick=\"".str_replace('"', '\"', $options['onclick'])."\"";
706		}
707		$input .= " />";
708		return $input;
709	}
710
711	/**
712	 * Generate a reset button.
713	 *
714	 * @param string $value The value for the reset button.
715	 * @param array $options Array of options for the reset button (class, id, name)
716	 * @return string The generated reset button.
717	 */
718	function generate_reset_button($value, $options=array())
719	{
720		$input = "<input type=\"reset\" value=\"".htmlspecialchars_uni($value)."\"";
721
722		if(isset($options['class']))
723		{
724			$input .= " class=\"submit_button ".$options['class']."\"";
725		}
726		else
727		{
728			$input .= " class=\"submit_button\"";
729		}
730		if(isset($options['id']))
731		{
732			$input .= " id=\"".$options['id']."\"";
733		}
734		if(isset($options['name']))
735		{
736			$input .= " name=\"".$options['name']."\"";
737		}
738		$input .= " />";
739		return $input;
740	}
741
742	/**
743	 * Generate a yes/no radio button choice.
744	 *
745	 * @param string $name The name of the yes/no choice field.
746	 * @param string $value The value that should be checked.
747	 * @param boolean $int Using integers for the checkbox?
748	 * @param array $yes_options Array of options for the yes checkbox (@see generate_radio_button)
749	 * @param array $no_options Array of options for the no checkbox (@see generate_radio_button)
750	 * @return string The generated yes/no radio button.
751	 */
752	function generate_yes_no_radio($name, $value="1", $int=true, $yes_options=array(), $no_options = array())
753	{
754		global $lang;
755
756		// Checked status
757		if($value === "no" || $value === '0' || $value === 0)
758		{
759			$no_checked = 1;
760			$yes_checked = 0;
761		}
762		else
763		{
764			$yes_checked = 1;
765			$no_checked = 0;
766		}
767		// Element value
768		if($int == true)
769		{
770			$yes_value = 1;
771			$no_value = 0;
772		}
773		else
774		{
775			$yes_value = "yes";
776			$no_value = "no";
777		}
778
779		if(!isset($yes_options['class']))
780		{
781			$yes_options['class'] = '';
782		}
783
784		if(!isset($no_options['class']))
785		{
786			$no_options['class'] = '';
787		}
788
789		// Set the options straight
790		$yes_options['class'] = "radio_yes ".$yes_options['class'];
791		$yes_options['checked'] = $yes_checked;
792		$no_options['class'] = "radio_no ".$no_options['class'];
793		$no_options['checked'] = $no_checked;
794
795		$yes = $this->generate_radio_button($name, $yes_value, $lang->yes, $yes_options);
796		$no = $this->generate_radio_button($name, $no_value, $lang->no, $no_options);
797		return $yes." ".$no;
798	}
799
800	/**
801	 * Generate an on/off radio button choice.
802	 *
803	 * @param string $name The name of the on/off choice field.
804	 * @param int $value The value that should be checked.
805	 * @param boolean $int Using integers for the checkbox?
806	 * @param array $on_options Array of options for the on checkbox (@see generate_radio_button)
807	 * @param array $off_options Array of options for the off checkbox (@see generate_radio_button)
808	 * @return string The generated on/off radio button.
809	 */
810	function generate_on_off_radio($name, $value=1, $int=true, $on_options=array(), $off_options = array())
811	{
812		global $lang;
813
814		// Checked status
815		if($value == "off" || (int) $value !== 1)
816		{
817			$off_checked = 1;
818			$on_checked = 0;
819		}
820		else
821		{
822			$on_checked = 1;
823			$off_checked = 0;
824		}
825		// Element value
826		if($int == true)
827		{
828			$on_value = 1;
829			$off_value = 0;
830		}
831		else
832		{
833			$on_value = "on";
834			$off_value = "off";
835		}
836
837		// Set the options straight
838		if(!isset($on_options['class']))
839		{
840			$on_options['class'] = '';
841		}
842
843		if(!isset($off_options['class']))
844		{
845			$off_options['class'] = '';
846		}
847
848		$on_options['class'] = "radio_on ".$on_options['class'];
849		$on_options['checked'] = $on_checked;
850		$off_options['class'] = "radio_off ".$off_options['class'];
851		$off_options['checked'] = $off_checked;
852
853		$on = $this->generate_radio_button($name, $on_value, $lang->on, $on_options);
854		$off = $this->generate_radio_button($name, $off_value, $lang->off, $off_options);
855		return $on." ".$off;
856	}
857
858	/**
859	 * @param string $name
860	 * @param int $day
861	 * @param int $month
862	 * @param int $year
863	 *
864	 * @return string
865	 */
866	function generate_date_select($name, $day=0,$month=0,$year=0)
867	{
868		global $lang;
869
870		$months = array(
871			1 => $lang->january,
872			2 => $lang->february,
873			3 => $lang->march,
874			4 => $lang->april,
875			5 => $lang->may,
876			6 => $lang->june,
877			7 => $lang->july,
878			8 => $lang->august,
879			9 => $lang->september,
880			10 => $lang->october,
881			11 => $lang->november,
882			12 => $lang->december,
883		);
884
885		// Construct option list for days
886		$days = array();
887		for($i = 1; $i <= 31; ++$i)
888		{
889			$days[$i] = $i;
890		}
891
892		if(!$day)
893		{
894			$day = date("j", TIME_NOW);
895		}
896
897		if(!$month)
898		{
899			$month = date("n", TIME_NOW);
900		}
901
902		if(!$year)
903		{
904			$year = date("Y", TIME_NOW);
905		}
906
907		$built = $this->generate_select_box($name.'_day', $days, (int)$day, array('id' => $name.'_day'))." &nbsp; ";
908		$built .= $this->generate_select_box($name.'_month', $months, (int)$month, array('id' => $name.'_month'))." &nbsp; ";
909		$built .= $this->generate_numeric_field($name.'_year', $year, array('id' => $name.'_year', 'style' => 'width: 100px;', 'min' => 0));
910		return $built;
911	}
912
913	/**
914	 * Output a row of buttons in a wrapped container.
915	 *
916	 * @param array $buttons Array of the buttons (html) to output.
917	 * @return string The submit wrapper (optional)
918	 */
919	function output_submit_wrapper($buttons)
920	{
921		global $plugins;
922		$buttons = $plugins->run_hooks("admin_form_output_submit_wrapper", $buttons);
923		$return = "<div class=\"form_button_wrapper\">\n";
924		foreach($buttons as $button)
925		{
926			$return .= $button." \n";
927		}
928		$return .= "</div>\n";
929		if($this->_return == false)
930		{
931			echo $return;
932		}
933		else
934		{
935			return $return;
936		}
937	}
938
939	/**
940	 * Finish up a form.
941	 *
942	 * @return string The ending form tag (optional)
943	 */
944	function end()
945	{
946		global $plugins;
947		$plugins->run_hooks("admin_form_end", $this);
948		if($this->_return == false)
949		{
950			echo "</form>";
951		}
952		else
953		{
954			return "</form>";
955		}
956	}
957}
958
959/**
960 * Generate a form container.
961 */
962class DefaultFormContainer
963{
964	/** @var Table */
965	private $_container;
966	/** @var string */
967	public $_title;
968
969	/**
970	 * Initialise the new form container.
971	 *
972	 * @param string $title The title of the form container
973	 * @param string $extra_class An additional class to apply if we have one.
974	 */
975	function __construct($title='', $extra_class='')
976	{
977		$this->_container = new Table;
978		$this->extra_class = $extra_class;
979		$this->_title = $title;
980	}
981
982	/**
983	 * Output a header row of the form container.
984	 *
985	 * @param string $title The header row label.
986	 * @param array $extra Array of extra information for this header cell (class, style, colspan, width)
987	 */
988	function output_row_header($title, $extra=array())
989	{
990		$this->_container->construct_header($title, $extra);
991	}
992
993	/**
994	 * Output a row of the form container.
995	 *
996	 * @param string $title The title of the row.
997	 * @param string $description The description of the row/field.
998	 * @param string $content The HTML content to show in the row.
999	 * @param string $label_for The ID of the control this row should be a label for.
1000	 * @param array $options Array of options for the row cell.
1001	 * @param array $row_options Array of options for the row container.
1002	 */
1003	function output_row($title, $description="", $content="", $label_for="", $options=array(), $row_options=array())
1004	{
1005		global $plugins;
1006		$pluginargs = array(
1007			'title' => &$title,
1008			'description' => &$description,
1009			'content' => &$content,
1010			'label_for' => &$label_for,
1011			'options' => &$options,
1012			'row_options' => &$row_options,
1013			'this' => &$this
1014		);
1015
1016		$plugins->run_hooks("admin_formcontainer_output_row", $pluginargs);
1017
1018		$row = $for = '';
1019		if($label_for != '')
1020		{
1021			$for = " for=\"{$label_for}\"";
1022		}
1023
1024		if($title)
1025		{
1026			$row = "<label{$for}>{$title}</label>";
1027		}
1028
1029		if($description != '')
1030		{
1031			$row .= "\n<div class=\"description\">{$description}</div>\n";
1032		}
1033
1034		$row .= "<div class=\"form_row\">{$content}</div>\n";
1035
1036		$this->_container->construct_cell($row, $options);
1037
1038		if(!isset($options['skip_construct']))
1039		{
1040			$this->_container->construct_row($row_options);
1041		}
1042	}
1043
1044	/**
1045	 * Output a row cell for a table based form row.
1046	 *
1047	 * @param string $data The data to show in the cell.
1048	 * @param array $options Array of options for the cell (optional).
1049	 */
1050	function output_cell($data, $options=array())
1051	{
1052		$this->_container->construct_cell($data, $options);
1053	}
1054
1055	/**
1056	 * Build a row for the table based form row.
1057	 *
1058	 * @param array $extra Array of extra options for the cell (optional).
1059	 */
1060	function construct_row($extra=array())
1061	{
1062		$this->_container->construct_row($extra);
1063	}
1064
1065	/**
1066	 * return the cells of a row for the table based form row.
1067	 *
1068	 * @param string $row_id The id of the row.
1069	 * @param boolean $return Whether or not to return or echo the resultant contents.
1070	 * @return string The output of the row cells (optional).
1071	 */
1072	function output_row_cells($row_id, $return=false)
1073	{
1074		if(!$return)
1075		{
1076			echo $this->_container->output_row_cells($row_id, $return);
1077		}
1078		else
1079		{
1080			return $this->_container->output_row_cells($row_id, $return);
1081		}
1082	}
1083
1084	/**
1085	 * Count the number of rows in the form container. Useful for displaying a 'no rows' message.
1086	 *
1087	 * @return int The number of rows in the form container.
1088	 */
1089	function num_rows()
1090	{
1091		return $this->_container->num_rows();
1092	}
1093
1094	/**
1095	 * Output the end of the form container row.
1096	 *
1097	 * @param boolean $return Whether or not to return or echo the resultant contents.
1098	 * @return string The output of the form container (optional).
1099	 */
1100	function end($return=false)
1101	{
1102		global $plugins;
1103
1104		$hook = array(
1105			'return'	=> &$return,
1106			'this'		=> &$this
1107		);
1108
1109		$plugins->run_hooks("admin_formcontainer_end", $hook);
1110		if($return == true)
1111		{
1112			return $this->_container->output($this->_title, 1, "general form_container {$this->extra_class}", true);
1113		}
1114		else
1115		{
1116			echo $this->_container->output($this->_title, 1, "general form_container {$this->extra_class}", false);
1117		}
1118	}
1119}
1120