/** * Constructs the PHP target object from the parameters sent to the web page by the wizard * @param boolean $bReadUploadedFiles True to also ready any uploaded file (for blob/document fields) * @return object */ public function GetTargetObject($bReadUploadedFiles = false) { if (isset($this->m_aData['m_oCurrentValues']['id'])) { $oObj = MetaModel::GetObject($this->m_aData['m_sClass'], $this->m_aData['m_oCurrentValues']['id']); } else { $oObj = MetaModel::NewObject($this->m_aData['m_sClass']); } foreach ($this->m_aData['m_oCurrentValues'] as $sAttCode => $value) { // Because this is stored in a Javascript array, unused indexes // are filled with null values and unused keys (stored as strings) contain $$NULL$$ if ($sAttCode != 'id' && $sAttCode !== false && $value !== null && $value !== '$$NULL$$') { $oAttDef = MetaModel::GetAttributeDef($this->m_aData['m_sClass'], $sAttCode); if ($oAttDef->IsLinkSet() && $value != '') { // special handling for lists // assumes this is handled as an array of objects // thus encoded in json like: [ { name:'link1', 'id': 123}, { name:'link2', 'id': 124}...] $aData = json_decode($value, true); // true means decode as a hash array (not an object) // Check what are the meaningful attributes $aFields = $this->GetLinkedWizardStructure($oAttDef); $sLinkedClass = $oAttDef->GetLinkedClass(); $aLinkedObjectsArray = array(); if (!is_array($aData)) { echo "aData: '{$aData}' (value: '{$value}')\n"; } foreach ($aData as $aLinkedObject) { $oLinkedObj = MetaModel::NewObject($sLinkedClass); foreach ($aFields as $sLinkedAttCode) { if (isset($aLinkedObject[$sLinkedAttCode]) && $aLinkedObject[$sLinkedAttCode] !== null) { $sLinkedAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sLinkedAttCode); if ($sLinkedAttDef->IsExternalKey() && $aLinkedObject[$sLinkedAttCode] != '' && $aLinkedObject[$sLinkedAttCode] > 0) { // For external keys: load the target object so that external fields // get filled too $oTargetObj = MetaModel::GetObject($sLinkedAttDef->GetTargetClass(), $aLinkedObject[$sLinkedAttCode]); $oLinkedObj->Set($sLinkedAttCode, $oTargetObj); } else { $oLinkedObj->Set($sLinkedAttCode, $aLinkedObject[$sLinkedAttCode]); } } } $aLinkedObjectsArray[] = $oLinkedObj; } $oSet = DBObjectSet::FromArray($sLinkedClass, $aLinkedObjectsArray); $oObj->Set($sAttCode, $oSet); } else { if ($oAttDef->GetEditClass() == 'Document') { if ($bReadUploadedFiles) { $oDocument = utils::ReadPostedDocument('attr_' . $sAttCode, 'fcontents'); $oObj->Set($sAttCode, $oDocument); } else { // Create a new empty document, just for displaying the file name $oDocument = new ormDocument(null, '', $value); $oObj->Set($sAttCode, $oDocument); } } else { if ($oAttDef->IsExternalKey() && !empty($value) && $value > 0) { // For external keys: load the target object so that external fields // get filled too $oTargetObj = MetaModel::GetObject($oAttDef->GetTargetClass(), $value); $oObj->Set($sAttCode, $oTargetObj); } else { $oObj->Set($sAttCode, $value); } } } } } if (isset($this->m_aData['m_sState']) && !empty($this->m_aData['m_sState'])) { $oObj->Set(MetaModel::GetStateAttributeCode($this->m_aData['m_sClass']), $this->m_aData['m_sState']); } $oObj->DoComputeValues(); return $oObj; }
// Check user rights and prompt if needed $oPage = new ajax_page(""); $oPage->no_cache(); $sOperation = utils::ReadParam('operation', ''); switch ($sOperation) { case 'add': $aResult = array('error' => '', 'att_id' => 0, 'preview' => 'false', 'msg' => ''); $sObjClass = stripslashes(utils::ReadParam('obj_class', '', false, 'class')); $sTempId = utils::ReadParam('temp_id', ''); if (empty($sObjClass)) { $aResult['error'] = "Missing argument 'obj_class'"; } elseif (empty($sTempId)) { $aResult['error'] = "Missing argument 'temp_id'"; } else { try { $oDoc = utils::ReadPostedDocument('file'); $oAttachment = MetaModel::NewObject('Attachment'); $oAttachment->Set('expire', time() + 3600); // one hour... $oAttachment->Set('temp_id', $sTempId); $oAttachment->Set('item_class', $sObjClass); $oAttachment->SetDefaultOrgId(); $oAttachment->Set('contents', $oDoc); $iAttId = $oAttachment->DBInsert(); $aResult['msg'] = $oDoc->GetFileName(); $aResult['icon'] = utils::GetAbsoluteUrlAppRoot() . AttachmentPlugIn::GetFileIcon($oDoc->GetFileName()); $aResult['att_id'] = $iAttId; $aResult['preview'] = $oDoc->IsPreviewAvailable() ? 'true' : 'false'; } catch (FileUploadException $e) { $aResult['error'] = $e->GetMessage(); }
$oDashboard = $oMenu->GetDashboard(); $oPage->TrashUnexpectedOutput(); $oPage->SetContentType('text/xml'); $oPage->SetContentDisposition('attachment', $oMenu->GetLabel() . '.xml'); $oPage->add($oDashboard->ToXml()); } break; case 'import_dashboard': $sMenuId = utils::ReadParam('id', '', false, 'raw_data'); ApplicationMenu::LoadAdditionalMenus(); $index = ApplicationMenu::GetMenuIndexById($sMenuId); $oMenu = ApplicationMenu::GetMenuNode($index); $aResult = array('error' => ''); try { if ($oMenu instanceof DashboardMenuNode) { $oDoc = utils::ReadPostedDocument('dashboard_upload_file'); $oDashboard = $oMenu->GetDashboard(); $oDashboard->FromXml($oDoc->GetData()); $oDashboard->Save(); } else { $aResult['error'] = 'Dashboard id="' . $sMenuId . '" not found.'; } } catch (DOMException $e) { $aResult = array('error' => Dict::S('UI:Error:InvalidDashboardFile')); } catch (Exception $e) { $aResult = array('error' => $e->getMessage()); } $oPage->add(json_encode($aResult)); break; case 'about_box': $oPage->SetContentType('text/html');
/** * Updates the object from the POSTed parameters (form) */ public function UpdateObjectFromPostedForm($sFormPrefix = '', $aAttList = null, $sTargetState = '') { if (is_null($aAttList)) { $aAttList = array_keys(MetaModel::ListAttributeDefs(get_class($this))); } $aValues = array(); foreach ($aAttList as $sAttCode) { $oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode); if ($oAttDef->GetEditClass() == 'Document') { $value = array('fcontents' => utils::ReadPostedDocument("attr_{$sFormPrefix}{$sAttCode}", 'fcontents')); } elseif ($oAttDef->GetEditClass() == 'RedundancySetting') { $value = $oAttDef->ReadValueFromPostedForm($sFormPrefix); } else { if ($oAttDef->GetEditClass() == 'LinkedSet' && !$oAttDef->IsIndirect() && ($oAttDef->GetEditMode() == LINKSET_EDITMODE_INPLACE || $oAttDef->GetEditMode() == LINKSET_EDITMODE_ADDREMOVE)) { $aRawToBeCreated = json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tbc", '{}', 'raw_data'), true); $aToBeCreated = array(); foreach ($aRawToBeCreated as $aData) { $sSubFormPrefix = $aData['formPrefix']; $sObjClass = $aData['class']; $aObjData = array(); foreach ($aData as $sKey => $value) { if (preg_match("/^attr_{$sSubFormPrefix}(.*)\$/", $sKey, $aMatches)) { $aObjData[$aMatches[1]] = $value; } } $aToBeCreated[] = array('class' => $sObjClass, 'data' => $aObjData); } $value = array('to_be_created' => $aToBeCreated, 'to_be_deleted' => json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tbd", '[]', 'raw_data'), true), 'to_be_added' => json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tba", '[]', 'raw_data'), true), 'to_be_removed' => json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tbr", '[]', 'raw_data'), true)); } else { $value = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null, 'raw_data'); } } if (!is_null($value)) { $aValues[$sAttCode] = $value; } } $aErrors = array(); $aFinalValues = array(); foreach ($this->GetWriteableAttList(array_keys($aValues), $aErrors, $sTargetState) as $sAttCode => $oAttDef) { $aFinalValues[$sAttCode] = $aValues[$sAttCode]; } $this->UpdateObjectFromArray($aFinalValues); // Invoke extensions after the update of the object from the form foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance) { $oExtensionInstance->OnFormSubmit($this, $sFormPrefix); } return $aErrors; }
/** * Select the options of the CSV load and check for CSV parsing errors * @param WebPage $oPage The current web page * @return void */ function SelectOptions(WebPage $oPage) { $sOperation = utils::ReadParam('operation', 'csv_data'); $sCSVData = ''; switch ($sOperation) { case 'file_upload': $oDocument = utils::ReadPostedDocument('csvdata'); if (!$oDocument->IsEmpty()) { $sCSVData = $oDocument->GetData(); } break; default: $sCSVData = utils::ReadPostedParam('csvdata', '', 'raw_data'); } $sEncoding = utils::ReadParam('encoding', 'UTF-8'); // Compute a subset of the data set, now that we know the charset if ($sEncoding == 'UTF-8') { // Remove the BOM if any if (substr($sCSVData, 0, 3) == UTF8_BOM) { $sCSVData = substr($sCSVData, 3); } // Clean the input // Todo: warn the user if some characters are lost/substituted $sUTF8Data = iconv('UTF-8', 'UTF-8//IGNORE//TRANSLIT', $sCSVData); } else { $sUTF8Data = iconv($sEncoding, 'UTF-8//IGNORE//TRANSLIT', $sCSVData); } $aGuesses = GuessParameters($sUTF8Data); // Try to predict the parameters, based on the input data $sSeparator = utils::ReadParam('separator', '', false, 'raw_data'); if ($sSeparator == '') { $sSeparator = $aGuesses['separator']; } $iSkippedLines = utils::ReadParam('nb_skipped_lines', ''); $bBoxSkipLines = utils::ReadParam('box_skiplines', 0); if ($sSeparator == 'tab') { $sSeparator = "\t"; } $sOtherSeparator = in_array($sSeparator, array(',', ';', "\t")) ? '' : $sSeparator; $sTextQualifier = utils::ReadParam('text_qualifier', '', false, 'raw_data'); if ($sTextQualifier == '') { $sTextQualifier = $aGuesses['qualifier']; } $sOtherTextQualifier = in_array($sTextQualifier, array('"', "'")) ? '' : $sTextQualifier; $bHeaderLine = utils::ReadParam('header_line', 0); $sClassName = utils::ReadParam('class_name', '', false, 'class'); $bAdvanced = utils::ReadParam('advanced', 0); $aFieldsMapping = utils::ReadParam('field', array(), false, 'raw_data'); $aSearchFields = utils::ReadParam('search_field', array(), false, 'field_name'); // Create a truncated version of the data used for the fast preview // Take about 20 lines of data... knowing that some lines may contain carriage returns $iMaxLen = strlen($sUTF8Data); if ($iMaxLen > 0) { $iMaxLines = 20; $iCurPos = true; while ($iCurPos > 0 && $iMaxLines > 0) { $pos = strpos($sUTF8Data, "\n", $iCurPos); if ($pos !== false) { $iCurPos = 1 + $pos; } else { $iCurPos = strlen($sUTF8Data); $iMaxLines = 1; } $iMaxLines--; } $sCSVDataTruncated = substr($sUTF8Data, 0, $iCurPos); } else { $sCSVDataTruncated = ''; } $sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data'); if (!empty($sSynchroScope)) { $oSearch = DBObjectSearch::FromOQL($sSynchroScope); $sClassName = $oSearch->GetClass(); $oSet = new DBObjectSet($oSearch); $iCount = $oSet->Count(); DisplaySynchroBanner($oPage, $sClassName, $iCount); $aSynchroUpdate = utils::ReadParam('synchro_update', array()); } $oPage->add('<h2>' . Dict::S('UI:Title:CSVImportStep2') . '</h2>'); $oPage->add('<div class="wizContainer">'); $oPage->add('<table><tr><td style="vertical-align:top;padding-right:50px;">'); $oPage->add('<form enctype="multipart/form-data" id="wizForm" method="post" id="csv_options">'); $oPage->add('<h3>' . Dict::S('UI:CSVImport:SeparatorCharacter') . '</h3>'); $oPage->add('<p><input type="radio" name="separator" value="," onClick="DoPreview()"' . IsChecked($sSeparator, ',') . '/> ' . Dict::S('UI:CSVImport:SeparatorComma+') . '<br/>'); $oPage->add('<input type="radio" name="separator" value=";" onClick="DoPreview()"' . IsChecked($sSeparator, ';') . '/> ' . Dict::S('UI:CSVImport:SeparatorSemicolon+') . '<br/>'); $oPage->add('<input type="radio" name="separator" value="tab" onClick="DoPreview()"' . IsChecked($sSeparator, "\t") . '/> ' . Dict::S('UI:CSVImport:SeparatorTab+') . '<br/>'); $oPage->add('<input type="radio" name="separator" value="other" onClick="DoPreview()"' . IsChecked($sOtherSeparator, '', true) . '/> ' . Dict::S('UI:CSVImport:SeparatorOther') . ' <input type="text" size="3" maxlength="1" name="other_separator" id="other_separator" value="' . $sOtherSeparator . '" onClick="DoPreview()"/>'); $oPage->add('</p>'); $oPage->add('</td><td style="vertical-align:top;padding-right:50px;">'); $oPage->add('<h3>' . Dict::S('UI:CSVImport:TextQualifierCharacter') . '</h3>'); $oPage->add('<p><input type="radio" name="text_qualifier" value=""" onClick="DoPreview()"' . IsChecked($sTextQualifier, '"') . '/> ' . Dict::S('UI:CSVImport:QualifierDoubleQuote+') . '<br/>'); $oPage->add('<input type="radio" name="text_qualifier" value="'" onClick="DoPreview()"' . IsChecked($sTextQualifier, "'") . '/> ' . Dict::S('UI:CSVImport:QualifierSimpleQuote+') . '<br/>'); $oPage->add('<input type="radio" name="text_qualifier" value="other" onClick="DoPreview()"' . IsChecked($sOtherTextQualifier, '', true) . '/> ' . Dict::S('UI:CSVImport:QualifierOther') . ' <input type="text" size="3" maxlength="1" name="other_qualifier" value="' . htmlentities($sOtherTextQualifier, ENT_QUOTES, 'UTF-8') . '" onChange="DoPreview()"/>'); $oPage->add('</p>'); $oPage->add('</td><td style="vertical-align:top;">'); $oPage->add('<h3>' . Dict::S('UI:CSVImport:CommentsAndHeader') . '</h3>'); $oPage->add('<p><input type="checkbox" name="header_line" id="box_header" value="1" onClick="DoPreview()"' . IsChecked($bHeaderLine, 1) . '/> ' . Dict::S('UI:CSVImport:TreatFirstLineAsHeader') . '<p>'); $oPage->add('<p><input type="checkbox" name="box_skiplines" value="1" id="box_skiplines" onClick="DoPreview()"' . IsChecked($bBoxSkipLines, 1) . '/> ' . Dict::Format('UI:CSVImport:Skip_N_LinesAtTheBeginning', '<input type="text" size=2 name="nb_skipped_lines" id="nb_skipped_lines" onChange="DoPreview()" value="' . $iSkippedLines . '">') . '<p>'); $oPage->add('</td></tr></table>'); $oPage->add('<input type="hidden" name="csvdata_truncated" id="csvdata_truncated" value="' . htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8') . '"/>'); $oPage->add('<input type="hidden" name="csvdata" id="csvdata" value="' . htmlentities($sUTF8Data, ENT_QUOTES, 'UTF-8') . '"/>'); // The encoding has changed, keep that information within the wizard $oPage->add('<input type="hidden" name="encoding" value="UTF-8">'); $oPage->add('<input type="hidden" name="class_name" value="' . $sClassName . '"/>'); $oPage->add('<input type="hidden" name="advanced" value="' . $bAdvanced . '"/>'); $oPage->add('<input type="hidden" name="synchro_scope" value="' . $sSynchroScope . '"/>'); foreach ($aFieldsMapping as $iNumber => $sAttCode) { $oPage->add('<input type="hidden" name="field[' . $iNumber . ']" value="' . $sAttCode . '"/>'); } foreach ($aSearchFields as $index => $sDummy) { $oPage->add('<input type="hidden" name="search_field[' . $index . ']" value="1"/>'); } $oPage->add('<input type="hidden" name="step" value="3"/>'); if (!empty($sSynchroScope)) { foreach ($aSynchroUpdate as $sKey => $value) { $oPage->add('<input type="hidden" name="synchro_update[' . $sKey . ']" value="' . $value . '"/>'); } } $oPage->add('<div id="preview">'); $oPage->add('<p style="text-align:center">' . Dict::S('UI:CSVImport:CSVDataPreview') . '</p>'); $oPage->add('</div>'); $oPage->add('<input type="button" value="' . Dict::S('UI:Button:Back') . '" onClick="GoBack()"/>'); $oPage->add('<input type="submit" value="' . Dict::S('UI:Button:Next') . '"/>'); $oPage->add('</form>'); $oPage->add('</div>'); $oPage->add_script(<<<EOF \tfunction GoBack() \t{ \t\t\$('input[name=step]').val(1); \t\t\$('#wizForm').submit(); \t\t \t} \t \tvar ajax_request = null; \t \tfunction DoPreview() \t{ \t\tvar separator = \$('input[name=separator]:checked').val(); \t\tif (separator == 'other') \t\t{ \t\t\tseparator = \$('#other_separator').val(); \t\t} \t\tvar text_qualifier = \$('input[name=text_qualifier]:checked').val(); \t\tif (text_qualifier == 'other') \t\t{ \t\t\ttext_qualifier = \$('#other_qualifier').val(); \t\t} \t\tvar do_skip_lines = 0; \t\tif (\$('#box_skiplines:checked').val() != null) \t\t{ \t\t\tdo_skip_lines = \$('#nb_skipped_lines').val(); \t\t} \t\tvar header_line = 0; \t\tif (\$('#box_header:checked').val() != null) \t\t{ \t\t\theader_line = 1; \t\t} \t\tvar encoding = \$('input[name=encoding]').val(); \t\t\$('#preview').block(); \t\t \t\t// Make sure that we cancel any pending request before issuing another \t\t// since responses may arrive in arbitrary order \t\tif (ajax_request != null) \t\t{ \t\t\tajax_request.abort(); \t\t\tajax_request = null; \t\t} \t\t \t\tajax_request = \$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.csvimport.php', \t\t\t { operation: 'parser_preview', enctype: 'multipart/form-data', csvdata: \$("#csvdata_truncated").val(), separator: separator, qualifier: text_qualifier, do_skip_lines: do_skip_lines, header_line: header_line, encoding: encoding }, \t\t\t function(data) { \t\t\t\t \$('#preview').empty(); \t\t\t\t \$('#preview').append(data); \t\t\t\t \$('#preview').unblock(); \t\t\t\t} \t\t\t ); \t} EOF ); $oPage->add_ready_script('DoPreview();'); }