/** * main form generation code build the model to approximate HML, the form UI and the binding between UI and model * @staticvar array [$dettypes] array detail type definitions for this database * @staticvar object [$di] field name to index mapping for detail type definition * @staticvar array [$rectypes] array record type structure definitions for this database * @staticvar object [$ri] field name to index mapping for record field structure definition * @staticvar object [$ti] field name to index mapping for term definition * @staticvar array [$termLookup] array term structure definitions for the enumerations in this database * @staticvar array [$relnLookup] array term structure definitions for the relationships in this database * @param integer [$rt_id] the rectype locally unique identifier * @return object an array of strings representing form, rtName, rtConceptID, rtDescription, and report on success * @uses getXFormTypeFromBaseType() * @uses createRecordLookup() * @uses createTermSelect() * @uses getTerms() * @uses getAllDetailTypeStructures() * @uses getAllRectypeStructures() * @uses HEURIST_UPLOAD_DIR * @uses HEURIST_BASE_URL * @uses HEURIST_DBNAME */ function buildform($rt_id) { // mappings and lookups - static so we only retrieve once per service call static $dettypes, $di, $rectypes, $ri, $rid, $terms, $ti, $termLookup, $relnLookup; if (!$dettypes || !$di) { $dettypes = getAllDetailTypeStructures(); $dettypes = $dettypes['typedefs']; $di = $dettypes['fieldNamesToIndex']; } if (!$rectypes || !$ri || !$rid) { $rectypes = getAllRectypeStructures(); $ri = $rectypes['typedefs']['commonNamesToIndex']; $rid = $rectypes['typedefs']['dtFieldNamesToIndex']; } if (!$terms || !$ti || !$termLookup || !$relnLookup) { $terms = getTerms(); $ti = $terms['fieldNamesToIndex']; $termLookup = $terms['termsByDomainLookup']['enum']; $relnLookup = $terms['termsByDomainLookup']['relation']; } if (!array_key_exists($rt_id, $rectypes['typedefs'])) { error_log("rectypes " . print_r($rectypes['typedefs'][$rt_id], true)); return array(null, null, null, null, "Rectype# {$rt_id} not found"); } $report = ""; $rectype = $rectypes['typedefs'][$rt_id]; // error_log("rectype is ".print_r($rectype,true)); //record type info $rtName = $rectypes['names'][$rt_id]; //detail or field type info $fieldTypeConceptIDIndex = $di['dty_ConceptID']; $fieldTypeNameIndex = $di['dty_Name']; $fieldBaseTypeIndex = $di['dty_Type']; //record field info $fieldNameIndex = $rid['rst_DisplayName']; $fieldDefaultValIndex = $rid['rst_DefaultValue']; $fieldHelpTextIndex = $rid['rst_DisplayHelpText']; $fieldTermsListIndex = $rid['rst_FilteredJsonTermIDTree']; $fieldTermHeaderListIndex = $rid['rst_TermIDTreeNonSelectableIDs']; $fieldPtrRectypeIDsListIndex = $rid['rst_PtrFilteredIDs']; $fieldMaxRepeatIndex = $rid['rst_MaxValues']; $rtConceptID = $rectype['commonFields'][$ri['rty_ConceptID']]; if (!$rtConceptID) { $rtConceptID = "0-" . $rt_id; } $rtDescription = $rectype['commonFields'][$ri['rty_Description']]; // output structure variables $model = "<instance>\n" . "<fhml id=\"heuristscholar.org:{$rtConceptID}\" version=\"" . date("Ymd") . "\">\n" . "<database id=\"" . HEURIST_DBID . "\" urlBase=\"" . HEURIST_BASE_URL . "\">" . HEURIST_DBNAME . "</database>\n" . "<query depth=\"0\" db=\"" . HEURIST_DBNAME . "\" q=\"t:{$rt_id}\" />\n" . "<generatedBy userID=\"" . get_user_id() . "\">" . get_user_name() . "</generatedBy>\n" . "<createdBy/>\n" . "<deviceID/>\n" . "<createTime/>\n" . "<uuid/>\n" . "<records count=\"1\">\n" . "<record depth=\"0\">\n" . "<type>\n" . "<conceptID>{$rtConceptID}</conceptID>\n" . "<label>{$rtName}</label>\n" . "</type>\n" . "<nonce/>\n" . "<details>\n"; $bind = "<bind nodeset=\"createdBy\" type=\"string\" jr:preload=\"property\" jr:preloadParams=\"username\"/>\n" . "<bind nodeset=\"createTime\" type=\"dateTime\" jr:preload=\"timestamp\" jr:preloadParams=\"start\"/>\n" . "<bind nodeset=\"deviceID\" type=\"string\" jr:preload=\"property\" jr:preloadParams=\"deviceid\"/>\n" . "<bind nodeset=\"uuid\" type=\"string\" readonly=\"true()\" calculate=\"uuid()\"/>\n" . "<bind nodeset=\"records/record/nonce\" type=\"string\" readonly=\"true()\" calculate=\"concat(/fhml/deviceID,'|',/fhml/createTime,'|',/fhml/uuid)\"/>\n"; $body = "<h:body>\n" . "<group appearance=\"field-list\">\n"; $groupSeparator = "</group>\n" . "<group appearance=\"field-list\">\n"; //@todo - sort by rst_DisplayOrder $fieldsLeft = count($rectype['dtFields']); $atGroupStart = true; //init separator detection for repatables foreach ($rectype['dtFields'] as $dt_id => $rt_dt) { if ($rt_dt[$rid['rst_NonOwnerVisibility']] == 'hidden') { continue; } --$fieldsLeft; // count down fields so we know when we hit the last one $dettype = $dettypes[$dt_id]['commonFields']; //get detail type description $baseType = $dettype[$fieldBaseTypeIndex]; $fieldTypeName = $dettype[$fieldTypeNameIndex]; $fieldName = $rt_dt[$fieldNameIndex]; $fieldtype = getXFormTypeFromBaseType($baseType); $fieldMaxCount = $rt_dt[$fieldMaxRepeatIndex]; $isRepeatable = $fieldMaxCount > 1 || $fieldMaxCount == NULL; //skip any unsupport field types if (!$fieldtype) { $report = $report . " {$rtName}." . $dettype[$fieldTypeNameIndex] . " ignored since type " . $baseType . " not supported<br/>"; continue; // not supported } if ($fieldtype == "groupbreak" && $atGroupStart) { //skip double separator, note that this includes separators before non supported types continue; } if ($baseType == "resource") { $rtIDs = $dettype[$di['dty_PtrTargetRectypeIDs']]; if (!$rtIDs || $rtIDs == "") { //unconstrained pointers not supported $report = $report . " {$rtName}." . $dettype[$fieldTypeNameIndex] . " ignored since unconstrained resource pointers are not supported<br/>"; continue; } } $dt_conceptid = $dettype[$fieldTypeConceptIDIndex]; if (!$dt_conceptid) { $dt_conceptid = "0-" . $dt_id; } $defaultValue = $rt_dt[$fieldDefaultValIndex]; // load default value //for controlled vocabs convert any local term ID to it's concept ID if ($baseType == "enum" && array_key_exists("{$defaultValue}", $termLookup)) { $termID = $termLookup[$defaultValue][$ti['trm_ConceptID']]; if ($termID) { $defaultValue = $termID; } else { $defaultValue = HEURIST_DBID . "-" . $defaultValue; } } else { if ($baseType == "relation" && array_key_exists("{$defaultValue}", $relnLookup)) { $termID = $relnLookup[$defaultValue][$ti['trm_ConceptID']]; if ($termID) { $defaultValue = $termID; } else { $defaultValue = HEURIST_DBID . "-" . $defaultValue; } } } if ($fieldtype != "groupbreak") { $model = $model . "<dt{$dt_id} conceptID=\"{$dt_conceptid}\" type=\"{$fieldTypeName}\" name=\"{$fieldName}\">" . ($defaultValue ? htmlentities($defaultValue) : "") . "</dt" . $dt_id . ">\n"; } if ($rt_dt[$rid['rst_RequirementType']] == 'required') { $isrequired = 'required="true()"'; } else { if ($rt_dt[$rid['rst_RequirementType']] == 'forbidden') { $isrequired = 'readonly="true()"'; } else { $isrequired = ''; } } $constraint = ''; /* @todo if($rt_dt[$rid['rst_MinValues']]=='required'){ //constraint=". > 10.51 and . < 18.39" jr:constraintMsg="number must be between 10.51 and 18.39" } */ // if repeatable vocab make it multi select. TODO: we should extend Heurist to include multi-select which is different than repeatable if ($fieldtype == "select1" && $isRepeatable) { $fieldtype = "select"; $isRepeatable = false; } $label = htmlentities($rt_dt[$fieldNameIndex]); $hint = htmlentities($rt_dt[$fieldHelpTextIndex]); $inputDefBody = "<label>{$label}</label>\n" . "<hint>{$hint}</hint>\n"; $xpathPrefix = "/fhml/records/record/details/"; $groupRepeatHdr = ($atGroupStart ? "" : $groupSeparator) . "<label>{$label}</label>\n" . "<repeat nodeset=\"/fhml/records/record/details/dt{$dt_id}\">\n"; $groupRepeatFtr = "</repeat>\n" . ($fieldsLeft ? $groupSeparator : ""); $atGroupStart = false; // past detection code so if ($fieldtype != "groupbreak") { $bind = $bind . "<bind nodeset=\"records/record/details/dt{$dt_id}\" type=\"{$fieldtype}\" {$isrequired} {$constraint}/>\n"; } if ($isRepeatable) { $body .= $groupRepeatHdr; } if ($fieldtype == "select1" || $fieldtype == "select") { if ($baseType == "resource") { $body = $body . "<{$fieldtype} appearance=\"minimal\" ref=\"" . $xpathPrefix . "dt" . $dt_id . "\">\n" . $inputDefBody . createRecordLookup($rtIDs) . "</{$fieldtype}>\n"; } else { $termIDTree = $dettype[$di['dty_JsonTermIDTree']]; $disabledTermIDsList = $dettype[$di['dty_TermIDTreeNonSelectableIDs']]; $fieldLookup = $baseType == "relation" ? $relnLookup : $termLookup; $body = $body . "<{$fieldtype} appearance=\"minimal\" ref=\"" . $xpathPrefix . "dt" . $dt_id . "\">\n" . $inputDefBody . createTermSelect($termIDTree, $disabledTermIDsList, $fieldLookup, false, $ti) . "</{$fieldtype}>\n"; } } else { if ($fieldtype == "binary") { //todo check for sketch type $isDrawing = false; $appearance = $dt_id == DT_DRAWING ? "draw" : "annotate"; $body = $body . "<upload ref=\"" . $xpathPrefix . "dt{$dt_id}\" appearance=\"{$appearance}\" mediatype=\"image/*\">\n" . $inputDefBody . "</upload>\n"; } else { if ($fieldtype == "groupbreak") { // if we get to here we have a legitament sepearator so break $body .= $groupSeparator; $atGroupStart = true; } else { if ($dt_id == DT_COUNTER) { //we have a counter field so let's launch the Inventory Counter $body = $body . "<input appearance=\"ex:faims.android.INVENTORYCOUNT\" ref=\"" . $xpathPrefix . "dt{$dt_id}\">\n" . $inputDefBody . "</input>\n"; } else { //all others and $fieldtype=="geopoint" as well $body = $body . "<input ref=\"" . $xpathPrefix . "dt{$dt_id}\">\n" . $inputDefBody . "</input>\n"; } } } } if ($isRepeatable) { $body .= $groupRepeatFtr; if ($fieldsLeft > 0) { $atGroupStart = true; } } } $model = $model . "</details>\n" . "</record>\n" . "</records>\n" . "</fhml>\n" . "</instance>\n"; $body = $body . "</group>\n" . "</h:body>\n"; $form = "<?xml version=\"1.0\"?>\n" . "<h:html xmlns=\"http://www.w3.org/2002/forms\" xmlns:h=\"http://www.w3.org/1999/xhtml\" " . "xmlns:ev=\"http://www.w3.org/2001/xml-events\" " . "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " . "xmlns:jr=\"http://openrosa.org/javarosa\">\n" . "<h:head>\n" . "<h:title>{$rtName}</h:title>\n" . "<model>\n" . $model . $bind . "</model>\n" . "</h:head>\n" . $body . "</h:html>"; return array($form, $rtName, $rtConceptID, $rtDescription, $report); }
//parking address echo createFormRowTextField('Parking Address', 'editDriverAddressLine1', $flag ? 'class="bg"' : '', false, "size='10px' value='" . $driverInfo['addressLine1'] . "'"); $flag = !$flag; echo createFormRowTextField('Address Line 2', 'editDriverAddressLine2', $flag ? 'class="bg"' : '', false, "size='10px' value='" . $driverInfo['addressLine2'] . "'"); $flag = !$flag; echo createFormRowTextField('City', 'editDriverAddressCity', $flag ? 'class="bg"' : '', false, "size='10px' value='" . $driverInfo['addressCity'] . "'"); $flag = !$flag; //state echo createFormRow('State', $flag ? 'class="bg"' : '', false, createStateSelect($conexion, 'editDriverAddressState', $driverInfo['addressState'])); $flag = !$flag; echo createFormRowTextField('Zip', 'editDriverAddressZip', $flag ? 'class="bg"' : '', false, "size='10px' value='" . $driverInfo['addressZip'] . "'"); $flag = !$flag; echo createFormRowTextField('P.O.Box', 'editDriverAddressBox', $flag ? 'class="bg"' : '', false, "size='10px' value='" . $driverInfo['addressPOBox'] . "'"); $flag = !$flag; // echo createFormRow('Payment Terms', $flag ? 'class="bg"' : '', true, createTermSelect($conexion, 'editDriverTermId', $driverInfo['termId'])); $flag = !$flag; echo createFormRowTextField('Percentage', 'editDriverPercentage', $flag ? 'class="bg"' : '', true, "size='10px' value='" . $driverInfo['driverPercentage'] . "'"); $flag = !$flag; echo createFormRowTextField('Driver Start Date', 'editDriverStartDate', $flag ? 'class="bg"' : '', false, "size='10px' value='" . to_MDY($driverInfo['driverStartDate']) . "'"); $flag = !$flag; echo createFormRow('Gender', $flag ? 'class="bg"' : '', true, arrayToSelect(array("0" => "--Select Gender--", "male" => "Male", "female" => "Female"), $driverInfo['driverGender'], 'editDriverGender', 'Gender', true)); $flag = !$flag; echo createFormRow('Ethnicity', $flag ? 'class="bg"' : '', true, createEthnicitySelect($conexion, 'editDriverEthnicId', $driverInfo['ethnicId'])); $flag = !$flag; echo createFormRow('Class', $flag ? 'class="bg"' : '', true, arrayToSelect(array("--Select Class--", "Class 1", "Class 2", "Class 3", "Class 4"), $driverInfo['driverClass'], 'editDriverClass', 'Class', true)); $flag = !$flag; ?> </table> <table> <tr>
$flag = !$flag; //parking address echo createFormRowTextField('Parking Address', 'addressLine1', $flag ? 'class="bg"' : '', false, 'size=10px'); $flag = !$flag; echo createFormRowTextField('Address Line 2', 'addressLine2', $flag ? 'class="bg"' : '', false, 'size=10px'); $flag = !$flag; echo createFormRowTextField('City', 'addressCity', $flag ? 'class="bg"' : '', false, 'size=10px'); $flag = !$flag; echo createFormRow('State', $flag ? 'class="bg"' : '', false, createStateSelect($conexion, 'addressState')); $flag = !$flag; echo createFormRowTextField('Zip', 'addressZip', $flag ? 'class="bg"' : '', false, 'size=10px'); $flag = !$flag; echo createFormRowTextField('P.O.Box', 'addressBox', $flag ? 'class="bg"' : '', false, 'size=10px'); $flag = !$flag; // echo createFormRow('Payment Terms', $flag ? 'class="bg"' : '', true, createTermSelect($conexion, 'termId')); $flag = !$flag; echo createFormRowTextField('Percentage', 'percentage', $flag ? 'class="bg"' : '', true, 'size=10px'); $flag = !$flag; echo createFormRowTextField('Driver Start Date', 'startDate', $flag ? 'class="bg"' : '', false, 'size=14px'); $flag = !$flag; echo createFormRow('Gender', $flag ? 'class="bg"' : '', true, arrayToSelect(array("0" => "--Select Gender--", "male" => "Male", "female" => "Female"), "0", 'gender', 'Gender', true)); $flag = !$flag; echo createFormRow('Ethnicity', $flag ? 'class="bg"' : '', true, createEthnicitySelect($conexion, 'ethnicId')); $flag = !$flag; echo createFormRow('Class', $flag ? 'class="bg"' : '', true, arrayToSelect(array("--Select Class--", "Class 1", "Class 2", "Class 3", "Class 4"), "0", 'driverClass', 'Class', true)); $flag = !$flag; ?> </table> <table> <tr>