baseline
[omp.pkp.sfu.ca.git] / lib / pkp / classes / form / Form.inc.php
blobe7800b07a60e92cba2852ec82afd5df26e2b101e
1 <?php
3 /**
4 * @file classes/form/Form.inc.php
6 * Copyright (c) 2000-2009 John Willinsky
7 * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
9 * @class Form
10 * @ingroup core
12 * @brief Class defining basic operations for handling HTML forms.
15 // $Id: Form.inc.php,v 1.6 2009/09/22 21:18:26 asmecher Exp $
18 import('form.FormError');
19 import('form.validation.FormValidator');
21 class Form {
23 /** The template file containing the HTML form */
24 var $_template;
26 /** Associative array containing form data */
27 var $_data;
29 /** Validation checks for this form */
30 var $_checks;
32 /** Errors occurring in form validation */
33 var $_errors;
35 /** Array of field names where an error occurred and the associated error message */
36 var $errorsArray;
38 /** Array of field names where an error occurred */
39 var $errorFields;
41 /**
42 * Constructor.
43 * @param $template string the path to the form template file
45 function Form($template, $callHooks = true) {
46 if ($callHooks === true && checkPhpVersion('4.3.0')) {
47 $trace = debug_backtrace();
48 // Call hooks based on the calling entity, assuming
49 // this method is only called by a subclass. Results
50 // in hook calls named e.g. "papergalleyform::Constructor"
51 // Note that class names are always lower case.
52 HookRegistry::call(strtolower($trace[1]['class']) . '::Constructor', array(&$this, &$template));
55 $this->_template = $template;
56 $this->_data = array();
57 $this->_checks = array();
58 $this->_errors = array();
59 $this->errorsArray = array();
60 $this->errorFields = array();
63 /**
64 * Display the form.
66 function display() {
67 $templateMgr =& TemplateManager::getManager();
68 $templateMgr->setCacheability(CACHEABILITY_NO_STORE);
69 $templateMgr->register_function('fieldLabel', array(&$this, 'smartyFieldLabel'));
70 $templateMgr->register_function('form_language_chooser', array(&$this, 'smartyFormLanguageChooser'));
72 $templateMgr->assign($this->_data);
73 $templateMgr->assign('isError', !$this->isValid());
74 $templateMgr->assign('errors', $this->getErrorsArray());
76 $templateMgr->assign('formLocales', Locale::getSupportedFormLocales());
78 // Determine the current locale to display fields with
79 $formLocale = Request::getUserVar('formLocale');
80 if (empty($formLocale) || !in_array($formLocale, array_keys(Locale::getAllLocales()))) {
81 $formLocale = Locale::getLocale();
83 $templateMgr->assign('formLocale', $formLocale);
85 $templateMgr->display($this->_template);
88 /**
89 * Get the value of a form field.
90 * @param $key string
91 * @return mixed
93 function getData($key) {
94 return isset($this->_data[$key]) ? $this->_data[$key] : null;
97 /**
98 * Set the value of a form field.
99 * @param $key
100 * @param $value
102 function setData($key, $value) {
104 if (is_string($value)) $value = Core::cleanVar($value);
106 $this->_data[$key] = $value;
110 * Initialize form data for a new form.
112 function initData() {
116 * Assign form data to user-submitted data.
118 function readInputData() {
122 * Validate form data.
124 function validate($callHooks = true) {
125 if (!isset($this->errorsArray)) {
126 $this->getErrorsArray();
129 foreach ($this->_checks as $check) {
130 // WARNING: This line is for PHP4 compatibility when
131 // instantiating forms without reference. Should not
132 // be removed or otherwise used.
133 $check->_setForm($this);
135 if (!isset($this->errorsArray[$check->getField()]) && !$check->isValid()) {
136 if (method_exists($check, 'getErrorFields') && method_exists($check, 'isArray') && call_user_func(array(&$check, 'isArray'))) {
137 $errorFields = call_user_func(array(&$check, 'getErrorFields'));
138 for ($i=0, $count=count($errorFields); $i < $count; $i++) {
139 $this->addError($errorFields[$i], $check->getMessage());
140 $this->errorFields[$errorFields[$i]] = 1;
142 } else {
143 $this->addError($check->getField(), $check->getMessage());
144 $this->errorFields[$check->getField()] = 1;
149 if ($callHooks === true && checkPhpVersion('4.3.0')) {
150 $trace = debug_backtrace();
151 // Call hooks based on the calling entity, assuming
152 // this method is only called by a subclass. Results
153 // in hook calls named e.g. "papergalleyform::validate"
154 // Note that class and function names are always lower
155 // case.
156 $value = null;
157 if (HookRegistry::call(strtolower($trace[0]['class'] . '::' . $trace[0]['function']), array(&$this, &$value))) {
158 return $value;
162 return $this->isValid();
166 * Execute the form's action.
167 * (Note that it is assumed that the form has already been validated.)
169 function execute() {
173 * Get the list of field names that need to support multiple locales
174 * @return array
176 function getLocaleFieldNames() {
177 return array();
181 * Determine whether or not the current request results from a resubmit
182 * of locale data resulting from a form language change.
183 * @return boolean
185 function isLocaleResubmit() {
186 $formLocale = Request::getUserVar('formLocale');
187 return (!empty($formLocale));
191 * Get the current form locale.
192 * @return string
194 function getFormLocale() {
195 $formLocale = Request::getUserVar('formLocale');
196 if (empty($formLocale)) $formLocale = Locale::getLocale();
197 return $formLocale;
201 * Adds specified user variables to input data.
202 * @param $vars array the names of the variables to read
204 function readUserVars($vars) {
205 foreach ($vars as $k) {
206 $this->setData($k, Request::getUserVar($k));
211 * Adds specified user date variables to input data.
212 * @param $vars array the names of the date variables to read
214 function readUserDateVars($vars) {
215 foreach ($vars as $k) {
216 $this->setData($k, Request::getUserDateVar($k));
221 * Add a validation check to the form.
222 * @param $formValidator FormValidator
224 function addCheck($formValidator) {
225 $this->_checks[] =& $formValidator;
229 * Add an error to the form.
230 * Errors are typically assigned as the form is validated.
231 * @param $field string the name of the field where the error occurred
233 function addError($field, $message) {
234 $this->_errors[] = new FormError($field, $message);
238 * Add an error field for highlighting on form
239 * @param $field string the name of the field where the error occurred
241 function addErrorField($field) {
242 $this->errorFields[$field] = 1;
246 * Check if form passes all validation checks.
247 * @return boolean
249 function isValid() {
250 return empty($this->_errors);
254 * Return set of errors that occurred in form validation.
255 * If multiple errors occurred processing a single field, only the first error is included.
256 * @return array erroneous fields and associated error messages
258 function getErrorsArray() {
259 $this->errorsArray = array();
260 foreach ($this->_errors as $error) {
261 if (!isset($this->errorsArray[$error->getField()])) {
262 $this->errorsArray[$error->getField()] = $error->getMessage();
265 return $this->errorsArray;
269 * Custom Smarty function for labelling/highlighting of form fields.
270 * @param $params array can contain 'name' (field name/ID), 'required' (required field), 'key' (localization key), 'label' (non-localized label string), 'suppressId' (boolean)
271 * @param $smarty Smarty
273 function smartyFieldLabel($params, &$smarty) {
274 if (isset($params) && !empty($params)) {
275 if (isset($params['key'])) {
276 $params['label'] = Locale::translate($params['key'], $params);
279 if (isset($this->errorFields[$params['name']])) {
280 $class = ' class="error"';
281 } else {
282 $class = '';
284 echo '<label' . (isset($params['suppressId']) ? '' : ' for="' . $params['name'] . '"'), $class, '>', $params['label'], (isset($params['required']) && !empty($params['required']) ? '*' : ''), '</label>';
288 function _decomposeArray($name, $value, $stack) {
289 if (is_array($value)) {
290 foreach ($value as $key => $subValue) {
291 $newStack = $stack;
292 $newStack[] = $key;
293 $this->_decomposeArray($name, $subValue, $newStack);
295 } else {
296 $name = htmlentities($name, ENT_COMPAT, LOCALE_ENCODING);
297 $value = htmlentities($value, ENT_COMPAT, LOCALE_ENCODING);
298 echo '<input type="hidden" name="' . $name;
299 while (($item = array_shift($stack)) !== null) {
300 $item = htmlentities($item, ENT_COMPAT, LOCALE_ENCODING);
301 echo '[' . $item . ']';
303 echo '" value="' . $value . "\" />\n";
308 * Add hidden form parameters for the localized fields for this form
309 * and display the language chooser field
310 * @param $params array
311 * @param $smarty object
313 function smartyFormLanguageChooser($params, &$smarty) {
314 // Echo back all non-current language field values so that they
315 // are not lost.
316 $formLocale = $smarty->get_template_vars('formLocale');
317 foreach ($this->getLocaleFieldNames() as $field) {
318 $values = $this->getData($field);
319 if (!is_array($values)) continue;
320 foreach ($values as $locale => $value) {
321 if ($locale != $formLocale) $this->_decomposeArray($field, $value, array($locale));
325 // Display the language selector widget.
326 $formLocale = $smarty->get_template_vars('formLocale');
327 echo '<div id="languageSelector"><select size="1" name="formLocale" id="formLocale" onchange="changeFormAction(\'' . htmlentities($params['form'], ENT_COMPAT, LOCALE_ENCODING) . '\', \'' . htmlentities($params['url'], ENT_QUOTES, LOCALE_ENCODING) . '\')" class="selectMenu">';
328 foreach (Locale::getSupportedLocales() as $locale => $name) {
329 echo '<option ' . ($locale == $formLocale?'selected="selected" ':'') . 'value="' . htmlentities($locale, ENT_COMPAT, LOCALE_ENCODING) . '">' . htmlentities($name, ENT_COMPAT, LOCALE_ENCODING) . '</option>';
331 echo '</select></div>';