Newer
Older
$data = $this->field->getSource();
$config = $this->field->getConfiguration();
if ($datetime = parent::getValue()) {
$datetime = is_int($datetime) ? $datetime :
strtotime($datetime);
if ($datetime && isset($data[$this->name . ':time'])) {
list($hr, $min) = explode(':', $data[$this->name . ':time']);
$datetime += $hr * 3600 + $min * 60;
}
if ($datetime && $config['gmt']) {
// Convert to GMT time
$tz = new DateTimeZone($cfg->getTimezone());
$D = DateTime::createFromFormat('U', $datetime);
$datetime -= $tz->getOffset($D);
}
class SectionBreakWidget extends Widget {
?><div class="form-header section-break"><h3><?php
echo Format::htmlchars($this->field->getLocal('label'));
?></h3><em><?php echo Format::htmlchars($this->field->getLocal('hint'));
?></em></div>
<?php
}
}
class ThreadEntryWidget extends Widget {
$object_id = false;
if ($options['client']) {
$namespace = $options['draft-namespace']
?: 'ticket.client';
$object_id = substr(session_id(), -12);
} else {
$namespace = $options['draft-namespace'] ?: 'ticket.staff';
list($draft, $attrs) = Draft::getDraftAndDataAttrs($namespace, $object_id, $this->value);
<span class="required"><?php
echo Format::htmlchars($this->field->getLocal('label'));
?>: <span class="error">*</span></span><br/>
<textarea style="width:100%;" name="<?php echo $this->field->get('name'); ?>"
placeholder="<?php echo Format::htmlchars($this->field->get('hint')); ?>"
class="<?php if ($cfg->isRichTextEnabled()) echo 'richtext';
?> draft draft-delete" <?php echo $attrs; ?>
cols="21" rows="8" style="width:80%;"><?php echo
$draft ?: Format::htmlchars($this->value); ?></textarea>
$config = $this->field->getConfiguration();
if (!$config['attachments'])
return;
$attachments = $this->getAttachments($config);
print $attachments->render($options);
foreach ($attachments->getMedia() as $type=>$urls) {
foreach ($urls as $url)
Form::emitMedia($url, $type);
function getAttachments($config=false) {
if (!$config)
$config = $this->field->getConfiguration();
$field = new FileUploadField(array(
'id'=>'attach',
'name'=>'attach:' . $this->field->get('id'),
'configuration'=>$config)
);
$field->setForm($this->field->getForm());
return $field;
class FileUploadWidget extends Widget {
static $media = array(
'css' => array(
'/css/filedrop.css',
),
);
$config = $this->field->getConfiguration();
$name = $this->field->getFormName();
$id = substr(md5(spl_object_hash($this)), 10);
$attachments = $this->field->getFiles();
$mimetypes = array_filter($config['__mimetypes'],
function($t) { return strpos($t, '/') !== false; }
);
$maxfilesize = ($config['size'] ?: 1048576) / 1048576;
$files = $F = array();
$new = array_fill_keys($this->field->getClean(), 1);
foreach ($attachments as $f) {
$F[] = $f->file;
}
// Add in newly added files not yet saved (if redisplaying after an
// error)
if ($new) {
$F = array_merge($F, AttachmentFile::objects()->filter(array(
'id__in' => array_keys($new)))->all());
}
foreach ($F as $file) {
$files[] = array(
'id' => $file->getId(),
'name' => $file->getName(),
'type' => $file->getType(),
'size' => $file->getSize(),
'download_url' => $file->getDownloadUrl(),
);
?><div id="<?php echo $id;
?>" class="filedrop"><div class="files"></div>
<div class="dropzone"><i class="icon-upload"></i>
<?php echo sprintf(
__('Drop files here or %s choose them %s'),
'<a href="#" class="manual">', '</a>'); ?>
<input type="file" multiple="multiple"
id="file-<?php echo $id; ?>" style="display:none;"
accept="<?php echo implode(',', $config['__mimetypes']); ?>"/>
$(function(){$('#<?php echo $id; ?> .dropzone').filedropbox({
url: 'ajax.php/form/upload/<?php echo $this->field->get('id') ?>',
link: $('#<?php echo $id; ?>').find('a.manual'),
fallback_id: 'file-<?php echo $id; ?>',
allowedfileextensions: <?php echo JsonDataEncoder::encode(
$config['__extensions'] ?: array()); ?>,
allowedfiletypes: <?php echo JsonDataEncoder::encode(
maxfiles: <?php echo $config['max'] ?: 20; ?>,
maxfilesize: <?php echo $maxfilesize; ?>,
name: '<?php echo $name; ?>[]',
files: <?php echo JsonDataEncoder::encode($files); ?>
});});
</script>
<?php
}
function getValue() {
$ids = array();
// Handle manual uploads (IE<10)
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES[$this->name])) {
foreach (AttachmentFile::format($_FILES[$this->name]) as $file) {
$F = $this->field->uploadFile($file);
$ids[] = $F->getId();
// If no value was sent, assume an empty list
$base = parent::getValue();
if (!$base)
if (is_array($base)) {
foreach ($base as $info) {
@list($id, $name) = explode(',', $info, 2);
// Keep the values as the IDs
if ($name)
$ids[$name] = $id;
else
$ids[] = $id;
}
}
class FileUploadError extends Exception {}
class FreeTextField extends FormField {
static $widget = 'FreeTextWidget';
function getConfigurationOptions() {
return array(
'content' => new TextareaField(array(
'configuration' => array('html' => true, 'size'=>'large'),
'label'=>__('Content'), 'required'=>true, 'default'=>'',
'hint'=>__('Free text shown in the form, such as a disclaimer'),
)),
'attachments' => new FileUploadField(array(
'id'=>'attach',
'name'=>'files',
'configuration' => array('extensions'=>'')
)),
);
}
function hasData() {
return false;
}
function isBlockLevel() {
return true;
}
/* utils */
function to_config($config) {
$keepers = array();
if ($config && isset($config['attachments']))
foreach ($config['attachments'] as $fid)
$keepers[] = $fid;
$this->getAttachments()->keepOnlyFileIds($keepers);
return $config;
}
function db_cleanup($field=false) {
$this->getAttachments()->deleteAll();
}
function getAttachments() {
if (!isset($this->attachments))
$this->attachments = GenericAttachments::forIdAndType($this->get('id'), 'I');
return $this->attachments;
}
function getFiles() {
if (!($attachments = $this->getAttachments()))
return array();
return $attachments->all();
}
}
class FreeTextWidget extends Widget {
?><div class=""><?php
if ($label = $this->field->getLocal('label')) { ?>
<h3><?php
echo Format::htmlchars($label);
?></h3><?php
}
if ($hint = $this->field->getLocal('hint')) { ?>
<em><?php
echo Format::htmlchars($hint);
?></em><?php
} ?>
<div><?php
echo Format::viewableImages($config['content']); ?></div>
</div>
<?php
if (($attachments=$this->field->getFiles())) { ?>
<br/>
<section>
<?php foreach ($attachments as $attach) { ?>
<div>
<a href="<?php echo $attach->file->getDownloadUrl(); ?>"
target="_blank" class="no-pjax">
<i class="icon-file"></i>
<?php echo Format::htmlchars($attach->getFilename()); ?>
</a>
</div>
<?php } ?>
</section>
<?php }
class VisibilityConstraint {
const HIDDEN = 0x0001;
const VISIBLE = 0x0002;
var $initial;
var $constraint;
function __construct($constraint, $initial=self::VISIBLE) {
$this->constraint = $constraint;
$this->initial = $initial;
}
function emitJavascript($field) {
$func = 'recheck';
$form = $field->getForm();
?>
<script type="text/javascript">
!(function() {
var <?php echo $func; ?> = function() {
var target = $('#field<?php echo $field->getWidget()->id; ?>');
<?php $fields = $this->getAllFields($this->constraint);
foreach ($fields as $f) {
$field = $form->getField($f);
echo sprintf('var %1$s = $("#%1$s");',
}
$expression = $this->compileQ($this->constraint, $form);
?>
if (<?php echo $expression; ?>)
$(this).trigger('show');
});
else
target.slideUp('fast', function (){
$(this).trigger('hide');
});
};
<?php foreach ($fields as $f) {
$w = $form->getField($f)->getWidget();
?>
$('#<?php echo $w->id; ?>').on('change', <?php echo $func; ?>);
$('#field<?php echo $w->id; ?>').on('show hide', <?php
echo $func; ?>);
<?php } ?>
})();
</script><?php
}
/**
* Determines if the field was visible when the form was submitted
*/
function isVisible($field) {
return $this->compileQPhp($this->constraint, $field);
}
function compileQPhp(Q $Q, $field) {
if (!($form = $field->getForm())) {
return $this->initial == self::VISIBLE;
}
$expr = array();
foreach ($Q->constraints as $c=>$value) {
if ($value instanceof Q) {
$expr[] = $this->compileQPhp($value, $field);
}
else {
@list($f, $op) = explode('__', $c, 2);
$field = $form->getField($f);
$wval = $field->getClean();
switch ($op) {
case 'eq':
case null:
$expr[] = ($wval == $value && $field->isVisible());
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
}
}
}
$glue = $Q->isOred()
? function($a, $b) { return $a || $b; }
: function($a, $b) { return $a && $b; };
$initial = !$Q->isOred();
$expression = array_reduce($expr, $glue, $initial);
if ($Q->isNegated)
$expression = !$expression;
return $expression;
}
function getAllFields(Q $Q, &$fields=array()) {
foreach ($Q->constraints as $c=>$value) {
if ($c instanceof Q) {
$this->getAllFields($c, $fields);
}
else {
list($f, $op) = explode('__', $c, 2);
$fields[$f] = true;
}
}
return array_keys($fields);
}
function compileQ($Q, $form) {
$expr = array();
foreach ($Q->constraints as $c=>$value) {
if ($value instanceof Q) {
$expr[] = $this->compileQ($value, $form);
}
else {
list($f, $op) = explode('__', $c, 2);
$widget = $form->getField($f)->getWidget();
$id = $widget->id;
$expr[] = sprintf('(%s.is(":visible") && %s)',
$id,
sprintf('%s == %s',
sprintf($widget->getJsValueGetter(), $id),
JsonDataEncoder::encode($value))
);
}
}
}
$glue = $Q->isOred() ? ' || ' : ' && ';
$expression = implode($glue, $expr);
if (count($expr) > 1)
$expression = '('.$expression.')';
if ($Q->isNegated)
$expression = '!'.$expression;
return $expression;
}
}
class AssignmentForm extends Form {
static $id = 'assign';
var $_assignee = null;
function __construct($source=null, $options=array()) {
parent::__construct($source, $options);
// Department of the object -- if necessary to limit assinees
if (isset($options['dept']))
$this->_dept = $options['dept'];
}
function getFields() {
if ($this->fields)
return $this->fields;
$fields = array(
'assignee' => new AssigneeField(array(
'id'=>1,
'label' => __('Assignee'),
'flags' => hexdec(0X450F3),
'required' => true,
'validator-error' => __('Assignee selection required'),
'configuration' => array(
'criteria' => array(
'available' => true,
),
'dept' => $this->_dept ?: null,
),
)
),
'comments' => new TextareaField(array(
'id' => 2,
'label'=> '',
'required'=>false,
'default'=>'',
'configuration' => array(
'html' => true,
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
'placeholder' => __('Optional reason for the assignment'),
),
)
),
);
$this->setFields($fields);
return $this->fields;
}
function isValid() {
if (!parent::isValid())
return false;
// Do additional assignment validation
if (!($assignee = $this->getAssignee())) {
$this->getField('assignee')->addError(
__('Unknown assignee'));
} elseif ($assignee instanceof Staff) {
// Make sure the agent is available
if (!$assignee->isAvailable())
$this->getField('assignee')->addError(
__('Agent is unavailable for assignment')
);
}
return !$this->errors();
}
function getClean() {
return parent::getClean();
}
function render($options) {
switch(strtolower($options['template'])) {
case 'simple':
$inc = STAFFINC_DIR . 'templates/dynamic-form-simple.tmpl.php';
break;
default:
throw new Exception(sprintf(__('%s: Unknown template style %s'),
'FormUtils', $options['template']));
}
$form = $this;
include $inc;
}
function getAssignee() {
if (!isset($this->_assignee)) {
$value = $this->getField('assignee')->getClean();
if ($value[0] == 's')
$this->_assignee = Staff::lookup(substr($value, 1));
elseif ($value[0] == 't')
$this->_assignee = Team::lookup(substr($value, 1));
}
return $this->_assignee;
}
function assigneeCriteria() {
$dept = $this->id;
return function () use($dept) {
return array('dept_id' =>$dept);
};
}
}
class TransferForm extends Form {
static $id = 'transfer';
var $_dept = null;
function __construct($source=null, $options=array()) {
parent::__construct($source, $options);
}
function getFields() {
if ($this->fields)
return $this->fields;
$fields = array(
'dept' => new DepartmentField(array(
'id'=>1,
'label' => __('Department'),
'flags' => hexdec(0X450F3),
'required' => true,
'validator-error' => __('Department selection required'),
)
),
'comments' => new TextareaField(array(
'id' => 2,
'label'=> '',
'required'=>false,
'default'=>'',
'configuration' => array(
'html' => true,
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
'placeholder' => __('Optional reason for the transfer'),
),
)
),
);
$this->setFields($fields);
return $this->fields;
}
function isValid() {
if (!parent::isValid())
return false;
// Do additional validations
if (!($dept = $this->getDept()))
$this->getField('dept')->addError(
__('Unknown department'));
return !$this->errors();
}
function getClean() {
return parent::getClean();
}
function render($options) {
switch(strtolower($options['template'])) {
case 'simple':
$inc = STAFFINC_DIR . 'templates/dynamic-form-simple.tmpl.php';
break;
default:
throw new Exception(sprintf(__('%s: Unknown template style %s'),
get_class(), $options['template']));
}
$form = $this;
include $inc;
}
function getDept() {
if (!isset($this->_dept)) {
if (($id = $this->getField('dept')->getClean()))
$this->_dept = Dept::lookup($id);
}
return $this->_dept;
}
}
/**
* FieldUnchanged
*
* Thrown in the to_database() method to indicate the value should not be
* saved in the database (it wasn't changed in the request)
*/
class FieldUnchanged extends Exception {}