Example #1
0
 public static function Run($strFormId, $strAlternateHtmlFile = null)
 {
     // Ensure strFormId is a class
     $objClass = new $strFormId();
     // Ensure strFormId is a subclass of QForm
     if (!$objClass instanceof QForm) {
         throw new QCallerException('Object is not a subclass of QForm (note, it can NOT be a subclass of QFormBase): ' . $strFormId);
     }
     // See if we can get a Form Class out of PostData
     $objClass = null;
     if (array_key_exists('Qform__FormId', $_POST) && $_POST['Qform__FormId'] == $strFormId && array_key_exists('Qform__FormState', $_POST)) {
         $strPostDataState = $_POST['Qform__FormState'];
         if ($strPostDataState) {
             // We might have a valid form state -- let's see by unserializing this object
             $objClass = QForm::Unserialize($strPostDataState);
         }
     }
     if ($objClass) {
         global ${$strFormId};
         ${$strFormId} = $objClass;
         $objClass->strCallType = $_POST['Qform__FormCallType'];
         $objClass->intFormStatus = QFormBase::FormStatusUnrendered;
         if ($objClass->strCallType == QCallType::Ajax) {
             QApplication::$RequestMode = QRequestMode::Ajax;
         }
         // Globalize and Set Variable
         global ${$strFormId};
         ${$strFormId} = $objClass;
         // Iterate through all the control modifications
         $strModificationArray = explode("\n", trim($_POST['Qform__FormUpdates']));
         if ($strModificationArray) {
             foreach ($strModificationArray as $strModification) {
                 $strModification = trim($strModification);
                 if ($strModification) {
                     $intPosition = strpos($strModification, ' ');
                     $strControlId = substr($strModification, 0, $intPosition);
                     $strModification = substr($strModification, $intPosition + 1);
                     $intPosition = strpos($strModification, ' ');
                     if ($intPosition !== false) {
                         $strProperty = substr($strModification, 0, $intPosition);
                         $strValue = substr($strModification, $intPosition + 1);
                     } else {
                         $strProperty = $strModification;
                         $strValue = null;
                     }
                     switch ($strProperty) {
                         case 'Parent':
                             if ($strValue) {
                                 if ($strValue == $objClass->FormId) {
                                     $objClass->objControlArray[$strControlId]->SetParentControl(null);
                                 } else {
                                     $objClass->objControlArray[$strControlId]->SetParentControl($objClass->objControlArray[$strValue]);
                                 }
                             } else {
                                 // Remove all parents
                                 $objClass->objControlArray[$strControlId]->SetParentControl(null);
                                 $objClass->objControlArray[$strControlId]->SetForm(null);
                                 $objClass->objControlArray[$strControlId] = null;
                                 unset($objClass->objControlArray[$strControlId]);
                             }
                             break;
                         default:
                             if (array_key_exists($strControlId, $objClass->objControlArray)) {
                                 $objClass->objControlArray[$strControlId]->__set($strProperty, $strValue);
                             }
                             break;
                     }
                 }
             }
         }
         // Clear the RenderedCheckableControlArray
         $objClass->blnRenderedCheckableControlArray = array();
         $strCheckableControlList = trim($_POST['Qform__FormCheckableControls']);
         $strCheckableControlArray = explode(' ', $strCheckableControlList);
         foreach ($strCheckableControlArray as $strCheckableControl) {
             $objClass->blnRenderedCheckableControlArray[trim($strCheckableControl)] = true;
         }
         // Iterate through all the controls
         foreach ($objClass->objControlArray as $objControl) {
             // If they were rendered last time and are visible (and if ServerAction, enabled), then Parse its post data
             if ($objControl->Visible && ($objClass->strCallType == QCallType::Ajax || $objControl->Enabled) && $objControl->RenderMethod) {
                 // Call each control's ParsePostData()
                 $objControl->ParsePostData();
             }
             // Reset the modified/rendered flags and the validation
             // in ALL controls
             $objControl->ResetFlags();
             $objControl->ValidationReset();
         }
         // Trigger Run Event (if applicable)
         $objClass->Form_Run();
         // Trigger Load Event (if applicable)
         $objClass->Form_Load();
         // Trigger a triggered control's Server- or Ajax- action (e.g. PHP method) here (if applicable)
         $objClass->TriggerActions();
     } else {
         // We have no form state -- Create Brand New One
         $objClass = new $strFormId();
         // Setup HTML Include File Path, based on passed-in strAlternateHtmlFile (if any)
         try {
             $objClass->HtmlIncludeFilePath = $strAlternateHtmlFile;
         } catch (QCallerException $objExc) {
             $objExc->IncrementOffset();
             throw $objExc;
         }
         global ${$strFormId};
         ${$strFormId} = $objClass;
         // By default, this form is being created NOT via a PostBack
         // So there is no CallType
         $objClass->strCallType = QCallType::None;
         $objClass->strFormId = $strFormId;
         $objClass->intFormStatus = QFormBase::FormStatusUnrendered;
         $objClass->objControlArray = array();
         $objClass->objGroupingArray = array();
         // Globalize and Set Variable
         global ${$strFormId};
         ${$strFormId} = $objClass;
         // Trigger Run Event (if applicable)
         $objClass->Form_Run();
         // Trigger Create Event (if applicable)
         $objClass->Form_Create();
     }
     // Trigger PreRender Event (if applicable)
     $objClass->Form_PreRender();
     // Render the Page
     switch ($objClass->strCallType) {
         case QCallType::Ajax:
             // Must use AJAX-based renderer
             $objClass->RenderAjax();
             break;
         case QCallType::Server:
         case QCallType::None:
         case '':
             // Server/Postback or New Page
             // Make sure all controls are marked as not being on the page yet
             foreach ($objClass->objControlArray as $objControl) {
                 $objControl->ResetOnPageStatus();
             }
             // Use Standard Rendering
             $objClass->Render();
             break;
         default:
             throw new Exception('Unknown Form CallType: ' . $objClass->strCallType);
     }
     // Ensure that RenderEnd() was called during the Render process
     switch ($objClass->intFormStatus) {
         case QFormBase::FormStatusUnrendered:
             throw new QCallerException('$this->RenderBegin() is never called in the HTML Include file');
         case QFormBase::FormStatusRenderBegun:
             throw new QCallerException('$this->RenderEnd() is never called in the HTML Include file');
         case QFormBase::FormStatusRenderEnded:
             break;
         default:
             throw new QCallerException('FormStatus is in an unknown status');
     }
     // Tigger Exit Event (if applicable)
     $objClass->Form_Exit();
 }
 /**
  * This method initializes the actual layout of the form
  * It runs in all cases including initial form (the time when Form_Create is run) as well as on
  * trigger actions (QServerAction, QAjaxAction, QServerControlAction and QAjaxControlAction)
  *
  * It is responsible for implementing the logic and sequence in which page wide checks are done
  * such as running Form_Validate and Control validations for every control of the page and their
  * child controls. Checking for an existing FormState and loading them before trigerring any action
  * is also a responsibility of this method.
  * @param string $strFormClass The class of the form to create when creating a new form.
  * @param string|null $strAlternateHtmlFile location of the alternate HTML template file.
  * @param string|null $strFormId The html id to use for the form. If null, $strFormClass will be used.
  *
  * @throws QCallerException
  * @throws QInvalidFormStateException
  * @throws Exception
  */
 public static function Run($strFormClass, $strAlternateHtmlFile = null, $strFormId = null)
 {
     // See if we can get a Form Class out of PostData
     $objClass = null;
     if ($strFormId === null) {
         $strFormId = $strFormClass;
     }
     if (array_key_exists('Qform__FormId', $_POST) && $_POST['Qform__FormId'] == $strFormId && array_key_exists('Qform__FormState', $_POST)) {
         $strPostDataState = $_POST['Qform__FormState'];
         if ($strPostDataState) {
             // We might have a valid form state -- let's see by unserializing this object
             $objClass = QForm::Unserialize($strPostDataState);
         }
         // If there is no QForm Class, then we have an Invalid Form State
         if (!$objClass) {
             self::InvalidFormState();
         }
     }
     if ($objClass) {
         // Globalize
         global $_FORM;
         $_FORM = $objClass;
         $objClass->strCallType = $_POST['Qform__FormCallType'];
         $objClass->intFormStatus = QFormBase::FormStatusUnrendered;
         if ($objClass->strCallType == QCallType::Ajax) {
             QApplication::$RequestMode = QRequestMode::Ajax;
         }
         // Cleanup ajax post data if the encoding does not match, since ajax data is always utf-8
         if ($objClass->strCallType == QCallType::Ajax && QApplication::$EncodingType != 'UTF-8') {
             foreach ($_POST as $key => $val) {
                 if (substr($key, 0, 6) != 'Qform_') {
                     $_POST[$key] = iconv('UTF-8', QApplication::$EncodingType, $val);
                 }
             }
         }
         if (!empty($_POST['Qform__FormParameter'])) {
             $_POST['Qform__FormParameter'] = self::UnpackPostVar($_POST['Qform__FormParameter']);
         }
         // Decode custom post variables from server calls
         if (!empty($_POST['Qform__AdditionalPostVars'])) {
             $val = self::UnpackPostVar($_POST['Qform__AdditionalPostVars']);
             $_POST = array_merge($_POST, $val);
         }
         // Iterate through all the control modifications
         if (!empty($_POST['Qform__FormUpdates'])) {
             $controlUpdates = $_POST['Qform__FormUpdates'];
             if (is_string($controlUpdates)) {
                 // Server post is encoded, ajax not encoded
                 $controlUpdates = self::UnpackPostVar($controlUpdates);
             }
             if (!empty($controlUpdates)) {
                 foreach ($controlUpdates as $strControlId => $params) {
                     foreach ($params as $strProperty => $strValue) {
                         switch ($strProperty) {
                             case 'Parent':
                                 if ($strValue) {
                                     if ($strValue == $objClass->FormId) {
                                         $objClass->objControlArray[$strControlId]->SetParentControl(null);
                                     } else {
                                         $objClass->objControlArray[$strControlId]->SetParentControl($objClass->objControlArray[$strValue]);
                                     }
                                 } else {
                                     // Remove all parents
                                     $objClass->objControlArray[$strControlId]->SetParentControl(null);
                                     $objClass->objControlArray[$strControlId]->SetForm(null);
                                     $objClass->objControlArray[$strControlId] = null;
                                     unset($objClass->objControlArray[$strControlId]);
                                 }
                                 break;
                             default:
                                 if (array_key_exists($strControlId, $objClass->objControlArray)) {
                                     $objClass->objControlArray[$strControlId]->__set($strProperty, $strValue);
                                 }
                                 break;
                         }
                     }
                 }
             }
         }
         // Set the RenderedCheckableControlArray
         if (!empty($_POST['Qform__FormCheckableControls'])) {
             $vals = $_POST['Qform__FormCheckableControls'];
             if (is_string($vals)) {
                 // Server post is encoded, ajax not encoded
                 $vals = self::UnpackPostVar($vals);
             }
             $objClass->checkableControlValues = $vals;
         } else {
             $objClass->checkableControlValues = [];
         }
         // This is original code. In an effort to minimize changes,
         // we aren't going to touch the server calls for now
         if ($objClass->strCallType != QCallType::Ajax) {
             foreach ($objClass->objControlArray as $objControl) {
                 // If they were rendered last time and are visible
                 // (and if ServerAction, enabled), then Parse its post data
                 if ($objControl->Visible && $objControl->Enabled && $objControl->RenderMethod) {
                     // Call each control's ParsePostData()
                     $objControl->ParsePostData();
                 }
                 // Reset the modified/rendered flags and the validation
                 // in ALL controls
                 $objControl->ResetFlags();
             }
         } else {
             // Ajax post. Only send data to controls specified in the post to save time.
             $previouslyFoundArray = array();
             $controls = $_POST;
             $controls = array_merge($controls, $objClass->checkableControlValues);
             foreach ($controls as $key => $val) {
                 if ($key == 'Qform__FormControl') {
                     $strControlId = $val;
                 } elseif (substr($key, 0, 6) == 'Qform_') {
                     continue;
                     // ignore this form data
                 } else {
                     $strControlId = $key;
                 }
                 if (($intOffset = strpos($strControlId, '_')) !== false) {
                     // the first break is the control id
                     $strControlId = substr($strControlId, 0, $intOffset);
                 }
                 if (($objControl = $objClass->GetControl($strControlId)) && !isset($previouslyFoundArray[$strControlId])) {
                     if ($objControl->Visible && $objControl->RenderMethod) {
                         // Call each control's ParsePostData()
                         $objControl->ParsePostData();
                     }
                     $previouslyFoundArray[$strControlId] = true;
                 }
             }
         }
         // Only if our action is validating, we are going to reset the validation state of all the controls
         if (isset($_POST['Qform__FormControl']) && isset($objClass->objControlArray[$_POST['Qform__FormControl']])) {
             $objControl = $objClass->objControlArray[$_POST['Qform__FormControl']];
             if ($objControl->CausesValidation) {
                 $objClass->ResetValidationStates();
             }
         }
         // Trigger Run Event (if applicable)
         $objClass->Form_Run();
         // Trigger Load Event (if applicable)
         $objClass->Form_Load();
         // Trigger a triggered control's Server- or Ajax- action (e.g. PHP method) here (if applicable)
         $objClass->TriggerActions();
     } else {
         // We have no form state -- Create Brand New One
         $objClass = new $strFormClass();
         // Globalize
         global $_FORM;
         $_FORM = $objClass;
         // Setup HTML Include File Path, based on passed-in strAlternateHtmlFile (if any)
         try {
             $objClass->HtmlIncludeFilePath = $strAlternateHtmlFile;
         } catch (QCallerException $objExc) {
             $objExc->IncrementOffset();
             throw $objExc;
         }
         // By default, this form is being created NOT via a PostBack
         // So there is no CallType
         $objClass->strCallType = QCallType::None;
         $objClass->strFormId = $strFormId;
         $objClass->intFormStatus = QFormBase::FormStatusUnrendered;
         $objClass->objControlArray = array();
         $objClass->objGroupingArray = array();
         // Trigger Run Event (if applicable)
         $objClass->Form_Run();
         // Trigger Create Event (if applicable)
         $objClass->Form_Create();
         $objClass->Form_Initialize();
         if (defined('__DESIGN_MODE__') && __DESIGN_MODE__ == 1) {
             // Attach custom event to dialog to handle right click menu items sent by form
             $dlg = new QModelConnectorEditDlg($objClass, 'qconnectoreditdlg');
             $dlg->AddAction(new QOnEvent('qdesignerclick'), new QAjaxAction('ctlDesigner_Click', null, null, 'ui'));
         }
     }
     // Trigger PreRender Event (if applicable)
     $objClass->Form_PreRender();
     // Render the Page
     switch ($objClass->strCallType) {
         case QCallType::Ajax:
             // Must use AJAX-based renderer
             $objClass->RenderAjax();
             break;
         case QCallType::Server:
         case QCallType::None:
         case '':
             // Server/Postback or New Page
             // Make sure all controls are marked as not being on the page yet
             foreach ($objClass->objControlArray as $objControl) {
                 $objControl->ResetOnPageStatus();
             }
             // Use Standard Rendering
             $objClass->Render();
             // Ensure that RenderEnd() was called during the Render process
             switch ($objClass->intFormStatus) {
                 case QFormBase::FormStatusUnrendered:
                     throw new QCallerException('$this->RenderBegin() is never called in the HTML Include file');
                 case QFormBase::FormStatusRenderBegun:
                     throw new QCallerException('$this->RenderEnd() is never called in the HTML Include file');
                 case QFormBase::FormStatusRenderEnded:
                     break;
                 default:
                     throw new QCallerException('FormStatus is in an unknown status');
             }
             break;
         default:
             throw new Exception('Unknown Form CallType: ' . $objClass->strCallType);
     }
     // Once all the controls have been set up, and initialized, remember them.
     $objClass->SaveControlState();
     // Tigger Exit Event (if applicable)
     $objClass->Form_Exit();
 }