1: <?php
2: /**
3: * This class represents a single form variable that may be rendered as one or
4: * more form fields.
5: *
6: * @author Robert E. Coyle <robertecoyle@hotmail.com>
7: * @package Form
8: */
9: class Horde_Form_Variable {
10:
11: /**
12: * The form instance this variable is assigned to.
13: *
14: * @var Horde_Form
15: */
16: var $form;
17:
18: /**
19: * A short description of this variable's purpose.
20: *
21: * @var string
22: */
23: var $humanName;
24:
25: /**
26: * The internally used name.
27: *
28: * @var string
29: */
30: var $varName;
31:
32: /**
33: * A {@link Horde_Form_Type} instance.
34: *
35: * @var Horde_Form_Type
36: */
37: var $type;
38:
39: /**
40: * Whether this is a required variable.
41: *
42: * @var boolean
43: */
44: var $required;
45:
46: /**
47: * Whether this is a readonly variable.
48: *
49: * @var boolean
50: */
51: var $readonly;
52:
53: /**
54: * A long description of the variable's purpose, special instructions, etc.
55: *
56: * @var string
57: */
58: var $description;
59:
60: /**
61: * The variable help text.
62: *
63: * @var string
64: */
65: var $help;
66:
67: /**
68: * Whether this is an array variable.
69: *
70: * @var boolean
71: */
72: var $_arrayVal;
73:
74: /**
75: * The default value.
76: *
77: * @var mixed
78: */
79: var $_defValue = null;
80:
81: /**
82: * A {@link Horde_Form_Action} instance.
83: *
84: * @var Horde_Form_Action
85: */
86: var $_action;
87:
88: /**
89: * Whether this variable is disabled.
90: *
91: * @var boolean
92: */
93: var $_disabled = false;
94:
95: /**
96: * TODO
97: *
98: * @var boolean
99: */
100: var $_autofilled = false;
101:
102: /**
103: * Whether this is a hidden variable.
104: *
105: * @var boolean
106: */
107: var = false;
108:
109: /**
110: * TODO
111: *
112: * @var array
113: */
114: var $_options = array();
115:
116: /**
117: * Variable constructor.
118: *
119: * @param string $humanName A short description of the variable's
120: * purpose.
121: * @param string $varName The internally used name.
122: * @param Horde_Form_Type $type A {@link Horde_Form_Type} instance.
123: * @param boolean $required Whether this is a required variable.
124: * @param boolean $readonly Whether this is a readonly variable.
125: * @param string $description A long description of the variable's
126: * purpose, special instructions, etc.
127: */
128: function Horde_Form_Variable($humanName, $varName, &$type, $required,
129: $readonly = false, $description = null)
130: {
131: $this->humanName = $humanName;
132: $this->varName = $varName;
133: $this->type = &$type;
134: $this->required = $required;
135: $this->readonly = $readonly;
136: $this->description = $description;
137: $this->_arrayVal = (strpos($varName, '[]') !== false);
138: }
139:
140: /**
141: * Assign this variable to the specified form.
142: *
143: * @param Horde_Form $form The form instance to assign this variable to.
144: */
145: function setFormOb(&$form)
146: {
147: $this->form = &$form;
148: }
149:
150: /**
151: * Sets a default value for this variable.
152: *
153: * @param mixed $value A variable value.
154: */
155: function setDefault($value)
156: {
157: $this->_defValue = $value;
158: }
159:
160: /**
161: * Returns this variable's default value.
162: *
163: * @return mixed This variable's default value.
164: */
165: function getDefault()
166: {
167: return $this->_defValue;
168: }
169:
170: /**
171: * Assigns an action to this variable.
172: *
173: * Example:
174: * <code>
175: * $v = &$form->addVariable('My Variable', 'var1', 'text', false);
176: * $v->setAction(Horde_Form_Action::factory('submit'));
177: * </code>
178: *
179: * @param Horde_Form_Action $action A {@link Horde_Form_Action} instance.
180: */
181: function setAction($action)
182: {
183: $this->_action = $action;
184: }
185:
186: /**
187: * Returns whether this variable has an attached action.
188: *
189: * @return boolean True if this variable has an attached action.
190: */
191: function hasAction()
192: {
193: return !is_null($this->_action);
194: }
195:
196: /**
197: * Makes this a hidden variable.
198: */
199: function hide()
200: {
201: $this->_hidden = true;
202: }
203:
204: /**
205: * Returns whether this is a hidden variable.
206: *
207: * @return boolean True if this a hidden variable.
208: */
209: function isHidden()
210: {
211: return $this->_hidden;
212: }
213:
214: /**
215: * Disables this variable.
216: */
217: function disable()
218: {
219: $this->_disabled = true;
220: }
221:
222: /**
223: * Returns whether this variable is disabled.
224: *
225: * @return boolean True if this variable is disabled.
226: */
227: function isDisabled()
228: {
229: return $this->_disabled;
230: }
231:
232: /**
233: * Return the short description of this variable.
234: *
235: * @return string A short description
236: */
237: function getHumanName()
238: {
239: return $this->humanName;
240: }
241:
242: /**
243: * Returns the internally used variable name.
244: *
245: * @return string This variable's internal name.
246: */
247: function getVarName()
248: {
249: return $this->varName;
250: }
251:
252: /**
253: * Returns this variable's type.
254: *
255: * @return Horde_Form_Type This variable's {@link Horde_Form_Type}
256: * instance.
257: */
258: function &getType()
259: {
260: return $this->type;
261: }
262:
263: /**
264: * Returns the name of this variable's type.
265: *
266: * @return string This variable's {@link Horde_Form_Type} name.
267: */
268: function getTypeName()
269: {
270: return $this->type->getTypeName();
271: }
272:
273: /**
274: * Returns whether this is a required variable.
275: *
276: * @return boolean True if this is a required variable.
277: */
278: function isRequired()
279: {
280: return $this->required;
281: }
282:
283: /**
284: * Returns whether this is a readonly variable.
285: *
286: * @return boolean True if this a readonly variable.
287: */
288: function isReadonly()
289: {
290: return $this->readonly;
291: }
292:
293: /**
294: * Returns the possible values of this variable.
295: *
296: * @return array The possible values of this variable or null.
297: */
298: function getValues()
299: {
300: return $this->type->getValues();
301: }
302:
303: /**
304: * Returns whether this variable has a long description.
305: *
306: * @return boolean True if this variable has a long description.
307: */
308: function hasDescription()
309: {
310: return !empty($this->description);
311: }
312:
313: /**
314: * Returns this variable's long description.
315: *
316: * @return string This variable's long description.
317: */
318: function getDescription()
319: {
320: return $this->description;
321: }
322:
323: /**
324: * Returns whether this is an array variable.
325: *
326: * @return boolean True if this an array variable.
327: */
328: function isArrayVal()
329: {
330: return $this->_arrayVal;
331: }
332:
333: /**
334: * Returns whether this variable is to upload a file.
335: *
336: * @return boolean True if variable is to upload a file.
337: */
338: function isUpload()
339: {
340: return ($this->type->getTypeName() == 'file');
341: }
342:
343: /**
344: * Assigns a help text to this variable.
345: *
346: * @param string $help The variable help text.
347: */
348: function setHelp($help)
349: {
350: $this->form->_help = true;
351: $this->help = $help;
352: }
353:
354: /**
355: * Returns whether this variable has some help text assigned.
356: *
357: * @return boolean True if this variable has a help text.
358: */
359: function hasHelp()
360: {
361: return !empty($this->help);
362: }
363:
364: /**
365: * Returns the help text of this variable.
366: *
367: * @return string This variable's help text.
368: */
369: function getHelp()
370: {
371: return $this->help;
372: }
373:
374: /**
375: * Sets a variable option.
376: *
377: * @param string $option The option name.
378: * @param mixed $val The option's value.
379: */
380: function setOption($option, $val)
381: {
382: $this->_options[$option] = $val;
383: }
384:
385: /**
386: * Returns a variable option's value.
387: *
388: * @param string $option The option name.
389: *
390: * @return mixed The option's value.
391: */
392: function getOption($option)
393: {
394: return isset($this->_options[$option]) ? $this->_options[$option] : null;
395: }
396:
397: /**
398: * Processes the submitted value of this variable according to the rules of
399: * the variable type.
400: *
401: * @param Variables $vars The {@link Variables} instance of the submitted
402: * form.
403: * @param mixed $info A variable passed by reference that will be
404: * assigned the processed value of the submitted
405: * variable value.
406: *
407: * @return mixed Depending on the variable type.
408: */
409: function getInfo(&$vars, &$info)
410: {
411: return $this->type->getInfo($vars, $this, $info);
412: }
413:
414: /**
415: * Returns whether this variable if it had the "trackchange" option set
416: * has actually been changed.
417: *
418: * @param Variables $vars The {@link Variables} instance of the submitted
419: * form.
420: *
421: * @return boolean Null if this variable doesn't have the "trackchange"
422: * option set or the form wasn't submitted yet. A boolean
423: * indicating whether the variable was changed otherwise.
424: */
425: function wasChanged(&$vars)
426: {
427: if (!$this->getOption('trackchange')) {
428: return null;
429: }
430: $old = $vars->get('__old_' . $this->getVarName());
431: if (is_null($old)) {
432: return null;
433: }
434: return $old != $vars->get($this->getVarName());
435: }
436:
437: /**
438: * Validates this variable.
439: *
440: * @param Variables $vars The {@link Variables} instance of the submitted
441: * form.
442: * @param string $message A variable passed by reference that will be
443: * assigned a descriptive error message if
444: * validation failed.
445: *
446: * @return boolean True if the variable validated.
447: */
448: function validate(&$vars, &$message)
449: {
450: if ($this->_arrayVal) {
451: $vals = $this->getValue($vars);
452: if (!is_array($vals)) {
453: if ($this->required) {
454: $message = Horde_Form_Translation::t("This field is required.");
455: return false;
456: } else {
457: return true;
458: }
459: }
460: foreach ($vals as $i => $value) {
461: if ($value === null && $this->required) {
462: $message = Horde_Form_Translation::t("This field is required.");
463: return false;
464: } else {
465: if (!$this->type->isValid($this, $vars, $value, $message)) {
466: return false;
467: }
468: }
469: }
470: } else {
471: $value = $this->getValue($vars);
472: return $this->type->isValid($this, $vars, $value, $message);
473: }
474:
475: return true;
476: }
477:
478: /**
479: * Returns the submitted or default value of this variable.
480: * If an action is attached to this variable, the value will get passed to
481: * the action object.
482: *
483: * @param Variables $vars The {@link Variables} instance of the submitted
484: * form.
485: * @param integer $index If the variable is an array variable, this
486: * specifies the array element to return.
487: *
488: * @return mixed The variable or element value.
489: */
490: function getValue(&$vars, $index = null)
491: {
492: if ($this->_arrayVal) {
493: $name = str_replace('[]', '', $this->varName);
494: } else {
495: $name = $this->varName;
496: }
497: $value = $vars->getExists($name, $wasset);
498:
499: if (!$wasset) {
500: $value = $this->getDefault();
501: }
502:
503: if ($this->_arrayVal && !is_null($index)) {
504: if (!$wasset && !is_array($value)) {
505: $return = $value;
506: } else {
507: $return = isset($value[$index]) ? $value[$index] : null;
508: }
509: } else {
510: $return = $value;
511: }
512:
513: if ($this->hasAction()) {
514: $this->_action->setValues($vars, $return, $this->_arrayVal);
515: }
516:
517: return $return;
518: }
519:
520: }
521: