a tiny mvc framework for php using php-activerecord
1<?php
2/*
3 build a <form> based on an object
4*/
5
6namespace HalfMoon;
7
8require_once("form_common.php");
9
10class FormHelper extends FormTagHelper {
11 public function form_for($obj, $url_or_obj, $options = array(),
12 \Closure $form_content) {
13 if (!$obj)
14 throw new HalfMoonException("invalid object passed to form_for()");
15
16 $this->form_object = $obj;
17
18 return $this->output_form_around_closure($url_or_obj, $options,
19 $form_content);
20 }
21
22 public function form_content_for($obj, $url_or_obj, $options = array(),
23 \Closure $form_content) {
24 if (!$obj)
25 throw new HalfMoonException("invalid object passed to form_for()");
26
27 $this->form_object = $obj;
28
29 $html = Utils::to_s($this, $form_content);
30
31 $this->form_object = null;
32
33 return $html;
34 }
35
36 /* the prefix to use for class and id names for fields */
37 protected function form_prefix() {
38 if (empty($this->form_prefix))
39 return strtolower(get_class($this->form_object));
40 else
41 return $this->form_prefix;
42 }
43
44 /* provide an html object id to use for a given field name */
45 public function prefixed_field_id($field) {
46 return preg_replace("/[^a-z0-9]/", "_",
47 $this->form_prefix() . "_" . $field);
48 }
49
50 /* provide an html object name to use for a given field name */
51 public function prefixed_field_name($field) {
52 return $this->form_prefix() . "[" . $field . "]";
53 }
54
55 /* return the value of the particular field for the form object */
56 protected function value_for_field($field, $options) {
57 /* value is being statically overridden */
58 if (isset($options["value"]))
59 return $options["value"];
60 /* if we have an array-looking name of field[var], use an AR getter of
61 * field(var) */
62 elseif (preg_match("/^(.+)\[([^\]]+)\]$/", $field, $m))
63 return $this->form_object->{"get_" . $m[1]}($m[2]);
64 else
65 return $this->form_object->$field;
66 }
67
68 /* honor names/ids passed through as options */
69 private function set_field_id_and_name($field, $options) {
70 if (!isset($options["id"]))
71 $options["id"] = $this->prefixed_field_id($field);
72
73 if (!isset($options["name"]))
74 $options["name"] = $this->prefixed_field_name($field);
75
76 return $options;
77 }
78
79 /* create an <input type="checkbox"> with a hidden input field to detect
80 * when the checkbox has been unchecked (see rails docs for check_box, but
81 * since php presents $_GET and $_POST with the last seen value, we have to
82 * reverse the order of the checkbox and hidden input field) */
83 public function check_box($field, $options = array(), $checked_value = 1,
84 $unchecked_value = 0) {
85 if (!$this->form_object)
86 throw new HalfMoonException("no form object; you probably wanted "
87 . "check_box_tag");
88
89 $options = $this->set_field_id_and_name($field, $options);
90
91 return "<input"
92 . " type=\"hidden\" "
93 . " name=\"" . h($options["name"]) . "\""
94 . " value=\"" . h($unchecked_value) . "\""
95 . " />"
96 . $this->wrap_field_with_errors($field,
97 $this->check_box_tag($field, $checked_value,
98 (bool)$this->value_for_field($field, $options), $options)
99 );
100 }
101
102 /* create an <input> file upload field */
103 public function file_field($field, $options = array()) {
104 if (!$this->form_object)
105 throw new HalfMoonException("no form object; you probably wanted "
106 . "file_field_tag");
107
108 $options = $this->set_field_id_and_name($field, $options);
109
110 return $this->wrap_field_with_errors($field,
111 $this->file_field_tag($field, $options)
112 );
113 }
114
115 /* create a hidden <input> field */
116 public function hidden_field($field, $options = array()) {
117 if (!$this->form_object)
118 throw new HalfMoonException("no form object; you probably wanted "
119 . "hidden_field_tag");
120
121 $options = $this->set_field_id_and_name($field, $options);
122
123 return $this->hidden_field_tag($field, $this->value_for_field($field,
124 $options), $options);
125 }
126
127 /* create a <label> that references a field */
128 public function label($field, $caption = null, $options = array()) {
129 if (!$this->form_object)
130 throw new HalfMoonException("no form object; you probably wanted "
131 . "label_tag");
132
133 if (!isset($options["for"]))
134 $options["for"] = $this->prefixed_field_id($field);
135
136 return $this->label_tag($field, $caption, $options);
137 }
138
139 /* create an <input> password field, *not including any value* */
140 public function password_field($field, $options = array()) {
141 if (!$this->form_object)
142 throw new HalfMoonException("no form object; you probably wanted "
143 . "password_field_tag");
144
145 $options = $this->set_field_id_and_name($field, $options);
146
147 return $this->wrap_field_with_errors($field,
148 $this->password_field_tag($field, $value = null, $options)
149 );
150 }
151
152 /* create an <input> radio button */
153 public function radio_button($field, $value, $options = array()) {
154 if (!$this->form_object)
155 throw new HalfMoonException("no form object; you probably wanted "
156 . "radio_button_tag");
157
158 $options = $this->set_field_id_and_name($field, $options);
159
160 return $this->wrap_field_with_errors($field,
161 $this->radio_button_tag($field, $value,
162 ($this->value_for_field($field, $options) == $value), $options)
163 );
164 }
165
166 /* create a <select> box with options */
167 public function select($field, $choices, $options = array()) {
168 if (!$this->form_object)
169 throw new HalfMoonException("no form object; you probably wanted "
170 . "select_tag");
171
172 $options = $this->set_field_id_and_name($field, $options);
173
174 return $this->wrap_field_with_errors($field,
175 $this->select_tag($field, $choices, $this->value_for_field($field,
176 $options), $options)
177 );
178 }
179
180 /* create an <input> submit button */
181 public function submit_button($value = "Submit Changes",
182 $options = array()) {
183 if (!isset($options["name"]))
184 $options["name"] = "commit";
185
186 return $this->submit_tag($value, $options);
187 }
188
189 /* create a <textarea> field */
190 public function text_area($field, $options = array()) {
191 if (!$this->form_object)
192 throw new HalfMoonException("no form object; you probably wanted "
193 . "text_area_tag");
194
195 $options = $this->set_field_id_and_name($field, $options);
196
197 return $this->wrap_field_with_errors($field,
198 $this->text_area_tag($field, $this->value_for_field($field,
199 $options), $options)
200 );
201 }
202
203 /* create an <input> text field */
204 public function text_field($field, $options = array()) {
205 if (!$this->form_object)
206 throw new HalfMoonException("no form object; you probably wanted "
207 . "text_field_tag");
208
209 $options = $this->set_field_id_and_name($field, $options);
210
211 return $this->wrap_field_with_errors($field,
212 $this->text_field_tag($field, $this->value_for_field($field,
213 $options), $options)
214 );
215 }
216
217 /* create a <select> of grouped time zones */
218 public function time_zone_select($field, $options = array()) {
219 if (!$this->form_object)
220 throw new HalfMoonException("no form object; you probably wanted "
221 . "time_zone_select_tag");
222
223 $options = $this->set_field_id_and_name($field, $options);
224
225 return $this->wrap_field_with_errors($field,
226 $this->time_zone_select_tag($field,
227 $this->value_for_field($field, $options), $options)
228 );
229 }
230}
231
232?>