/** * Pre-filter actions any submission, or prepares the form. * * @param T_Response $response encapsulated response to filter */ protected function doPreFilter(T_Response $response) { $t_field = $this->form->getAlias() . '_timeout'; $l_field = $this->form->getAlias() . '_thread_lock'; $s_field = $this->form->getAlias() . '_salt'; // prepare form: // (a) add thread lock if required // (b) add timeout $timeout = new T_Form_Hidden($t_field, $this->timeout + time()); $this->form->addChild($timeout); if ($this->lock_to) { $lock_to = new T_Form_Hidden($l_field, $this->lock_to); $this->form->addChild($lock_to); } // process form if is POST: if ($this->env->isMethod('POST')) { try { // create salt field and validate to get salt $salt = new T_Form_Hidden($s_field, null); if ($salt->isSubmitted($this->env->input('POST'))) { $salt->validate($this->env->input('POST')); } // salt form and validate if ($salt->isPresent() && $salt->isValid()) { $salt = $salt->getValue(); $this->form->setFieldnameSalt($salt, $this->hash); if ($this->form->isSubmitted($this->env->input('POST'))) { $this->form->validate($this->env->input('POST')); } } // check timeout and thread lock if ($this->form->isPresent() && $this->form->isValid()) { // check timeout $timeout = $this->form->search($t_field)->getValue(); if ($timeout < time()) { $msg = 'This form has expired. Please submit the form ' . 'again to complete your request.'; throw new T_Exception_Filter($msg); } // check lock thread if ($this->lock_to) { $lock_to = $this->form->search($l_field)->getValue(); if (strcmp($lock_to, $this->lock_to) !== 0) { $msg = 'A technical error occurred at our end, sorry. ' . 'Please submit the form again.'; throw new T_Exception_Filter($msg); } } } } catch (T_Exception_Filter $e) { $this->form->setError(new T_Form_Error($e->getMessage())); } } // ready form for redisplay (remember an error may be added in the POST // method so make even a valid form ready for display). // (a) Set form forward as same page // (b) Salt form and add salt hidden input // (c) Reset timeout from now $this->form->setForward($this->env->getRequestUrl()->setParameters($this->env->input('GET')->uncage())); $salt = uniqid(rand(), true); $this->form->setFieldnameSalt($salt, $this->hash); $this->form->addChild(new T_Form_Hidden($s_field, $salt)); // note that the salt hidden input is added *after* the form is // salted as this input needs to be plain. $this->form->search($t_field)->setValue($this->timeout + time()); }
$form->addChild($fieldset); $repeated = new T_Form_Repeated('jobs', 'Add Another Job', 1, 6); $repeated->addChild(new T_Form_Text('title', 'Title')); $repeated->addChild(new T_Form_Text('company', 'Company')); $start = new T_Form_Text('start', 'Start Date'); $start->setHelp('Enter date in format dd/mm/yyyy'); $start->setOptional()->attachFilter(new T_Validate_UnixDate('d|m|y')); $repeated->addChild($start); $fieldset->addChild($repeated); $skills = new T_Form_TextArea('skills', 'Additional Info'); $skills->setOptional()->setHelp('Describe any additional career achievements, etc.'); $fieldset->addChild($skills); $form->setForward($env->getRequestUrl()); // VALIDATE FORM if ($env->isMethod('POST')) { $form->validate($env->input('POST')); } // ACTION FORM if ($form->isPresent() && $form->isValid()) { $f = new T_Filter_Xhtml(); // action (e.g. email, etc.) echo '<h2>CV for <a href="mailto:', $form->search('email')->getValue($f), '">', $form->search('name')->getValue($f), '</a></h2>'; foreach ($form->search('jobs') as $job) { $date = $job->search('start'); if ($date->isPresent()) { $date = ' (from ' . date('d-m-Y', $date->getValue()) . ')'; } else { $date = null; } echo '<p>', $job->search('title')->getValue($f), ', ', $job->search('company')->getValue($f), $date, '</p>'; }
/** * Validates the form. * * @param T_Cage_Array $source source data * @return T_Form_Group fluent interface */ function validate(T_Cage_Array $source) { // validate normal portion of form parent::validate($source); // validate basic form if (count($this->steps) == 0) { return $this; } // populate and validate previous history $history = $this->search('history'); if ($history && $history->isPresent() && $history->isValid()) { $cage = new T_Cage_Array($history->getValue()); } else { $cage = new T_Cage_Array(array()); } foreach ($this->steps as $c) { $c->validate($cage); // always validate... as this is required // to make sure optional steps are accounted // for OK in the validation. } // work out where we are now, and validate this step submission $seek = $this->search('seek'); if ($seek && ($seek = $seek->getValue())) { reset($this->steps); do { if (strcmp(key($this->steps), $seek) === 0) { break; } } while (next($this->steps)); if (!current($this->steps)) { reset($this->steps); } // not found } $cur = current($this->steps); $cur->validate($source); // if we're going backwards, the form submission has to be valid, but // the current step doesn't (as we'll come back to it!) if (parent::isValid() && $this->isAction('prev')) { if (false === prev($this->steps)) { reset($this->steps); } // ^ reset if no prev } if (parent::isValid() && $cur->isValid() && $this->isAction('forward')) { if (false === next($this->steps)) { reset($this->steps); do { $cur = current($this->steps); if ($cur && !$cur->isValid()) { // problem at this step, break here and display. We // can break; } } while (next($this->steps)); if (!current($this->steps)) { reset($this->steps); $this->is_complete = true; } // ^ reset if got to end unless there is an element that // is not present/or is invalid. } else { // we've moved forward using a standard forward step to a new // area. We need to clear errors on this step from previous // cross-form navigation, and the user is about to re-complete // it. current($this->steps)->clearError(); } } $this->init(); // ^ prepare form in possible new position, with possible new form // data (whether it is present/not valid/etc.) return $this; }