<?php

    
require_once 'HTML/QuickForm.php';
    
    class 
radForm extends  HTML_QuickForm 
    
{
        
// private var to maintain the viewstate.
        
var $_viewstate;
        
        
/**
         *
         * Class constructor 
         *
         * Sets up the main form elements, calls the action handler, and renders the extra 
         * elements based upon the viewstate.
         */
        
function radForm()
        {
            
$this->HTML_QuickForm('RadUser');
             
            
// recover the viewstate from the hidden form element           
            
$this->addElement('hidden''__VIEWSTATE');
            if (
$this->getSubmitValue('__VIEWSTATE'))
            {
                
$this->_viewstate unserialize(base64_decode($this->getSubmitValue('__VIEWSTATE')));
            }
            else 
            {
                
// defaults it to being an array if not already set
                
$this->_viewstate = array();
            }
            
            
// this is added for the javascript to change to allow the action handler (serverside)
            // to read it
            
$action =& $this->createElement('hidden''action');
            
$this->addElement($action);
            
            
// adds the default fields
            
$this->addElement('header'null'RADIUS Admin');
            
$this->addElement('text''onsite_id''OnSite Ref');
            
$this->addElement('text''cbuk''CBUK');
            
$this->addElement('text''phonenum''Phone Number');
            
$this->addElement('text''username''Username');
            
$this->addElement('checkbox''active''Active');
            
            
// add the select box to allow adding profiles
            
$this->addElement('header'null'Add Profile');
            
$options array_merge(array(=> ' -- select a profile -- '), $this->_getProfiles());
            
// this adds a JS onchange function to call the serverside actionhandler.
            
$this->addElement('select''addProfile''Add Profile'$options'onchange="submitWithAction(\'profileAdd\',this)"');
            
            
// call the action handler
            
$this->_actionHandler();
            
            
// this function renders the extra form elements that have been added
            
$this->processViewstate();
            
$this->_updateViewstate();
            
$this->addElement('submit''post''Submit');
        }
        
        
/**
         *
         * Goes though each profile and adds the profile section to the form
         */
        
function processViewstate()
        {
            if (isset(
$this->_viewstate['profiles']))
            {
                foreach (
$this->_viewstate['profiles'] as $profileName => $profileFields)
                {
                    
$this->addProfileGroup($profileName$profileName);
                }
            }
        }
        
        
/**
         *
         * Adds the group select and check/reply options to the form.
         */
        
function addProfileGroup($prefix$name)
        {
            static 
$index;
            isset(
$index)?$index++:$index=0
              
            
// profile title and remove link
            
$removeLink '<a href="#" onclick="submitWithAction(\'profileDel|' $prefix '\'); return false;" >remove</a>';
            
$this->addElement('header'null'Profile ' $name ' - '  .  $removeLink);
            
            
// group selector
            
$options array_merge( array(=> ' -- select a group -- '), $this->_getGroups());
            
$this->addElement('select''groupAdd[' $prefix ']''Current Group'$options'onchange="submitWithAction(\'groupSet|' $prefix '\', this)"');
            
            
// checks
            
$options array_merge( array(=> ' -- select a check -- '), $this->_getChecks());
            
$this->addElement('select''checkAdd[' $prefix ']''Checks'$options'onchange="submitWithAction(\'checkAdd|' $prefix '\', this)"');
            if (isset(
$this->_viewstate['profiles'][$prefix]['check']['elements']))
            {
                foreach (
$this->_viewstate['profiles'][$prefix]['check']['elements'] as $index => $element)
                {
                    
$group = array();
                    
$group[] = $this->createElement('select''op'null$this->_getOperators());
                    
$group[] = $this->createElement('text''value'$element);
                    
$group[] = $this->createElement('submit'null'remove'    'onclick="submitWithAction(\'checkDelete|' $prefix '|' $index '\')"');
                    
$this->addGroup($group$prefix '_checks' $index$element);
                }
            }
            
            
// replies
            
$options array_merge( array(=> ' -- select a reply -- '), $this->_getReplies());
            
$this->addElement('select''replyAdd[' $prefix ']''Replies'$options'onchange="submitWithAction(\'replyAdd|' $prefix '\', this)"');
            if (isset(
$this->_viewstate['profiles'][$prefix]['reply']['elements']))
            {
                foreach (
$this->_viewstate['profiles'][$prefix]['reply']['elements'] as $index => $element)
                {
                    
$group = array();
                    
$group[] = $this->createElement('select''op'null$this->_getOperators());
                    
$group[] = $this->createElement('text''value'$element);
                    
$group[] = $this->createElement('submit'null'remove''onclick="submitWithAction(\'replyDelete|' $prefix '|' $index '\')"');
                    
$this->addGroup($group$prefix '_replys' $index$element);
                }
            }
            

        }
        
        
/**
         *
         *  Function to update the viewstate
         */
        
function _updateViewstate()
        {
            
$viewstate =& $this->getElement('__VIEWSTATE');
            if (!
is_array($this->_viewstate))
            {
                
$this->_viewstate = array();
            }
            
$viewstate->setValue(base64_encode(serialize($this->_viewstate)));            
        }
        
        
/**
         *
         * This function handles the action that would have been set client side in the hidden element
         * All it does is update the viewstate, as the rendering of the form is done elsewhere
         */
        
function _actionHandler()
        {
            
$actionElement =& $this->getElement('action');
            if (!
$actionElement->getValue())
            {
                return 
true;    
            }
            
$action $actionElement->getValue();
            
$actionElement->setValue('');
            
            
// actions look like 'profileAdd|something|somethingelse'
            
$actions explode('|',$action);
            switch (
$actions[0])
            {
                case 
'profileAdd':
                    
// resets the addProfile box to the top element.
                    
$selectBox =& $this->getElement('addProfile');
                    
$selectBox->setValue(0);
                    
                    if (!isset(
$this->_viewstate['profiles']))
                    {
                        
$this->_viewstate['profiles'] = array();
                    }
                    if (!isset(
$this->_viewstate['profiles'][$actions[1]]))
                    {
                        
$this->_viewstate['profiles'][$actions[1]] = array('checks' => array(), 'replys' => array());
                    }
                    break;
                case 
'profileDel':
                    
// resets the addProfile box to the top element.
                    
$selectBox =& $this->getElement('addProfile');
                    
$selectBox->setValue(0);
                    unset(
$this->_viewstate['profiles'][$actions[1]]);      
                    break;
                case 
'checkAdd':
                    if (!isset(
$this->_viewstate['profiles'][$actions[1]]['check']['elements']))
                    {
                        
$this->_viewstate['profiles'][$actions[1]]['check']['elements'] = array();
                    }
                    
array_push($this->_viewstate['profiles'][$actions[1]]['check']['elements'], $actions[2]);
                    break;
                case 
'checkDelete':
                    unset(
$this->_viewstate['profiles'][$actions[1]]['check']['elements'][$actions[2]]);
                    break;
                case 
'replyAdd':
                    if (!isset(
$this->_viewstate['profiles'][$actions[1]]['reply']['elements']))
                    {
                        
$this->_viewstate['profiles'][$actions[1]]['reply']['elements'] = array();
                    }
                    
array_push($this->_viewstate['profiles'][$actions[1]]['reply']['elements'], $actions[2]);
                    break;
                case 
'replyDelete':
                    unset(
$this->_viewstate['profiles'][$actions[1]]['reply']['elements'][$actions[2]]);
                    break;
            }
            return 
true;
        }
        
        
/**
         *
         * Returns a list of the profiles
         */
        
function _getProfiles()
        {
            
// will be read from a database soon
            
return array(=> 'LNS'=> 'LTS');
        }
        
        
/**
         *
         * Returns a list of valid operators
         */
        
function _getOperators()
        {
            return array(
'==' => '==',
                           
'!=' => '!=',
                           
'='  => '=',
                           
':=' => ':=',
                           
'<=' => '<=',
                           
'>=' => '>=',
                           
'>'  => '>',
                           
'<'  => '<',
                           
'=~' => '=~',
                           
'+=' => '+=',
                           
'!~' => '!~',
                           
'=*' => '=*',
                           
'!*' => '!*'
                          
);
        }
        
        
/**
         *
         * Returns an array of groups from the database.
         */
        
function _getGroups()
        {
            return array (
=> 'group a'=> 'group b');
        }
        
        
/**
         *
         * Returns an array of checks
         */
        
function _getChecks()
        {
            return array (
=> 'check 1'=> 'check 2');
        }
        
        
/**
         *
         * Returns an array of replys
         */
        
function _getReplies()
        {
            return array (
=> 'reply 1'=> 'reply 2');
        }
    }
    
?>
<script>
    function submitWithAction(action, selectBox)
    {
        var actionString;
        
        if (selectBox)
        {
            if (selectBox.selectedIndex == 0)
            {
                return false;
            }
            actionString = action + '|' + selectBox.options[selectBox.selectedIndex].text;
        }
        else
        {
            actionString = action;
        }
        
        document.RadUser.action.value = actionString;
        document.RadUser.submit();   
    }
</script>

<h1>RADIUS User Admin (Expert)</h1>
<?php
    $form 
= new radForm();
    
    
$form->display();