Skip to content
Snippets Groups Projects
class.forms.php 143 KiB
Newer Older
  • Learn to ignore specific revisions
  •         // Canned attachments initiated by this session
            if (isset($_SESSION[':cannedFiles']))
               $allowed += $_SESSION[':cannedFiles'];
    
    
            // Parse the files and make sure it's allowed.
            foreach ($files as $info) {
                @list($id, $name) = explode(',', $info, 2);
                if (!isset($allowed[$id]))
                    continue;
    
                // 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';
    
        protected $attachments;
    
    
        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',
    
                    'label' => __('Attachments'),
    
                    'name'=>'files',
                    'configuration' => array('extensions'=>'')
                )),
    
            );
        }
    
        function hasData() {
            return false;
        }
    
        function isBlockLevel() {
            return true;
        }
    
    
        /* utils */
    
        function to_config($config) {
            if ($config && isset($config['attachments']))
    
                $keepers = $config['attachments'] = array_values($config['attachments']);
    
            $this->getAttachments()->keepOnlyFileIds($keepers);
    
            return $config;
        }
    
    
        function db_cleanup($field=false) {
    
            if ($field && $this->getFiles())
    
                $this->getAttachments()->deleteAll();
        }
    
        function getAttachments() {
            if (!isset($this->attachments))
                $this->attachments = GenericAttachments::forIdAndType($this->get('id'), 'I');
    
    
            return $this->attachments ?: array();
    
        }
    
        function getFiles() {
    
            if (!isset($this->files)) {
                $files = array();
                if (($attachments=$this->getAttachments()))
                    foreach ($attachments->all() as $a)
                        $files[] = $a->getFile();
                $this->files = $files;
            }
            return $this->files;
    
    }
    
    class FreeTextWidget extends Widget {
    
        function render($options=array()) {
    
            $config = $this->field->getConfiguration();
    
            $class = $config['classes'] ?: 'thread-body bleed';
            ?><div class="<?php echo $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->getAttachments()) && count($attachments)) { ?>
    
                <section class="freetext-files">
                <div class="title"><?php echo __('Related Resources'); ?></div>
    
                <?php foreach ($attachments->all() as $attach) { ?>
    
                    <div class="file">
    
                    <a href="<?php echo $attach->file->getDownloadUrl(); ?>"
    
                        target="_blank" download="<?php echo $attach->file->getDownloadUrl();
                        ?>" class="truncate no-pjax">
    
                        <i class="icon-file"></i>
    
                        <?php echo Format::htmlchars($attach->getFilename()); ?>
    
                    </a>
                    </div>
                <?php } ?>
            </section>
            <?php }
    
    class VisibilityConstraint {
    
        static $operators = array(
            'eq' => 1,
        );
    
    
        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) {
    
    
            if (!$this->constraint->constraints)
                return;
    
    
            $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");',
    
                    $field->getWidget()->id);
    
            }
            $expression = $this->compileQ($this->constraint, $form);
    ?>
    
              if (<?php echo $expression; ?>)
    
    Peter Rotich's avatar
    Peter Rotich committed
                target.slideDown('fast', function (){
    
                    $(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) {
    
    
            // Assume initial visibility if constraint is not provided.
            if (!$this->constraint->constraints)
                return $this->initial == self::VISIBLE;
    
    
    
            return $this->compileQPhp($this->constraint, $field);
        }
    
    
        static function splitFieldAndOp($field) {
    
            if (false !== ($last = strrpos($field, '__'))) {
                $op = substr($field, $last + 2);
                if (isset(static::$operators[$op]))
                    $field = substr($field, 0, strrpos($field, '__'));
            }
    
            return array($field, $op);
        }
    
    
        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) = self::splitFieldAndOp($c);
    
                    $field = $form->getField($f);
                    $wval = $field->getClean();
                    switch ($op) {
                    case 'eq':
                    case null:
    
                        $expr[] = ($wval == $value && $field->isVisible());
    
                    }
                }
            }
            $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) = self::splitFieldAndOp($c);
    
                    $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) = self::splitFieldAndOp($c);
    
                    $widget = $form->getField($f)->getWidget();
                    $id = $widget->id;
    
                    switch ($op) {
                    case 'eq':
    
                        $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;
        }
    }
    
    
    Peter Rotich's avatar
    Peter Rotich committed
    class AssignmentForm extends Form {
    
        static $id = 'assign';
        var $_assignee = null;
    
        var $_assignees = null;
    
    Peter Rotich's avatar
    Peter Rotich committed
    
    
        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'),
    
    Peter Rotich's avatar
    Peter Rotich committed
                        'configuration' => array(
                            'criteria' => array(
                                'available' => true,
                                ),
                           ),
    
    Peter Rotich's avatar
    Peter Rotich committed
                        )
                    ),
                'comments' => new TextareaField(array(
                        'id' => 2,
                        'label'=> '',
                        'required'=>false,
                        'default'=>'',
                        'configuration' => array(
                            'html' => true,
    
                            'size' => 'small',
    
    Peter Rotich's avatar
    Peter Rotich committed
                            'placeholder' => __('Optional reason for the assignment'),
                            ),
                        )
                    ),
                );
    
    
            if (isset($this->_assignees))
    
                $fields['assignee']->setChoices($this->_assignees);
    
    
    
    Peter Rotich's avatar
    Peter Rotich committed
            $this->setFields($fields);
    
            return $this->fields;
        }
    
    
        function getField($name) {
    
            if (($fields = $this->getFields())
                    && isset($fields[$name]))
                return $fields[$name];
        }
    
    
        function isValid($include=false) {
    
            if (!parent::isValid($include) || !($f=$this->getField('assignee')))
    
    Peter Rotich's avatar
    Peter Rotich committed
                return false;
    
            // Do additional assignment validation
            if (!($assignee = $this->getAssignee())) {
    
                $f->addError(__('Unknown assignee'));
    
    Peter Rotich's avatar
    Peter Rotich committed
            } elseif ($assignee instanceof Staff) {
                // Make sure the agent is available
                if (!$assignee->isAvailable())
    
                    $f->addError(__('Agent is unavailable for assignment'));
            } elseif ($assignee instanceof Team) {
                // Make sure the team is active and has members
                if (!$assignee->isActive())
                    $f->addError(__('Team is disabled'));
                elseif (!$assignee->getNumMembers())
                    $f->addError(__('Team does not have members'));
    
    Peter Rotich's avatar
    Peter Rotich committed
            }
    
            return !$this->errors();
        }
    
        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 setAssignees($assignees) {
            $this->_assignees = $assignees;
            $this->_fields = array();
        }
    
        function getAssignees() {
            return $this->_assignees;
        }
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        function getAssignee() {
    
    
    Peter Rotich's avatar
    Peter Rotich committed
            if (!isset($this->_assignee))
                $this->_assignee = $this->getField('assignee')->getClean();
    
    Peter Rotich's avatar
    Peter Rotich committed
    
            return $this->_assignee;
        }
    
    
        function getComments() {
            return $this->getField('comments')->getClean();
    
    Peter Rotich's avatar
    Peter Rotich committed
        }
    }
    
    class ClaimForm extends AssignmentForm {
    
        var $_fields;
    
        function setFields($fields) {
            $this->_fields = $fields;
            parent::setFields($fields);
        }
    
        function getFields() {
    
            if ($this->_fields)
                return $this->_fields;
    
    Peter Rotich's avatar
    Peter Rotich committed
            $fields = parent::getFields();
    
    Peter Rotich's avatar
    Peter Rotich committed
            // Disable && hide assignee field selection
            if (isset($fields['assignee'])) {
                $visibility = new VisibilityConstraint(
                        new Q(array()), VisibilityConstraint::HIDDEN);
    
    Peter Rotich's avatar
    Peter Rotich committed
                $fields['assignee']->set('visibility', $visibility);
            }
    
            // Change coments placeholder to reflect claim
            if (isset($fields['comments'])) {
                $fields['comments']->configure('placeholder',
                        __('Optional reason for the claim'));
            }
    
    
            $this->setFields($fields);
    
            return $this->fields;
    
    Peter Rotich's avatar
    Peter Rotich committed
    }
    
    class TransferForm extends Form {
    
        static $id = 'transfer';
        var $_dept = null;
    
        function __construct($source=null, $options=array()) {
            parent::__construct($source, $options);
    
    Peter Rotich's avatar
    Peter Rotich committed
        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 is required'),
    
    Peter Rotich's avatar
    Peter Rotich committed
                        )
                    ),
                'comments' => new TextareaField(array(
                        'id' => 2,
                        'label'=> '',
                        'required'=>false,
                        'default'=>'',
                        'configuration' => array(
                            'html' => true,
    
    Peter Rotich's avatar
    Peter Rotich committed
                            'size' => 'small',
    
    Peter Rotich's avatar
    Peter Rotich committed
                            'placeholder' => __('Optional reason for the transfer'),
                            ),
                        )
                    ),
                );
    
            $this->setFields($fields);
    
            return $this->fields;
    
        function isValid($include=false) {
    
            if (!parent::isValid($include))
    
    Peter Rotich's avatar
    Peter Rotich committed
                return false;
    
            // Do additional validations
            if (!($dept = $this->getDept()))
                $this->getField('dept')->addError(
                        __('Unknown department'));
    
            return !$this->errors();
    
    Peter Rotich's avatar
    Peter Rotich committed
        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;
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        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 {}