protected function compile() { parent::compile(); // Check for javascript framework if (TL_MODE == 'FE') { /** @type PageModel $objPage */ global $objPage; $this->Template->jquery = false; $this->Template->mootools = false; if ($objPage->getRelated('layout')->addJQuery) { $this->Template->jquery = true; } elseif ($objPage->getRelated('layout')->addMooTools) { $this->Template->mootools = true; } } }
/** * Generate the form * @return string */ protected function compile() { $hasUpload = false; $doNotSubmit = false; $arrSubmitted = array(); $blnAddDateJS = true; $this->loadDataContainer('tl_form_field'); $formId = strlen($this->formID) ? 'auto_' . $this->formID : 'auto_form_' . $this->id; $arrUnset = array('FORM_NEXT', 'FORM_BACK'); foreach ($arrUnset as $strKey) { unset($_SESSION['FORM_DATA'][$strKey]); } // form used to edit existing formdata record if ($this->objEditRecord instanceof Database_Result) { $arrEditRecord = $this->objEditRecord->row(); $this->blnEditform = true; $this->import('FormData'); } // Check multipage $objPaginators = $this->Database->prepare("SELECT id,pid,`sorting`,`type`,`name`,`label`,`value`,`imageSubmit`,`singleSRC`,`sLabel`,`efgAddBackButton`,`efgBackStoreSessionValues`,`efgBackSlabel`,`efgBackImageSubmit`,`efgBackSingleSRC` FROM tl_form_field WHERE pid=? AND `type`=? ORDER BY `sorting`")->execute($this->id, 'efgFormPaginator'); if ($objPaginators->numRows) { $this->blnMultipage = true; $this->intTotalPages = (int) $objPaginators->numRows; while ($objPaginators->next()) { $this->arrPaginators[] = $objPaginators->row(); } } // use core class Form if this is not a multi page form and not frontend edit form if (!$this->blnMultipage && !$this->blnEditform || $this->method == 'GET' || TL_MODE == 'BE') { $this->strTemplate = 'form'; return parent::compile(); } global $objPage; if ($objPage->outputFormat == 'html5') { $blnIsHtml5 = true; } $this->blnAllowSkipRequired = false; // allow form submission, if ALL required fields are empty $this->arrWidgetsFailedValidation = array(); // validation result of required widgets $doNotValidate = false; $strMode = ''; $intActivePage = 1; $this->Template = new FrontendTemplate($this->strTemplate); $this->loadLanguageFile('tl_form'); // render a previous completed page if (strlen($_SESSION['EFP'][$formId]['render_page'])) { $intActivePage = (int) $_SESSION['EFP'][$formId]['render_page']; $this->intActivePage = (int) $_SESSION['EFP'][$formId]['render_page']; $strMode = 'reload'; unset($_SESSION['EFP'][$formId]['render_page']); } elseif (!strlen($_POST['FORM_SUBMIT'])) { unset($_SESSION['EFP'][$formId]['render_page']); unset($_SESSION['EFP'][$formId]['completed']); } if ($this->Input->post('FORM_SUBMIT') == $formId && (strlen($_POST['FORM_PAGE']) || is_array($_POST['FORM_STEP']))) { $intActivePage = (int) $_POST['FORM_PAGE']; $intGoto = 0; if (strlen($_POST['FORM_BACK']) || strlen($_POST['FORM_BACK_x'])) { $intActivePage = (int) $_POST['FORM_PAGE']; $doNotValidate = true; $strMode = 'back'; } elseif (is_array($_POST['FORM_STEP']) || is_array($_POST['FORM_STEP_x'])) { $intGoto = is_array($_POST['FORM_STEP']) ? key($_POST['FORM_STEP']) : key($_POST['FORM_STEP_x']); if ($intGoto < $intActivePage) { $_SESSION['EFP'][$formId]['render_page'] = $intGoto < 1 ? 1 : $intGoto; $this->reload(); } elseif ($intGoto > $intActivePage && $_SESSION['EFP'][$formId]['completed']['page_' . $intGoto]) { $_SESSION['EFP'][$formId]['render_page'] = $intGoto; $this->reload(); } } if ($intActivePage < 1) { $intActivePage = 1; } if ($intActivePage > $this->intTotalPages) { $intActivePage = $this->intTotalPages; } $this->intActivePage = $intActivePage; } $this->Template->fields = ''; $this->Template->hidden = ''; $this->Template->formSubmit = $formId; $this->Template->tableless = $this->tableless ? true : false; $this->Template->method = $this->method == 'GET' ? 'get' : 'post'; if ($this->blnMultipage || $this->blnEditform) { $objPageWidget = new FormHidden(array('name' => 'FORM_PAGE', 'value' => $this->intActivePage)); $this->Template->hidden .= $objPageWidget->parse(); } $this->initializeSession($formId); $this->getMaxFileSize(); // Get all form fields $objFields = $this->Database->prepare("SELECT * FROM tl_form_field WHERE pid=? AND invisible!=1 ORDER BY sorting")->execute($this->id); $row = 0; $max_row = $objFields->numRows; $arrLabels = array(); while ($objFields->next()) { if ($objFields->name != '') { $arrLabels[$objWidget->name] = $objFields->label; } if ($this->intTotalPages > 1 && ($this->blnMultipage || $this->blnEditform)) { // skip fields outside range of active page $intFieldSorting = (int) $objFields->sorting; if ($this->intActivePage <= 1 && $intFieldSorting > (int) $this->arrPaginators[$this->intActivePage - 1]['sorting']) { continue; } elseif ($this->intActivePage > 1 && $this->intActivePage < $this->intTotalPages && ($intFieldSorting <= (int) $this->arrPaginators[$this->intActivePage - 2]['sorting'] || $intFieldSorting > (int) $this->arrPaginators[$this->intActivePage - 1]['sorting'])) { continue; } elseif ($this->intActivePage == $this->intTotalPages && $intFieldSorting <= (int) $this->arrPaginators[$this->intActivePage - 2]['sorting']) { continue; } } // unset session values if no FORM_SUBMIT or form page has not been completed // (to avoid wrong validation against session values and to avoid usage of values of other forms) // this behaviour can be deactivated by setting: $GLOBALS['EFP'][$formId]['doNotCleanStoredSessionData'] = true; if ($strMode != 'reload' && strlen($objFields->name)) { if (!strlen($_POST['FORM_SUBMIT']) || !$_SESSION['EFP'][$formId]['completed']['page_' . $this->intActivePage]) { if (!$GLOBALS['EFP'][$formId]['doNotCleanStoredSessionData']) { unset($_SESSION['FORM_DATA'][$objFields->name]); } } } $strClass = $GLOBALS['TL_FFL'][$objFields->type]; // Continue if the class is not defined if (!$this->classFileExists($strClass)) { continue; } $arrData = $objFields->row(); $arrData['decodeEntities'] = true; $arrData['allowHtml'] = $this->allowTags; $arrData['rowClass'] = 'row_' . $row . ($row == 0 ? ' row_first' : ($row == $max_row - 1 ? ' row_last' : '')) . ($row % 2 == 0 ? ' even' : ' odd'); $arrData['tableless'] = $this->tableless; if ($this->blnMultipage || $this->blnEditform) { $arrData['formMultipage'] = $this->blnMultipage; $arrData['formActivePage'] = $this->intActivePage; $arrData['formTotalPages'] = $this->intTotalPages; } // Increase the row count if it is a password field if ($objFields->type == 'password') { ++$row; ++$max_row; $arrData['rowClassConfirm'] = 'row_' . $row . ($row == $max_row - 1 ? ' row_last' : '') . ($row % 2 == 0 ? ' even' : ' odd'); } // Submit buttons do not use the name attribute if ($objFields->type == 'submit') { $arrData['name'] = ''; } $objWidget = new $strClass($arrData); $objWidget->required = $objFields->mandatory ? true : false; if ($objWidget->required) { $this->arrWidgetsFailedValidation[$objFields->name] = 0; } // always populate from existing session data if configured if ($GLOBALS['EFP'][$formId]['doNotCleanStoredSessionData'] == true && isset($_SESSION['FORM_DATA'][$objFields->name])) { $objWidget->value = $_SESSION['FORM_DATA'][$objFields->name]; } if ($strMode == 'reload' || $this->blnEditform && !strlen($_POST['FORM_BACK']) && !strlen($_POST['FORM_BACK_x'])) { // frontend editing if ($this->blnEditform && !$_SESSION['EFP'][$formId]['completed']['page_' . $this->intActivePage]) { if (is_array($objWidget->options)) { $arrData['options'] = $objWidget->options; } // prepare options array $arrData['options'] = $this->FormData->prepareDcaOptions($arrData); // set rgxp 'date' for field type 'calendar' if not set if ($arrData['type'] == 'calendar') { if (!isset($arrData['rgxp'])) { $arrData['rgxp'] = 'date'; } } elseif ($arrData['type'] == 'xdependentcalendarfields') { $arrData['rgxp'] = 'date'; $arrData['dateFormat'] = $arrData['xdateformat']; } // prepare value $varFieldValue = $this->FormData->prepareDbValForWidget($arrEditRecord[$objFields->name], $arrData); $objWidget->value = $varFieldValue; } else { // populate field if page has been completed if ($_SESSION['EFP'][$formId]['completed']['page_' . $this->intActivePage] == true) { $objWidget->value = $_SESSION['FORM_DATA'][$objFields->name]; } else { if ($objWidget instanceof uploadable) { unset($_SESSION['FILES'][$objFields->name]); } } } } // HOOK: load form field callback if (!strlen($_POST['FORM_BACK']) && !strlen($_POST['FORM_BACK_x'])) { if (isset($GLOBALS['TL_HOOKS']['loadFormField']) && is_array($GLOBALS['TL_HOOKS']['loadFormField'])) { foreach ($GLOBALS['TL_HOOKS']['loadFormField'] as $callback) { $this->import($callback[0]); $objWidget = $this->{$callback}[0]->{$callback}[1]($objWidget, $formId, $this->arrData); } } } // Validate input if ($this->Input->post('FORM_SUBMIT') == $formId) { // populate field if (strlen($_POST['FORM_BACK']) || strlen($_POST['FORM_BACK_x'])) { if ($strMode == 'back' && strlen($this->arrPaginators[$this->intActivePage - 1]['efgBackStoreSessionValues'])) { unset($_SESSION['FORM_DATA'][$objFields->name]); $objWidget->value = $this->Input->post($objFields->name); } elseif ($_SESSION['EFP'][$formId]['completed']['page_' . $this->intActivePage] == true) { $objWidget->value = $_SESSION['FORM_DATA'][$objFields->name]; unset($_SESSION['FORM_DATA'][$objFields->name]); } } if (!$doNotValidate) { if ($objWidget instanceof uploadable) { // if widget does not store the file, store it in tmp folder and session to make it available for mails etc. if (!$objWidget->storeFile) { if ($this->intActivePage < $this->intTotalPages) { // unset file in session, if this page has not been completed if (!$_SESSION['EFP'][$formId]['completed']['page_' . $this->intActivePage]) { unset($_SESSION['FILES'][$objFields->name]); } $objWidget->validate(); // file has been uploaded, store it in temp folder if (is_uploaded_file($_SESSION['FILES'][$objFields->name]['tmp_name'])) { $this->import('Files'); $strDstFile = TL_ROOT . '/system/tmp/' . md5_file($_SESSION['FILES'][$objFields->name]['tmp_name']); if (@copy($_SESSION['FILES'][$objFields->name]['tmp_name'], $strDstFile)) { $_SESSION['FILES'][$objFields->name]['tmp_name'] = $strDstFile; $_SESSION['FILES'][$objFields->name]['uploaded'] = true; $this->Files->chmod($strDstFile, 0644); } } } } else { $objWidget->validate(); } } else { $objWidget->validate(); } // HOOK: validate form field callback if (isset($GLOBALS['TL_HOOKS']['validateFormField']) && is_array($GLOBALS['TL_HOOKS']['validateFormField'])) { foreach ($GLOBALS['TL_HOOKS']['validateFormField'] as $callback) { $this->import($callback[0]); $objWidget = $this->{$callback}[0]->{$callback}[1]($objWidget, $formId, $this->arrData); } } } if ($objWidget->hasErrors()) { if ($objWidget->required) { $this->arrWidgetsFailedValidation[$objFields->name] = 1; } $doNotSubmit = true; } elseif ($objWidget->submitInput() || $strMode == 'back') { $arrSubmitted[$objFields->name] = $objWidget->value; $_SESSION['FORM_DATA'][$objFields->name] = $objWidget->value; } unset($_POST[$objFields->name]); } // if ($this->Input->post('FORM_SUBMIT') == $formId) if ($objWidget instanceof FormHidden) { $this->Template->hidden .= $objWidget->parse(); continue; } if ($objWidget instanceof uploadable) { $hasUpload = true; if ($this->blnMultipage) { // save file info in session in frontend edit mode if ($this->blnEditform && strlen($arrEditRecord[$objFields->name]) && (!isset($_SESSION['FILES'][$objFields->name]) || empty($_SESSION['FILES'][$objFields->name]))) { $objFile = new File($arrEditRecord[$objFields->name]); if ($objFile->size) { $_SESSION['FILES'][$objFields->name] = array('name' => $objFile->basename, 'type' => $objFile->mime, 'tmp_name' => TL_ROOT . '/' . $objFile->value, 'size' => $objFile->size, 'uploaded' => true); } } // add info about uploaded file to upload input if (isset($_SESSION['FILES'][$objFields->name]) && $_SESSION['FILES'][$objFields->name]['uploaded']) { $this->Template->fields .= preg_replace('/(.*?)(<input.*?>)(.*?)/sim', '$1<p class="upload_info">' . sprintf($GLOBALS['TL_LANG']['MSC']['fileUploaded'], $_SESSION['FILES'][$objFields->name]['name']) . '</p>$2$3', $objWidget->parse()); ++$row; continue; } } } // objWidget instanceof uploadable $this->Template->fields .= $objWidget->parse(); ++$row; } // while $objFields if ($doNotSubmit && $this->blnAllowSkipRequired) { if (count($this->arrWidgetsFailedValidation) && count(array_count_values($this->arrWidgetsFailedValidation)) == 1) { $doNotSubmit = false; } } // Process form data if ($this->Input->post('FORM_SUBMIT') == $formId && !$doNotSubmit) { if ($this->intTotalPages == 1 || !$this->blnMultipage && !$this->blnEditform) { $this->processFormData($arrSubmitted, $arrLabels); } else { // if not last page but page is completed, render next page if ($this->intActivePage < $this->intTotalPages && (strlen($_POST['FORM_NEXT']) || strlen($_POST['FORM_NEXT_x']))) { $_SESSION['EFP'][$formId]['render_page'] = (int) $_POST['FORM_PAGE'] + 1; $_SESSION['EFP'][$formId]['completed']['page_' . $_POST['FORM_PAGE']] = true; $this->reload(); } elseif ($strMode == 'back' && $this->intActivePage <= $this->intTotalPages && (strlen($_POST['FORM_BACK']) || strlen($_POST['FORM_BACK_x']))) { $_SESSION['EFP'][$formId]['render_page'] = (int) $_POST['FORM_PAGE'] - 1; $_SESSION['EFP'][$formId]['completed']['page_' . $_POST['FORM_PAGE']] = true; $this->reload(); } else { if ((int) $_POST['FORM_PAGE'] == $this->intTotalPages && (strlen($_POST['FORM_NEXT']) || strlen($_POST['FORM_NEXT_x']))) { unset($_SESSION['EFP'][$formId]['render_page']); unset($_SESSION['EFP'][$formId]['completed']); unset($_SESSION['FORM_DATA']['FORM_PAGE']); unset($_SESSION['FORM_DATA']['FORM_NEXT']); unset($_SESSION['FORM_DATA']['FORM_BACK']); $arrSubmitted = $_SESSION['FORM_DATA']; $this->processFormData($arrSubmitted, $arrLabels); } } } } $strAttributes = ''; $arrAttributes = deserialize($this->attributes, true); if (strlen($arrAttributes[1])) { $strAttributes .= ' class="' . $arrAttributes[1] . '"'; } $this->Template->hasError = $doNotSubmit; $this->Template->attributes = $strAttributes; $this->Template->enctype = $hasUpload ? 'multipart/form-data' : 'application/x-www-form-urlencoded'; $this->Template->formId = strlen($arrAttributes[0]) ? $arrAttributes[0] : 'f' . $this->id; //$this->Template->action = ampersand($this->Environment->request, true); $this->Template->action = $this->getIndexFreeRequest(); // Get target URL if ($this->method == 'GET') { $objNextPage = $this->Database->prepare("SELECT id, alias FROM tl_page WHERE id=?")->limit(1)->execute($this->jumpTo); if ($objNextPage->numRows) { $this->Template->action = $this->generateFrontendUrl($objNextPage->fetchAssoc()); } } // add Javascript to handle html5 input attribute 'required' on back button if ($blnIsHtml5) { $this->Template->fields .= ' <script>' . $this->getBackButtonJavascriptString() . ' </script>'; } if ($blnAddDateJS) { $this->Template->fields .= ' <script' . (!$blnIsHtml5 ? ' type="text/javascript"' : '') . '>' . $this->getDateString() . ' </script>'; } return $this->Template->parse(); }