Newer
Older
<?php
/*********************************************************************
class.forms.php
osTicket forms framework
Jared Hancock <jared@osticket.com>
Copyright (c) 2006-2013 osTicket
http://www.osticket.com
Released under the GNU General Public License WITHOUT ANY WARRANTY.
See LICENSE.TXT for details.
vim: expandtab sw=4 ts=4 sts=4:
**********************************************************************/
/**
* Form template, used for designing the custom form and for entering custom
* data for a ticket
*/
class Form {
static $renderer = 'GridFluidLayout';
function __construct($source=null, $options=array()) {
if (isset($options['title']))
$this->title = $options['title'];
if (isset($options['instructions']))
$this->instructions = $options['instructions'];
if (isset($options['id']))
$this->id = $options['id'];
// Use POST data if source was not specified
$this->_source = ($source) ? $source : $_POST;
function getId() {
return static::$id;
}
function data($source) {
foreach ($this->fields as $name=>$f)
if (isset($source[$name]))
$f->value = $source[$name];
}
if (!is_array($fields) && !$fields instanceof Traversable)
return;
$this->fields = $fields;
foreach ($fields as $k=>$f) {
$f->setForm($this);
function getFields() {
return $this->fields;
}
$fields = $this->getFields();
foreach($fields as $f)
if(!strcasecmp($f->get('name'), $name))
return $f;
if (isset($fields[$name]))
return $fields[$name];
function hasField($name) {
return $this->getField($name);
}
function getTitle() { return $this->title; }
function getInstructions() { return $this->instructions; }
function getSource() { return $this->_source; }
function setSource($source) { $this->_source = $source; }
/**
* Validate the form and indicate if there no errors.
*
* Parameters:
* $filter - (callback) function to receive each field and return
* boolean true if the field's errors are significant
*/
function isValid($include=false) {
$this->validate($this->getClean());
foreach ($this->getFields() as $field)
if ($field->errors() && (!$include || $include($field)))
$this->_errors[$field->get('id')] = $field->errors();
}
return !$this->_errors;
}
function validate($clean_data) {
// Validate the whole form so that errors can be added to the
// individual fields and collected below.
foreach ($this->validators as $V) {
$V($this);
}
}
function getClean() {
if (!$this->_clean) {
$this->_clean = array();
foreach ($this->getFields() as $key=>$field) {
// Prefer indexing by field.id if indexing numerically
if (is_int($key) && $field->get('id'))
$key = $field->get('id');
$this->_clean[$key] = $this->_clean[$field->get('name')]
= $field->getClean();
}
}
return $this->_clean;
}
function errors($formOnly=false) {
return ($formOnly) ? $this->_errors['form'] : $this->_errors;
}
function addError($message, $index=false) {
if ($index)
$this->_errors[$index] = $message;
else
$this->_errors['form'][] = $message;
}
function addErrors($errors=array()) {
foreach ($errors as $k => $v) {
if (($f=$this->getField($k)))
$f->addError($v);
else
$this->addError($v, $k);
}
}
function addValidator($function) {
if (!is_callable($function))
throw new Exception('Form validator must be callable');
$this->validators[] = $function;
function render($staff=true, $title=false, $options=array()) {
if ($title)
$this->title = $title;
if (isset($options['instructions']))
$this->instructions = $options['instructions'];
$template = $options['template'] ?: 'dynamic-form.tmpl.php';
include(STAFFINC_DIR . 'templates/' . $template);
include(CLIENTINC_DIR . 'templates/' . $template);
function getLayout($title=false, $options=array()) {
$rc = @$options['renderer'] ?: static::$renderer;
return new $rc($title, $options);
}
function asTable($title=false, $options=array()) {
return $this->getLayout($title, $options)->asTable($this);
// XXX: Media can't go in a table
echo $this->getMedia();
}
function getMedia() {
static $dedup = array();
foreach ($this->getFields() as $f) {
if (($M = $f->getMedia()) && is_array($M)) {
foreach ($M as $type=>$files) {
foreach ($files as $url) {
$key = strtolower($type.$url);
if (isset($dedup[$key]))
continue;
self::emitMedia($url, $type);
$dedup[$key] = true;
}
}
}
}
}
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
function emitJavascript($options=array()) {
// Check if we need to emit javascript
if (!($fid=$this->getId()))
return;
?>
<script type="text/javascript">
$(function() {
<?php
//XXX: We ONLY want to watch field on this form. We'll only
// watch form inputs if form_id is specified. Current FORM API
// doesn't generate the entire form (just fields)
if ($fid) {
?>
$(document).off('change.<?php echo $fid; ?>');
$(document).on('change.<?php echo $fid; ?>',
'form#<?php echo $fid; ?> :input',
function() {
//Clear any current errors...
var errors = $('#field'+$(this).attr('id')+'_error');
if (errors.length)
errors.slideUp('fast', function (){
$(this).remove();
});
//TODO: Validation input inplace or via ajax call
// and set any new errors AND visibilty changes
}
);
<?php
}
?>
});
</script>
<?php
}
static function emitMedia($url, $type) {
if ($url[0] == '/')
$url = ROOT_PATH . substr($url, 1);
switch (strtolower($type)) {
case 'css': ?>
<link rel="stylesheet" type="text/css" href="<?php echo $url; ?>"/><?php
break;
case 'js': ?>
<script type="text/javascript" src="<?php echo $url; ?>"></script><?php
break;
}
}
/**
* getState
*
* Retrieves an array of information which can be passed to the
* ::loadState method later to recreate the current state of the form
* fields and values.
*/
function getState() {
$info = array();
foreach ($this->getFields() as $f) {
// Skip invisible fields
if (!$f->isVisible())
continue;
// Skip fields set to default values
$v = $f->getClean();
$d = $f->get('default');
if ($v == $d)
continue;
// Skip empty values
if (!$v)
continue;
$info[$f->get('name') ?: $f->get('id')] = $f->to_database($v);
}
return $info;
}
/**
* loadState
*
* Reset this form to the state previously recorded by the ::getState()
* method
*/
function loadState($state) {
foreach ($this->getFields() as $f) {
$name = $f->get('name');
$f->reset();
if (isset($state[$name])) {
$f->value = $f->to_php($state[$name]);
}
}
}
/*
* Initialize a generic static form
*/
static function instantiate() {
$r = new ReflectionClass(get_called_class());
return $r->newInstanceArgs(func_get_args());
}
}
/**
* SimpleForm
* Wrapper for inline/static forms.
*
*/
class SimpleForm extends Form {
function __construct($fields=array(), $source=null, $options=array()) {
parent::__construct($source, $options);
$this->setFields($fields);
}
class CustomForm extends SimpleForm {
function getFields() {
$isedit = ($options['mode'] == 'edit');
$fields = array();
foreach (parent::getFields() as $field) {
if ($isedit && !$field->isEditable($user))
continue;
$fields[] = $field;
}
return $fields;
}
}
Loading
Loading full blame...