Exemple #1
0
function dataExtraction($frame = "", $form, $filter, $andor, $scope, $limitStart, $limitSize, $sortField, $sortOrder, $forceQuery, $mainFormOnly, $includeArchived = false, $id_reqsOnly = false, $resultOnly = false, $filterElements = null)
{
    global $xoopsDB;
    $limitStart = intval($limitStart);
    $limitSize = intval($limitSize);
    $sortField = formulize_db_escape($sortField);
    if (isset($_GET['debug'])) {
        $time_start = microtime_float();
    }
    if ($scope == "uid=\"blankscope\"") {
        return array();
    }
    if (is_numeric($frame)) {
        $frid = $frame;
    } elseif ($frame != "") {
        $frameid = go("SELECT frame_id FROM " . DBPRE . "formulize_frameworks WHERE frame_name='{$frame}'");
        $frid = $frameid[0]['frame_id'];
        unset($frameid);
    } else {
        $frid = "";
    }
    if (is_numeric($form)) {
        $fid = $form;
    } elseif ($GLOBALS['formulize_versionFourOrHigher'] == false) {
        $formcheck = go("SELECT ff_form_id FROM " . DBPRE . "formulize_framework_forms WHERE ff_frame_id='{$frid}' AND ff_handle='{$form}'");
        $fid = $formcheck[0]['ff_form_id'];
        unset($formcheck);
    }
    if (!$fid) {
        print "Form Name: " . $form . "<br>";
        print "Form id: " . $fid . "<br>";
        print "Frame Name: " . $frame . "<br>";
        print "Frame id: " . $frid . "<br>";
        exit("selected form does not exist in framework");
    }
    $form_handler = xoops_getmodulehandler('forms', 'formulize');
    $formObject = $form_handler->get($fid);
    if ($frid and !$mainFormOnly) {
        // GET THE LINK INFORMATION FOR THE CURRENT FRAMEWORK BASED ON THE REQUESTED FORM
        $linklist1 = go("SELECT fl_form2_id, fl_key1, fl_key2, fl_relationship, fl_unified_display, fl_common_value FROM " . DBPRE . "formulize_framework_links WHERE fl_frame_id = '{$frid}' AND fl_form1_id = '{$fid}'");
        $linklist2 = go("SELECT fl_form1_id, fl_key1, fl_key2, fl_relationship, fl_unified_display, fl_common_value FROM " . DBPRE . "formulize_framework_links WHERE fl_frame_id = '{$frid}' AND fl_form2_id = '{$fid}'");
    }
    // link list 1 is the list of form2s that the requested form links to
    // link list 2 is the list of form1s that the requested form links to
    // ie: the link list number denotes the position of the requested form in the pair
    //	print "Frame: $frame ($frid)<br>";
    //	print "Form: $form ($fid)<br>";
    // generate the list of key fields in the current form, so we can use the values in these fields to filter the linked forms. -- sept 27 2005
    $linkkeys1 = array();
    $linkisparent1 = array();
    $linkformids1 = array();
    $linktargetids1 = array();
    $linkselfids1 = array();
    $linkcommonvalue1 = array();
    $linkkeys2 = array();
    $linkisparent2 = array();
    $linkformids2 = array();
    $linktargetids2 = array();
    $linkselfids2 = array();
    $linkcommonvalue2 = array();
    if ($frid and !$mainFormOnly) {
        if (count($linklist1) > 0) {
            foreach ($linklist1 as $theselinks) {
                $linkformids1[] = $theselinks['fl_form2_id'];
                if ($theselinks['fl_key1'] != 0) {
                    $handleforlink = formulize_getElementHandleFromID($theselinks['fl_key1']);
                    $linkkeys1[] = $handleforlink;
                    $linktargetids1[] = $theselinks['fl_key2'];
                    $linkselfids1[] = $theselinks['fl_key1'];
                } else {
                    $linkkeys1[] = "";
                    $linktargetids1[] = "";
                }
                if ($theselinks['fl_relationship'] == 2) {
                    // 2 is one to many relationship...this does not appear to be referenced anywhere in the extraction layer!
                    $linkisparent1[] = 1;
                } else {
                    $linkisparent1[] = 0;
                }
                $linkcommonvalue1[] = $theselinks['fl_common_value'];
            }
        }
        if (count($linklist2) > 0) {
            foreach ($linklist2 as $theselinks) {
                $linkformids2[] = $theselinks['fl_form1_id'];
                if ($theselinks['fl_key2'] != 0) {
                    $handleforlink = formulize_getElementHandleFromID($theselinks['fl_key2']);
                    $linkkeys2[] = $handleforlink;
                    $linktargetids2[] = $theselinks['fl_key1'];
                    $linkselfids2[] = $theselinks['fl_key2'];
                } else {
                    $linkkeys2[] = "";
                    $linktargetids2[] = "";
                }
                if ($theselinks['fl_relationship'] == 3) {
                    // 3 is many to one relationship...this does not appear to be referenced anywhere in the extraction layer!
                    $linkisparent2[] = 1;
                } else {
                    $linkisparent2[] = 0;
                }
                $linkcommonvalue2[] = $theselinks['fl_common_value'];
            }
        }
        $linkkeys = array_merge($linkkeys1, $linkkeys2);
        $linkisparent = array_merge($linkisparent1, $linkisparent2);
        $linkformids = array_merge($linkformids1, $linkformids2);
        $linktargetids = array_merge($linktargetids1, $linktargetids2);
        $linkselfids = array_merge($linkselfids1, $linkselfids2);
        $linkcommonvalue = array_merge($linkcommonvalue1, $linkcommonvalue2);
    } else {
        $linkkeys = "";
        $linkisparent = "";
        $linkformids = array();
        $linktargetids = "";
        $linkselfids = "";
        $linkcommonvalue = "";
    }
    //print_r( $linkformids );
    $GLOBALS['formulize_linkformidsForCalcs'] = $linkformids;
    // now that we have the full details from the framework, figure out the full SQL necessary to get the entire dataset
    // This whole approach is predicated on being able to do reliable joins between the key fields of each form
    // Structure of the SQL should be...
    // SELECT main.entry_id, main.creation_uid, main.mod_uid, main.creation_datetime, main.mod_datetime, main.handle1...main.handleN, f2.entry_id, f2.1..f2.n, etc FROM formulize_A AS main [join syntax] WHERE main.handle1 = "whatever" AND/OR f2.handle1 = "whatever"
    // Join syntax:  if there are query terms on the f2 or subsequent forms, then use INNER JOIN formulize_B AS f2 ON main.1 LIKE CONCAT('%,', f2.entry_id, ',%') -- or no %, ,% if only one value is allowed
    // If there are no query terms on the f2 or subsequent forms, then use LEFT JOIN
    // establish the join type and all that
    $joinText = "";
    $linkSelect = "";
    $exportOverrideQueries = array();
    $limitClause = "";
    if ($limitSize) {
        $limitClause = " LIMIT {$limitStart}, {$limitSize} ";
    }
    if (is_array($filter) or substr($filter, 0, 6) != "SELECT" and substr($filter, 0, 6) != "INSERT") {
        // if the filter is not itself a fully formed SQL statement...
        $scopeFilter = "";
        if (is_array($scope)) {
            // assume any arrays are groupid arrays, and so make a valid scope string based on this.  Use the new entry owner table.
            if (count($scope) > 0) {
                $start = true;
                foreach ($scope as $groupid) {
                    // need to loop through the array, and not use implode, so we can sanitize the values
                    if (!$start) {
                        $scopeFilter .= " OR scope.groupid=" . intval($groupid);
                    } else {
                        $start = false;
                        $scopeFilter = " AND EXISTS(SELECT 1 FROM " . DBPRE . "formulize_entry_owner_groups AS scope WHERE (scope.entry_id=main.entry_id AND scope.fid=" . intval($fid) . ") AND (scope.groupid=" . intval($groupid);
                    }
                }
                $scopeFilter .= ")) ";
                // need two closing brackets for the exists statement and its where clause
            } else {
                // no valid entries found, so show no entries
                $scopeFilter = " AND main.entry_id<0 ";
            }
        } elseif ($scope) {
            // need to handle old "uid = X OR..." syntax
            $scopeFilter = " AND (" . str_replace("uid", "main.creation_uid", $scope) . ") ";
        }
        formulize_getElementMetaData("", false, $fid);
        // initialize the element metadata for this form...serious performance gain from this
        list($formFieldFilterMap, $whereClause, $orderByClause, $oneSideFilters, $otherPerGroupFilterJoins, $otherPerGroupFilterWhereClause) = formulize_parseFilter($filter, $andor, $linkformids, $fid, $frid);
        // ***********************
        // NOTE:  the oneSideFilters are divided into two sections, the AND filters and OR filters for a given form
        // These will need to be constructed differently if we are ever to support OR filters that are spread across forms.
        // Right now, oneSideFilters get rendered with all other filters for their form, which is fine if the OR filters all belong to the same form
        // But if there are OR filters on two different forms, then we will need to do some kind of much more complex handling of the OR filters, or else the count query, and the queries for calculations, will be screwed up
        // The proper approach to this would be to have the AND oneSideFilters divided by form, like now, but for the ORs, we would need to loop through all ORs on all forms at once, and concatenate them somehow, ie:
        // foreach($oneSideFilters as $thisOneSideFid=>$oneSideFilterData) {
        //   foreach($oneSideFilterData as $oneSideAndOr=>$thisOneSideFilter) {
        //     if($oneSideAndOr == "and") { // note, it's forced to lowercase in the parseFilter function
        //       // then add this filter to the exists/other construction/whatever for this particular form
        //     } else {
        //       // then add this filter to a more complex exists/other construction/whatever that contains all the ORs, grouped by form, with ORs in between them
        //       // ie, the final output would be like:  AND ( exists(select 1 from table1 where field11=x or field12=y) OR exists(select 1 from table2 where field21 LIKE '%t%') OR (exists(select 1 from table3 where field31 > 23) )
        //       // And this entire construction would be then added to queries, to account properly for all the OR operators that had been requested
        //     }
        //   }
        // }
        // NOTE: Oct 17 2011 -- since we are now splitting multiform queries into may different individual collections of entries, it may be possible to do what's suggested above more easily. However, we still need the full where clause at our disposal in the main query that gets the main form entry ids, or else we'll have an incorrect master list of entry ids to return.  :-(
        // ***********************
        if (isset($oneSideFilters[$fid])) {
            foreach ($oneSideFilters[$fid] as $thisOneSideFilter) {
                $mainFormWhereClause .= " AND ( {$thisOneSideFilter} ) ";
            }
        } else {
            $mainFormWhereClause = "";
        }
        if ($whereClause) {
            $whereClause = "AND {$whereClause}";
        }
        // create the per-group filters, if any, that apply to this user...only available when all XOOPS is invoked, not available when extract.php is being direct included
        global $xoopsDB;
        $perGroupFilter = "";
        $perGroupFiltersPerForms = array();
        // used with exists clauses and other per-form situations
        if ($xoopsDB) {
            $form_handler = xoops_getmodulehandler('forms', 'formulize');
            $perGroupFilter = $form_handler->getPerGroupFilterWhereClause($fid, "main");
            $perGroupFiltersPerForms[$fid] = $perGroupFilter;
            if ($frid) {
                foreach ($linkformids as $id => $thisLinkFid) {
                    $perGroupFiltersPerForms[$thisLinkFid] = $form_handler->getPerGroupFilterWhereClause($thisLinkFid, "f" . $id);
                }
            }
        }
        if ($frid) {
            $joinHandles = formulize_getJoinHandles(array(0 => $linkselfids, 1 => $linktargetids));
            // get the element handles for these elements, since we need those to properly construct the join clauses
            $newJoinText = "";
            // "new" variables initilized in each loop
            $joinTextIndex = array();
            $joinTextTableRef = array();
            $linkSelectIndex = array();
            $newexistsJoinText = "";
            $joinText = "";
            // not "new" variables persist (with .= operator)
            $existsJoinText = "";
            foreach ($linkformids as $id => $linkedFid) {
                // validate that the join conditions are valid...either both must have a value, or neither must have a value (match on user id)...otherwise the join is not possible
                if ($joinHandles[$linkselfids[$id]] and $joinHandles[$linktargetids[$id]] or $linkselfids[$id] == '' and $linktargetids[$id] == '') {
                    formulize_getElementMetaData("", false, $linkedFid);
                    // initialize the element metadata for this form...serious performance gain from this
                    $linkSelectIndex[$linkedFid] = "f{$id}.entry_id AS f" . $id . "_entry_id, f{$id}.creation_uid AS f" . $id . "_creation_uid, f{$id}.mod_uid AS f" . $id . "_mod_uid, f{$id}.creation_datetime AS f" . $id . "_creation_datetime, f{$id}.mod_datetime AS f" . $id . "_mod_datetime, f{$id}.*";
                    $linkSelect .= ", f{$id}.entry_id AS f" . $id . "_entry_id, f{$id}.creation_uid AS f" . $id . "_creation_uid, f{$id}.mod_uid AS f" . $id . "_mod_uid, f{$id}.creation_datetime AS f" . $id . "_creation_datetime, f{$id}.mod_datetime AS f" . $id . "_mod_datetime, f{$id}.*";
                    $joinType = isset($formFieldFilterMap[$linkedFid]) ? "INNER" : "LEFT";
                    $linkedFormObject = $form_handler->get($linkedFid);
                    $joinTextTableRef[$linkedFid] = DBPRE . "formulize_" . $linkedFormObject->getVar('form_handle') . " AS f{$id} ON ";
                    $joinText .= " {$joinType} JOIN " . DBPRE . "formulize_" . $linkedFormObject->getVar('form_handle') . " AS f{$id} ON";
                    // NOTE: we are aliasing the linked form tables to f$id where $id is the key of the position in the linked form metadata arrays where that form's info is stored
                    $newexistsJoinText = $existsJoinText ? " {$andor} " : "";
                    $newexistsJoinText .= " EXISTS(SELECT 1 FROM " . DBPRE . "formulize_" . $linkedFormObject->getVar('form_handle') . " AS f{$id} WHERE ";
                    // set this up also so we have it available for one to many/many to one calculations that require it
                    if ($linkcommonvalue[$id]) {
                        // common value
                        $newJoinText = " main.`" . $joinHandles[$linkselfids[$id]] . "`=f{$id}.`" . $joinHandles[$linktargetids[$id]] . "`";
                    } elseif ($linktargetids[$id]) {
                        // linked selectbox
                        if ($target_ele_value = formulize_isLinkedSelectBox($linktargetids[$id])) {
                            if ($target_ele_value[1]) {
                                // multiple values allowed
                                $newJoinText = " f{$id}.`" . $joinHandles[$linktargetids[$id]] . "` LIKE CONCAT('%,',main.entry_id,',%')";
                            } else {
                                // single value only
                                $newJoinText = " f{$id}.`" . $joinHandles[$linktargetids[$id]] . "` = main.entry_id";
                            }
                        } else {
                            $main_ele_value = formulize_isLinkedSelectBox($linkselfids[$id]);
                            //  we know it's linked because this is a linked selectbox join, we just need the ele_value properties
                            if ($main_ele_value[1]) {
                                // multiple values allowed
                                $newJoinText = " main.`" . $joinHandles[$linkselfids[$id]] . "` LIKE CONCAT('%,',f{$id}.entry_id,',%')";
                            } else {
                                // single value only
                                $newJoinText = " main.`" . $joinHandles[$linkselfids[$id]] . "` = f{$id}.entry_id";
                            }
                        }
                    } else {
                        // join by uid
                        $newJoinText = " main.creation_uid=f{$id}.creation_uid";
                    }
                    if (isset($perGroupFiltersPerForms[$linkedFid])) {
                        $newJoinText .= $perGroupFiltersPerForms[$linkedFid];
                    }
                    $joinTextIndex[$linkedFid] = $newJoinText;
                    $joinText .= $newJoinText;
                    if (count($oneSideFilters[$linkedFid]) > 0) {
                        // only setup the existsJoinText when there is a where clause that applies to this form...otherwise, we don't care, this form is not relevant to the query that the calculations will do (except maybe when the mainform is not the one-side form...but that's another story)
                        $existsJoinText .= $newexistsJoinText . $newJoinText;
                        foreach ($oneSideFilters[$linkedFid] as $thisOneSideFilter) {
                            $thisLinkedFidPerGroupFilter = isset($perGroupFiltersPerForms[$linkedFid]) ? $perGroupFiltersPerForms[$linkedFid] : "";
                            $existsJoinText .= " AND ( {$thisOneSideFilter} {$thisLinkedFidPerGroupFilter}) ";
                        }
                        $existsJoinText .= ") ";
                        // close the exists clause itself
                    }
                }
            }
        }
        // specify the join info for user table (depending whether there's a query on creator_email or not)
        $userJoinType = $formFieldFilterMap['creator_email'] ? "INNER" : "LEFT";
        $userJoinText = " {$userJoinType} JOIN " . DBPRE . "users AS usertable ON main.creation_uid=usertable.uid";
        $sortIsOnMain = true;
        if (!$orderByClause and $sortField) {
            if ($sortField == "creation_uid" or $sortField == "mod_uid" or $sortField == "creation_datetime" or $sortField == "mod_datetime") {
                $elementMetaData['id_form'] = $fid;
            } elseif ($sortField == "uid") {
                $sortField = "creation_uid";
                $elementMetaData['id_form'] = $fid;
            } elseif ($sortField == "proxyid") {
                $sortField = "mod_uid";
                $elementMetaData['id_form'] = $fid;
            } elseif ($sortField == "creation_date") {
                $sortField = "creation_datetime";
                $elementMetaData['id_form'] = $fid;
            } elseif ($sortField == "mod_date") {
                $sortField = "mod_datetime";
                $elementMetaData['id_form'] = $fid;
            } elseif ($sortField == "entry_id") {
                $sortField = "entry_id";
                $elementMetaData['id_form'] = $fid;
            } else {
                $elementMetaData = formulize_getElementMetaData($sortField, true);
                // need to get form that sort field is part of...
            }
            $sortFid = $elementMetaData['id_form'];
            if ($sortFid == $fid) {
                $sortFidAlias = "main";
            } else {
                $sortFidAlias = array_keys($linkformids, $sortFid);
                // position of this form in the linking relationships is important for identifying which form alias to use
                $sortFidAlias = "f" . $sortFidAlias[0];
                $sortIsOnMain = false;
            }
            $sortFieldMetaData = formulize_getElementMetaData($sortField, true);
            if ($sortFieldMetaData['ele_encrypt']) {
                $sortFieldFullValue = "AES_DECRYPT({$sortFidAlias}.`{$sortField}`, '" . getAESPassword() . "')";
                // sorts as text, which will screw up number fields
            } elseif (formulize_isLinkedSelectBox($sortField, true)) {
                $ele_value = unserialize($sortFieldMetaData['ele_value']);
                $boxproperties = explode("#*=:*", $ele_value[2]);
                $target_fid = $boxproperties[0];
                $target_element_handle = $boxproperties[1];
                $form_handler = xoops_getmodulehandler('forms', 'formulize');
                $targetFormObject = $form_handler->get($target_fid);
                // note you cannot sort by multi select boxes!
                $sortFieldFullValue = "(SELECT sourceSortForm.`" . $target_element_handle . "` FROM " . DBPRE . "formulize_" . $targetFormObject->getVar('form_handle') . " as sourceSortForm WHERE sourceSortForm.`entry_id` = " . $sortFidAlias . ".`" . $sortField . "`)";
            } else {
                $sortFieldFullValue = "{$sortFidAlias}.`{$sortField}`";
            }
            $orderByClause = " ORDER BY {$sortFieldFullValue} {$sortOrder} ";
        } elseif (!$orderByClause) {
            $orderByClause = "ORDER BY main.entry_id";
        }
        debug_memory("Before retrieving mainresults");
        //$beforeQueryTime = microtime_float();
        $countMasterResults = "SELECT COUNT(main.entry_id) FROM " . DBPRE . "formulize_" . $formObject->getVar('form_handle') . " AS main ";
        $countMasterResults .= "{$userJoinText} {$otherPerGroupFilterJoins} WHERE main.entry_id>0 {$mainFormWhereClause} {$scopeFilter} {$otherPerGroupFilterWhereClause} ";
        $countMasterResults .= $existsJoinText ? " AND ({$existsJoinText}) " : "";
        $countMasterResults .= isset($perGroupFiltersPerForms[$fid]) ? $perGroupFiltersPerForms[$fid] : "";
        if (isset($GLOBALS['formulize_getCountForPageNumbers'])) {
            // If there's an LOE Limit in place, check that we're not over it first
            global $formulize_LOE_limit;
            if ($countMasterResultsRes = $xoopsDB->query($countMasterResults)) {
                $countMasterResultsRow = $xoopsDB->fetchRow($countMasterResultsRes);
                if ($countMasterResultsRow[0] > $formulize_LOE_limit and $formulize_LOE_limit > 0 and !$forceQuery and !$limitClause) {
                    return $countMasterResultsRow[0];
                } else {
                    // if we're in a getData call from displayEntries, put the count in a special place for use in generating page numbers
                    $GLOBALS['formulize_countMasterResultsForPageNumbers'] = $countMasterResultsRow[0];
                }
            } else {
                exit("Error: could not count master results.<br>" . $xoopsDB->error() . "<br>SQL:{$countMasterResults}<br>");
            }
            unset($GLOBALS['formulize_getCountForPageNumbers']);
        }
        // now, if there's framework in effect, get the entry ids of the entries in the main form that match the criteria, so we can use a specific query for them instead of the order clause in the master query
        $limitByEntryId = "";
        $useAsSortSubQuery = "";
        if ($frid) {
            $limitByEntryId = " AND (";
            $entryIdQuery = str_replace("COUNT(main.entry_id)", "main.entry_id as main_entry_id", $countMasterResults);
            // don't count the entries, select their id numbers
            if (!$sortIsOnMain) {
                $sortFieldMetaData = formulize_getElementMetaData($sortField, true);
                $sortFormObject = $form_handler->get($sortFid);
                if ($sortFieldMetaData['ele_encrypt']) {
                    $useAsSortSubQuery = "(SELECT max(AES_DECRYPT(`{$sortField}`, '" . getAESPassword() . "')) as subsort FROM " . DBPRE . "formulize_" . $sortFormObject->getVar('form_handle') . " as {$sortFidAlias} WHERE " . $joinTextIndex[$sortFid] . " ORDER BY subsort {$sortOrder}) as usethissort";
                } else {
                    $useAsSortSubQuery = "(SELECT max(`{$sortField}`) as subsort FROM " . DBPRE . "formulize_" . $sortFormObject->getVar('form_handle') . " as {$sortFidAlias} WHERE " . $joinTextIndex[$sortFid] . " ORDER BY subsort {$sortOrder}) as usethissort";
                }
                $entryIdQuery = str_replace("SELECT main.entry_id as main_entry_id ", "SELECT {$useAsSortSubQuery}, main.entry_id as main_entry_id ", $entryIdQuery);
                // sorts as text which will screw up number fields
                $thisOrderByClause = " ORDER BY usethissort {$sortOrder} ";
            } else {
                $thisOrderByClause = $orderByClause;
            }
            $entryIdQuery .= " {$thisOrderByClause} {$limitClause}";
            $entryIdResult = $xoopsDB->query($entryIdQuery);
            $start = true;
            while ($entryIdValue = $xoopsDB->fetchArray($entryIdResult)) {
                $limitByEntryId .= !$start ? " OR " : "";
                $limitByEntryId .= "main.entry_id = " . $entryIdValue['main_entry_id'];
                $start = false;
            }
            $limitByEntryId .= ") ";
            if (!$start) {
                $limitClause = "";
                // nullify the existing limitClause since we don't want to use it in the actual query
            } else {
                $limitByEntryId = "";
            }
        }
        $selectClause = "";
        $sqlFilterElements = array();
        if ($filterElements) {
            // THIS IS HIGHLY EXPERIMENTAL...BECAUSE THE PROCESSING OF DATASETS RELIES RIGHT NOW ON METADATA BEING PRESENT AT THE FRONT OF EACH SET OF FIELDS, THERE IS FURTHER WORK REQUIRED TO MAKE THIS FUNCTION WITH THE CODE THAT PROCESSES ENTRIES
            //print_r( $filterElements );
            //print_r( $linkformids );
            foreach ($filterElements as $passedForm => $passedElements) {
                if ($passedForm == $fid) {
                    $formAlias = "main";
                } else {
                    $keys = array_keys($linkformids, $passedForm);
                    //print_r( $keys );
                    $formAlias = "f" . $keys[0];
                }
                foreach ($passedElements as $thisPassedElement) {
                    $sqlFilterElements[] = $formAlias . ".`" . formulize_db_escape($thisPassedElement) . "`";
                }
            }
        }
        if (count($sqlFilterElements) > 0) {
            $selectClause = implode(",", $sqlFilterElements);
        } else {
            $selectClause = "main.entry_id AS main_entry_id, main.creation_uid AS main_creation_uid, main.mod_uid AS main_mod_uid, main.creation_datetime AS main_creation_datetime, main.mod_datetime AS main_mod_datetime, main.* {$linkSelect}";
        }
        // if this is being done for gathering calculations, and the calculation is requested on the one side of a one to many/many to one relationship, then we will need to use different SQL to avoid duplicate values being returned by the database
        // note: when the main form is on the many side of the relationship, then we need to do something rather different...not sure what it is yet...the SQL as prepared is based on the calculation field and the main form being the one side (and so both are called main), but when field is on one side and main form is many side, then the aliases don't match, and scopefilter issues abound.
        // NOTE: Oct 17 2011 - the $oneSideSQL is also used when there are multiple linked subforms, since the exists structure is efficient compared to multiple joins
        $oneSideSQL = " FROM " . DBPRE . "formulize_" . $formObject->getVar('form_handle') . " AS main {$userJoinText} WHERE main.entry_id>0 {$scopeFilter} ";
        // does the mainFormWhereClause need to be used here too?  Needs to be tested. -- further note: Oct 17 2011 -- appears oneSideFilters[fid] is the same as the mainformwhereclause
        $oneSideSQL .= $existsJoinText ? " AND ({$existsJoinText}) " : "";
        if (count($oneSideFilters[$fid]) > 0) {
            foreach ($oneSideFilters[$fid] as $thisOneSideFilter) {
                $oneSideSQL .= " {$andor} ( {$thisOneSideFilter} ) ";
                // properly introduce these filters...need to move $andor to a higher level and put this inside ( ) ?? or maybe this just all gets redone if/when the OR bug is fixed (see big note up where oneSideFilters are first received from parseFilter function)
            }
        }
        $oneSideSQL .= isset($perGroupFiltersPerForms[$fid]) ? $perGroupFiltersPerForms[$fid] : "";
        $restOfTheSQL = " FROM " . DBPRE . "formulize_" . $formObject->getVar('form_handle') . " AS main {$userJoinText} {$joinText} {$otherPerGroupFilterJoins} WHERE main.entry_id>0 {$whereClause} {$scopeFilter} {$perGroupFilter} {$otherPerGroupFilterWhereClause} {$limitByEntryId} {$orderByClause} ";
        $restOfTheSQLForExport = " FROM " . DBPRE . "formulize_" . $formObject->getVar('form_handle') . " AS main {$userJoinText} {$joinText} {$otherPerGroupFilterJoins} WHERE main.entry_id>0 {$whereClause} {$scopeFilter} {$perGroupFilter} {$otherPerGroupFilterWhereClause} {$orderByClause} ";
        // don't use limitByEntryId since exports include all entries
        if (count($linkformids) > 1) {
            // AND $dummy == "never") { // when there is more than 1 joined form, we can get an exponential explosion of records returned, because SQL will give you all combinations of the joins
            if (!$sortIsOnMain) {
                $orderByToUse = " ORDER BY usethissort {$sortOrder} ";
                $useAsSortSubQuery = " @rownum:=@rownum+1, {$useAsSortSubQuery},";
                // need to add a counter as the first field, used as the master sorting key
            } else {
                $orderByToUse = $orderByClause;
                $useAsSortSubQuery = "  @rownum:=@rownum+1, ";
                // need to add a counter as the first field, used as the master sorting key
            }
            $oneSideSQLToUse = str_replace(" AS main {$userJoinText}", " AS main JOIN (SELECT @rownum := 0) as r {$userJoinText}", $oneSideSQL);
            // need to add the initialization of the rownum, which is what we use as the master sorting key
            $masterQuerySQL = "SELECT {$useAsSortSubQuery} main.entry_id {$oneSideSQLToUse} {$limitByEntryId} {$orderByToUse} ";
            $masterQuerySQLForExport = "SELECT {$useAsSortSubQuery} main.entry_id {$oneSideSQLToUse} {$orderByToUse} ";
            // no limit by entry id, since all entries should be included in exports
            if (!$resultOnly) {
                // so let's build a temp table with the unique entry ids in the forms that we care about, and then query each linked form separately for its records, so that we end up processing as few result rows as possible
                $masterQuerySQL = "INSERT INTO " . DBPRE . "formulize_temp_extract_REPLACEWITHTIMESTAMP {$masterQuerySQL} ";
                $masterQuerySQLForExport = "INSERT INTO " . DBPRE . "formulize_temp_extract_REPLACEWITHTIMESTAMP {$masterQuerySQLForExport} ";
            }
        } else {
            $masterQuerySQL = "SELECT {$selectClause}, usertable.email AS main_email, usertable.user_viewemail AS main_user_viewemail {$restOfTheSQL} ";
            $masterQuerySQLForExport = "SELECT {$selectClause}, usertable.email AS main_email, usertable.user_viewemail AS main_user_viewemail {$restOfTheSQLForExport} ";
        }
        $GLOBALS['formulize_queryForCalcs'] = " FROM " . DBPRE . "formulize_" . $formObject->getVar('form_handle') . " AS main {$userJoinText} {$joinText} WHERE main.entry_id>0  {$whereClause} {$scopeFilter} ";
        $GLOBALS['formulize_queryForCalcs'] .= isset($perGroupFiltersPerForms[$fid]) ? $perGroupFiltersPerForms[$fid] : "";
        $GLOBALS['formulize_queryForOneSideCalcs'] = $oneSideSQL;
        if ($GLOBALS['formulize_returnAfterSettingBaseQuery']) {
            return true;
        }
        // if we are only setting up calculations, then return now that the base query is built
        $sortIsOnMainFlag = $sortIsOnMain ? 1 : 0;
        // need to include the query first, so the SELECT or INSERT is the first thing in the string, so we catch it properly when coming back through the export process
        $GLOBALS['formulize_queryForExport'] = $masterQuerySQLForExport . " -- SEPARATOR FOR EXPORT QUERIES -- " . $sortIsOnMainFlag;
        // "$selectClauseToUse FROM " . DBPRE . "formulize_" . $formObject->getVar('form_handle') . " AS main $userJoinText $joinText $otherPerGroupFilterJoins WHERE main.entry_id>0 $whereClause $scopeFilter $perGroupFilter $otherPerGroupFilterWhereClause $limitByEntryId $orderByClause $limitClause";
    } else {
        // end of if the filter has a SELECT in it
        if (strstr($filter, " -- SEPARATOR FOR EXPORT QUERIES -- ")) {
            $exportOverrideQueries = explode(" -- SEPARATOR FOR EXPORT QUERIES -- ", $filter);
            $masterQuerySQL = $exportOverrideQueries[0];
            $sortIsOnMain = $exportOverrideQueries[1];
        } else {
            $masterQuerySQL = $filter;
            // need to split this based on some separator, because export ends up passing in a series of statements
        }
    }
    // after the export query has been generated, then let's put the limit on:
    $masterQuerySQL .= $limitClause;
    /*global $xoopsUser;
      if($xoopsUser->getVar('uid') == 4613) {
           $queryTime = $afterQueryTime - $beforeQueryTime;
           print "Query time: " . $queryTime . "<br>";
      }*/
    debug_memory("After retrieving mainresults");
    // Debug Code
    //global $xoopsUser;
    //if($xoopsUser->getVar('uid') == 1) {
    //     print "<br>Count query: $countMasterResults<br><br>";
    //     print "Master query: $masterQuerySQL<br>";
    //}
    formulize_benchmark("Before query");
    if (count($linkformids) > 1) {
        // AND $dummy=="never") { // when there is more than 1 joined form, we can get an exponential explosion of records returned, because SQL will give you all combinations of the joins, so we create a series of queries that will each handle the main form plus one of the linked forms, then we put all the data together into a single result set below
        if ($resultOnly) {
            $masterQueryRes = $xoopsDB->query($masterQuerySQL);
        } else {
            $timestamp = str_replace(".", "", microtime(true));
            if (!$sortIsOnMain) {
                $creatTableSQL = "CREATE TABLE " . DBPRE . "formulize_temp_extract_{$timestamp} ( `mastersort` BIGINT(11), `throwaway_sort_values` BIGINT(11), `entry_id` BIGINT(11), PRIMARY KEY (`mastersort`), INDEX i_entry_id (`entry_id`) ) ENGINE=MyISAM;";
                // when the sort is not on the main form, then we are including a special field in the select statement that we sort it by, so that the order is correct, and so it has to have a place to get inserted here
            } else {
                $creatTableSQL = "CREATE TABLE " . DBPRE . "formulize_temp_extract_{$timestamp} ( `mastersort` BIGINT(11), `entry_id` BIGINT(11), PRIMARY KEY (`mastersort`), INDEX i_entry_id (`entry_id`) ) ENGINE=MyISAM;";
            }
            $createTableRes = $xoopsDB->queryF($creatTableSQL);
            $gatherIdsRes = $xoopsDB->queryF(str_replace("REPLACEWITHTIMESTAMP", $timestamp, $masterQuerySQL));
            $linkQueryRes = array();
            if (isset($exportOverrideQueries[2])) {
                for ($i = 2; $i < count($exportOverrideQueries); $i++) {
                    $sql = str_replace("REPLACEWITHTIMESTAMP", $timestamp, $exportOverrideQueries[$i]);
                    $linkQueryRes[] = $xoopsDB->query($sql);
                }
            } else {
                // FURTHER OPTIMIZATIONS ARE POSSIBLE HERE...WE COULD NOT INCLUDE THE MAIN FORM AGAIN IN ALL THE SELECTS, THAT WOULD IMPROVE THE PROCESSING TIME A BIT, BUT WE WOULD HAVE TO CAREFULLY REFACTOR MORE OF THE LOOPING CODE BELOW THAT PARSES THE ENTRIES, BECAUSE RIGHT NOW IT'S ASSUMING THE FULL MAIN ENTRY IS PRESENT.  AT LEAST THE MAIN ENTRY ID WOULD NEED TO STILL BE USED, SINCE WE USE THAT TO SYNCH UP ALL THE ENTRIES FROM THE OTHER FORMS.
                foreach ($linkformids as $linkId => $thisLinkFid) {
                    $linkQuery = "SELECT\r\n   main.entry_id AS main_entry_id, main.creation_uid AS main_creation_uid, main.mod_uid AS main_mod_uid, main.creation_datetime AS main_creation_datetime, main.mod_datetime AS main_mod_datetime, main.*, " . $linkSelectIndex[$thisLinkFid] . ", usertable.email AS main_email, usertable.user_viewemail AS main_user_viewemail FROM " . DBPRE . "formulize_" . $formObject->getVar('form_handle') . " AS main\r\n   LEFT JOIN " . DBPRE . "users AS usertable ON main.creation_uid=usertable.uid\r\n   LEFT JOIN " . $joinTextTableRef[$thisLinkFid] . $joinTextIndex[$thisLinkFid] . "\r\n   INNER JOIN " . DBPRE . "formulize_temp_extract_REPLACEWITHTIMESTAMP as sort_and_limit_table ON main.entry_id = sort_and_limit_table.entry_id ";
                    if (isset($oneSideFilters[$thisLinkFid]) and is_array($oneSideFilters[$thisLinkFid])) {
                        $start = true;
                        foreach ($oneSideFilters[$thisLinkFid] as $thisOneSideFilter) {
                            if (!$start) {
                                $linkQuery .= " AND ( {$thisOneSideFilter} ) ";
                            } else {
                                $linkQuery .= " WHERE ( {$thisOneSideFilter} ) ";
                                $start = false;
                            }
                        }
                    }
                    $linkQuery .= " ORDER BY sort_and_limit_table.mastersort";
                    $linkQueryRes[] = $xoopsDB->query(str_replace("REPLACEWITHTIMESTAMP", $timestamp, $linkQuery));
                    $GLOBALS['formulize_queryForExport'] .= " -- SEPARATOR FOR EXPORT QUERIES -- " . $linkQuery;
                }
            }
            $dropRes = $xoopsDB->queryF("DROP TABLE " . DBPRE . "formulize_temp_extract_{$timestamp}");
        }
    } else {
        $masterQueryRes = $xoopsDB->query($masterQuerySQL);
    }
    if ($resultOnly) {
        if ($masterQueryRes) {
            if ($xoopsDB->getRowsNum($masterQueryRes) > 0) {
                return $masterQueryRes;
            } else {
                return false;
            }
        }
    }
    formulize_benchmark("After query");
    // need to calculate the derived value metadata
    // 1. figure out which fields in the included forms have derived values
    // 2. setup the metadata for those fields, according to the order they appear
    // -- metadata should be: formhandle (title or framework formhandle), formula, handle (element handle or framework handle)
    // 3. call the derived value function from inside the main loop
    $linkFormIdsFilter = "";
    if ($frid) {
        $linkFormIdsFilter = (is_array($linkformids) and count($linkformids) > 0) ? " OR t1.id_form IN (" . implode(",", $linkformids) . ") " : "";
    }
    $sql = "SELECT t1.ele_value, t2.desc_form, t1.ele_handle, t2.id_form FROM " . DBPRE . "formulize as t1, " . DBPRE . "formulize_id as t2 WHERE t1.ele_type='derived' AND (t1.id_form='{$fid}' {$linkFormIdsFilter} ) AND t1.id_form=t2.id_form ORDER BY t1.ele_order";
    $derivedFieldMetadata = array();
    if ($res = $xoopsDB->query($sql)) {
        if ($xoopsDB->getRowsNum($res) > 0) {
            $multipleIndexer = array();
            while ($row = $xoopsDB->fetchRow($res)) {
                $ele_value = unserialize($row[0]);
                // derived fields have ele_value as an array with only one element (that was done to future proof the data model, so we could add other things to ele_value if necessary)
                if (!isset($multipleIndexer[$row[1]])) {
                    $multipleIndexer[$row[1]] = 0;
                }
                $derivedFieldMetadata[$row[1]][$multipleIndexer[$row[1]]]['formula'] = $ele_value[0];
                // use row[1] (the form handle) as the key, so we can eliminate some looping later on
                $derivedFieldMetadata[$row[1]][$multipleIndexer[$row[1]]]['handle'] = $row[2];
                $derivedFieldMetadata[$row[1]][$multipleIndexer[$row[1]]]['form_id'] = $row[3];
                $multipleIndexer[$row[1]]++;
            }
        }
    } else {
        print "Error: could not check to see if there were derived value elements in one or more forms.  SQL:<br>{$sql}";
    }
    if (count($linkformids) > 1) {
        // AND $dummy == "never") {
        // this is a refactoring of the original code that is in the else part of this structure.
        // it's virtually the same, except for the part that sets the $masterIndexer, since we will need to reuse masterindex positions when parsing subsequent queries, so we don't just increment the $masterIndexer
        // Also, derived value formulas are processed all at the end, because until we've parsed the last query, we don't have a complete set of data for any record in the masterResults array
        // once this is proven stable, we should refactor this into a function and have a more unified/common way of parsing query results, but for now we'll keep it split out since we know the old way works intact in its current form and this new one is a little bit experimental
        // we need to loop through all the query results that were generated above, and gradually build up the same full results array out of them
        // then we also need to loop through all main entries one more time once we're done building, and set all the derived values
        // this is done to avoid an exponential explosion of results in the SQL, and instead we only have a linear progression of results to parse
        $masterResults = array();
        $masterIndexer = -1;
        $writtenMains = array();
        $masterQueryArrayIndex = array();
        foreach ($linkQueryRes as $thisRes) {
            // loop through the found data and create the dataset array in "getData" format
            $prevFieldNotMeta = true;
            $prevFormAlias = "";
            $prevMainId = "";
            while ($masterQueryArray = $xoopsDB->fetchArray($thisRes)) {
                foreach ($masterQueryArray as $field => $value) {
                    if ($field == "entry_id" or $field == "creation_uid" or $field == "mod_uid" or $field == "creation_datetime" or $field == "mod_datetime" or $field == "main_email" or $field == "main_user_viewemail") {
                        continue;
                    }
                    // ignore those plain fields, since we can only work with the ones that are properly aliased to their respective tables.  More details....Must refer to metadata fields by aliases only!  since * is included in SQL syntax, fetch_assoc will return plain column names from all forms with the values from those columns.....Also want to ignore the email fields, since the fact they're prefixed with "main" can throwoff the calculation of which entry we're currently writing
                    if (strstr($field, "creation_uid") or strstr($field, "creation_datetime") or strstr($field, "mod_uid") or strstr($field, "mod_datetime") or strstr($field, "entry_id")) {
                        // dealing with a new metadata field
                        $fieldNameParts = explode("_", $field);
                        // We account for a mainform entry appearing multiple times in the list, because when there are multiple entries in a subform, and SQL returns one row per subform,  we need to not change the main form and internal record until we pass to a new mainform entry
                        if ($prevFieldNotMeta) {
                            // only do once for each form
                            $curFormId = $fieldNameParts[0] == "main" ? $fid : $linkformids[substr($fieldNameParts[0], 1)];
                            // the table aliases are based on the keys of the linked forms in the linkformids array, so if we get the number out of the table alias, that key will give us the form id of the linked form as stored in the linkformids array
                            $prevFormAlias = $curFormAlias;
                            $curFormAlias = $fieldNameParts[0];
                            if ($prevFormAlias == "main") {
                                // if we just finished up a main form entry, then log that
                                $writtenMains[$prevMainId] = true;
                            }
                            //print "curFormAlias: $curFormAlias<br>prevMainId: $prevMainId<br>current main id: ". $masterQueryArray['main_entry_id'] . "<br><br>";
                            if ($curFormAlias == "main" and $prevMainId != $masterQueryArray['main_entry_id']) {
                                if ($writtenMains[$masterQueryArray['main_entry_id']]) {
                                    $masterIndexer = $masterQueryArrayIndex[$masterQueryArray['main_entry_id']];
                                    // use the master index value for this main entry id if we've already logged it
                                } else {
                                    $masterIndexer = count($masterResults);
                                    // use the next available number for the master indexer
                                    $masterQueryArrayIndex[$masterQueryArray['main_entry_id']] = $masterIndexer;
                                    // log it so we can reuse it for this entry when it comes up in another query
                                }
                                $prevMainId = $masterQueryArray['main_entry_id'];
                                // if the current form is a main, then store it's ID for use later when we're on a new form
                            }
                        }
                        $prevFieldNotMeta = false;
                        // setup handles to use for metadata fields
                        if ($curFormAlias == "main") {
                            if ($field == "main_creation_uid" or $field == "main_mod_uid" or $field == "main_creation_datetime" or $field == "main_mod_datetime" or $field == "main_entry_id") {
                                $elementHandle = $fieldNameParts[1] . "_" . $fieldNameParts[2];
                            }
                        } else {
                            continue;
                            // do not include metadata from the linked forms, or anything else (such as email, etc)
                        }
                    } elseif (!strstr($field, "main_email") and !strstr($field, "main_user_viewemail")) {
                        // dealing with a regular element field
                        $prevFieldNotMeta = true;
                        $elementHandle = $field;
                    } else {
                        // it's some other field...
                        continue;
                    }
                    // Check to see if this is a main entry that has already been catalogued, and if so, then skip it
                    if ($curFormAlias == "main" and isset($writtenMains[$masterQueryArray['main_entry_id']])) {
                        continue;
                    }
                    //print "<br>$curFormAlias - $field: $value<br>"; // debug line
                    formulize_benchmark("preping value...");
                    $valueArray = prepvalues($value, $elementHandle, $masterQueryArray[$curFormAlias . "_entry_id"]);
                    // note...metadata fields must not be in an array for compatibility with the 'display' function...not all values returned will actually be arrays, but if there are multiple values in a cell, then those will be arrays
                    formulize_benchmark("done preping value");
                    $masterResults[$masterIndexer][getFormTitle($curFormId)][$masterQueryArray[$curFormAlias . "_entry_id"]][$elementHandle] = $valueArray;
                    if ($elementHandle == "creation_uid" or $elementHandle == "mod_uid" or $elementHandle == "creation_datetime" or $elementHandle == "mod_datetime" or $elementHandle == "entry_id") {
                        // add in the creator_email when we have done the creation_uid
                        if ($elementHandle == "creation_uid") {
                            if (!isset($is_webmaster)) {
                                global $xoopsUser;
                                if (is_object($xoopsUser)) {
                                    // determine if the user is a webmaster, in order to control whether the e-mail addresses should be shown or not
                                    $is_webmaster = in_array(XOOPS_GROUP_ADMIN, $xoopsUser->getGroups()) ? true : false;
                                    $gperm_handler =& xoops_gethandler('groupperm');
                                    $view_private_fields = $gperm_handler->checkRight("view_private_elements", $fid, $xoopsUser->getGroups(), getFormulizeModId());
                                    $this_userid = $xoopsUser->getVar('uid');
                                } else {
                                    $view_private_fields = false;
                                    $is_webmaster = false;
                                    $this_userid = 0;
                                }
                            }
                            if ($is_webmaster or $view_private_fields or $masterQueryArray['main_user_viewemail'] or $masterQueryArray['main_creation_uid'] == $this_userid) {
                                $masterResults[$masterIndexer][getFormTitle($curFormId)][$masterQueryArray[$curFormAlias . "_entry_id"]]['creator_email'] = $masterQueryArray['main_email'];
                            } else {
                                $masterResults[$masterIndexer][getFormTitle($curFormId)][$masterQueryArray[$curFormAlias . "_entry_id"]]['creator_email'] = "";
                            }
                        }
                        // for backwards compatibility, replicate the old metadata fields
                        switch ($elementHandle) {
                            case "creation_uid":
                                $old_meta = "uid";
                                break;
                            case "mod_uid":
                                $old_meta = "proxyid";
                                break;
                            case "creation_datetime":
                                $old_meta = "creation_date";
                                break;
                            case "mod_datetime":
                                $old_meta = "mod_date";
                                break;
                        }
                        $masterResults[$masterIndexer][getFormTitle($curFormId)][$masterQueryArray[$curFormAlias . "_entry_id"]][$old_meta] = $valueArray;
                    }
                }
                // end of foreach field loop within a record
            }
            // end of main while loop for all records
        }
        // end of foreach linked query result
        if (count($derivedFieldMetadata) > 0 and $masterIndexer > -1) {
            // if there is derived value info for this data set and we have started to create values...need to do this one more time for the last value that we would have gathered data for...
            foreach ($masterResults as $masterIndex => $thisRecord) {
                $masterResults[$masterIndex] = formulize_calcDerivedColumns($thisRecord, $derivedFieldMetadata, $frid, $fid);
            }
        }
    } else {
        // loop through the found data and create the dataset array in "getData" format
        $prevFieldNotMeta = true;
        $masterIndexer = -1;
        $writtenMains = array();
        $prevFormAlias = "";
        $prevMainId = "";
        //formulize_benchmark("About to prepare results.");
        while ($masterQueryArray = $xoopsDB->fetchArray($masterQueryRes)) {
            set_time_limit(120);
            //formulize_benchmark("Starting to process one entry.");
            foreach ($masterQueryArray as $field => $value) {
                //formulize_benchmark("Starting to process one value");
                if ($field == "entry_id" or $field == "creation_uid" or $field == "mod_uid" or $field == "creation_datetime" or $field == "mod_datetime" or $field == "main_email" or $field == "main_user_viewemail") {
                    continue;
                }
                // ignore those plain fields, since we can only work with the ones that are properly aliased to their respective tables.  More details....Must refer to metadata fields by aliases only!  since * is included in SQL syntax, fetch_assoc will return plain column names from all forms with the values from those columns.....Also want to ignore the email fields, since the fact they're prefixed with "main" can throwoff the calculation of which entry we're currently writing
                if (strstr($field, "creation_uid") or strstr($field, "creation_datetime") or strstr($field, "mod_uid") or strstr($field, "mod_datetime") or strstr($field, "entry_id")) {
                    //formulize_benchmark("Starting to process metadata");
                    // dealing with a new metadata field
                    $fieldNameParts = explode("_", $field);
                    // We account for a mainform entry appearing multiple times in the list, because when there are multiple entries in a subform, and SQL returns one row per subform,  we need to not change the main form and internal record until we pass to a new mainform entry
                    if ($prevFieldNotMeta) {
                        // only do once for each form
                        $curFormId = $fieldNameParts[0] == "main" ? $fid : $linkformids[substr($fieldNameParts[0], 1)];
                        // the table aliases are based on the keys of the linked forms in the linkformids array, so if we get the number out of the table alias, that key will give us the form id of the linked form as stored in the linkformids array
                        $prevFormAlias = $curFormAlias;
                        $curFormAlias = $fieldNameParts[0];
                        if ($prevFormAlias == "main") {
                            // if we just finished up a main form entry, then log that
                            $writtenMains[$prevMainId] = true;
                        }
                        //print "curFormAlias: $curFormAlias<br>prevMainId: $prevMainId<br>current main id: ". $masterQueryArray['main_entry_id'] . "<br><br>";
                        if ($curFormAlias == "main" and $prevMainId != $masterQueryArray['main_entry_id']) {
                            //formulize_benchmark("Done entry, ready to do derived values.");
                            // now that the entire entry has been processed, do the derived values for it
                            if (count($derivedFieldMetadata) > 0 and $masterIndexer > -1) {
                                // if there is derived value info for this data set and we have started to create values...
                                //print "fid: $fid<br>";
                                //print "frid: $frid<br>";
                                formulize_benchmark("before doing derived...");
                                $masterResults[$masterIndexer] = formulize_calcDerivedColumns($masterResults[$masterIndexer], $derivedFieldMetadata, $frid, $fid);
                                formulize_benchmark("after doing derived");
                            }
                            $masterIndexer++;
                            // If this is a new main entry, then increment the masterIndexer, since the masterIndexer is used to uniquely identify each main entry
                            $prevMainId = $masterQueryArray['main_entry_id'];
                            // if the current form is a main, then store it's ID for use later when we're on a new form
                        }
                    }
                    $prevFieldNotMeta = false;
                    // setup handles to use for metadata fields
                    if ($curFormAlias == "main") {
                        if ($field == "main_creation_uid" or $field == "main_mod_uid" or $field == "main_creation_datetime" or $field == "main_mod_datetime" or $field == "main_entry_id") {
                            $elementHandle = $fieldNameParts[1] . "_" . $fieldNameParts[2];
                        } else {
                            continue;
                            // do not include main_entry_id as a value in the array...though it should not be in here anyway now that we're checking with strstr for metadata field names above
                        }
                    } else {
                        continue;
                        // do not include metadata from the linked forms, or anything else (such as email, etc)
                    }
                } elseif (!strstr($field, "main_email") and !strstr($field, "main_user_viewemail")) {
                    // dealing with a regular element field
                    $prevFieldNotMeta = true;
                    $elementHandle = $field;
                } else {
                    // it's some other field
                    continue;
                }
                // Check to see if this is a main entry that has already been catalogued, and if so, then skip it
                if ($curFormAlias == "main" and isset($writtenMains[$masterQueryArray['main_entry_id']])) {
                    continue;
                }
                //print "<br>$curFormAlias - $field: $value<br>"; // debug line
                formulize_benchmark("preping value...");
                $valueArray = prepvalues($value, $elementHandle, $masterQueryArray[$curFormAlias . "_entry_id"]);
                // note...metadata fields must not be in an array for compatibility with the 'display' function...not all values returned will actually be arrays, but if there are multiple values in a cell, then those will be arrays
                formulize_benchmark("done preping value");
                $masterResults[$masterIndexer][getFormTitle($curFormId)][$masterQueryArray[$curFormAlias . "_entry_id"]][$elementHandle] = $valueArray;
                if ($elementHandle == "creation_uid" or $elementHandle == "mod_uid" or $elementHandle == "creation_datetime" or $elementHandle == "mod_datetime" or $elementHandle == "entry_id") {
                    // add in the creator_email when we have done the creation_uid
                    if ($elementHandle == "creation_uid") {
                        if (!isset($is_webmaster)) {
                            global $xoopsUser;
                            if (is_object($xoopsUser)) {
                                // determine if the user is a webmaster, in order to control whether the e-mail addresses should be shown or not
                                $is_webmaster = in_array(XOOPS_GROUP_ADMIN, $xoopsUser->getGroups()) ? true : false;
                                $gperm_handler =& xoops_gethandler('groupperm');
                                $view_private_fields = $gperm_handler->checkRight("view_private_elements", $fid, $xoopsUser->getGroups(), getFormulizeModId());
                                $this_userid = $xoopsUser->getVar('uid');
                            } else {
                                $view_private_fields = false;
                                $is_webmaster = false;
                                $this_userid = 0;
                            }
                        }
                        if ($is_webmaster or $view_private_fields or $masterQueryArray['main_user_viewemail'] or $masterQueryArray['main_creation_uid'] == $this_userid) {
                            $masterResults[$masterIndexer][getFormTitle($curFormId)][$masterQueryArray[$curFormAlias . "_entry_id"]]['creator_email'] = $masterQueryArray['main_email'];
                        } else {
                            $masterResults[$masterIndexer][getFormTitle($curFormId)][$masterQueryArray[$curFormAlias . "_entry_id"]]['creator_email'] = "";
                        }
                    }
                    // for backwards compatibility, replicate the old metadata fields
                    switch ($elementHandle) {
                        case "creation_uid":
                            $old_meta = "uid";
                            break;
                        case "mod_uid":
                            $old_meta = "proxyid";
                            break;
                        case "creation_datetime":
                            $old_meta = "creation_date";
                            break;
                        case "mod_datetime":
                            $old_meta = "mod_date";
                            break;
                    }
                    $masterResults[$masterIndexer][getFormTitle($curFormId)][$masterQueryArray[$curFormAlias . "_entry_id"]][$old_meta] = $valueArray;
                }
            }
            // end of foreach field loop within a record
        }
        // end of main while loop for all records
        if (count($derivedFieldMetadata) > 0 and $masterIndexer > -1) {
            // if there is derived value info for this data set and we have started to create values...need to do this one more time for the last value that we would have gathered data for...
            //print "fid: $fid<br>";
            //print "frid: $frid<br>";
            $masterResults[$masterIndexer] = formulize_calcDerivedColumns($masterResults[$masterIndexer], $derivedFieldMetadata, $frid, $fid);
        }
    }
    // end if if there's more the 1 linked fid
    return $masterResults;
}
function drawSubLinks($subform_id, $sub_entries, $uid, $groups, $frid, $mid, $fid, $entry, $customCaption = "", $customElements = "", $defaultblanks = 0, $showViewButtons = 1, $captionsForHeadings = 0, $overrideOwnerOfNewEntries = "", $mainFormOwner = 0, $hideaddentries = "", $subformConditions = null, $subformElementId = 0, $rowsOrForms = 'row', $addEntriesText = _formulize_ADD_ENTRIES, $subform_element_object = null)
{
    $nestedSubform = false;
    if (isset($GLOBALS['formulize_inlineSubformFrid'])) {
        $frid = $GLOBALS['formulize_inlineSubformFrid'];
        $nestedSubform = true;
    }
    $member_handler = xoops_gethandler('member');
    $gperm_handler = xoops_gethandler('groupperm');
    $addEntriesText = $addEntriesText ? $addEntriesText : _formulize_ADD_ENTRIES;
    global $xoopsDB, $nosubforms;
    $GLOBALS['framework'] = $frid;
    $form_handler = xoops_getmodulehandler('forms', 'formulize');
    // limit the sub_entries array to just the entries that match the conditions, if any
    if (is_array($subformConditions) and is_array($sub_entries[$subform_id])) {
        list($conditionsFilter, $conditionsFilterOOM, $curlyBracketFormFrom) = buildConditionsFilterSQL($subformConditions, $subform_id, $entry, $mainFormOwner, $fid);
        // pass in mainFormOwner as the comparison ID for evaluating {USER} so that the included entries are consistent when an admin looks at a set of entries made by someone else.
        $subformObject = $form_handler->get($subform_id);
        $sql = "SELECT entry_id FROM " . $xoopsDB->prefix("formulize_" . $subformObject->getVar('form_handle')) . "{$curlyBracketFormFrom} WHERE entry_id IN (" . implode(", ", $sub_entries[$subform_id]) . ") {$conditionsFilter} {$conditionsFilterOOM}";
        $sub_entries[$subform_id] = array();
        if ($res = $xoopsDB->query($sql)) {
            while ($array = $xoopsDB->fetchArray($res)) {
                $sub_entries[$subform_id][] = $array['entry_id'];
            }
        }
    }
    include_once XOOPS_ROOT_PATH . "/modules/formulize/include/extract.php";
    $target_sub_to_use = (isset($_POST['target_sub']) and $_POST['target_sub'] != 0) ? $_POST['target_sub'] : $subform_id;
    $elementq = q("SELECT fl_key1, fl_key2, fl_common_value, fl_form2_id FROM " . $xoopsDB->prefix("formulize_framework_links") . " WHERE fl_frame_id=" . intval($frid) . " AND fl_form2_id=" . intval($fid) . " AND fl_form1_id=" . intval($target_sub_to_use));
    // element_to_write is used below in writing results of "add x entries" clicks, plus it is used for defaultblanks on first drawing blank entries, so we need to get this outside of the saving routine
    if (count($elementq) > 0) {
        $element_to_write = $elementq[0]['fl_key1'];
        $value_source = $elementq[0]['fl_key2'];
        $value_source_form = $elementq[0]['fl_form2_id'];
    } else {
        $elementq = q("SELECT fl_key2, fl_key1, fl_common_value, fl_form1_id FROM " . $xoopsDB->prefix("formulize_framework_links") . " WHERE fl_frame_id=" . intval($frid) . " AND fl_form1_id=" . intval($fid) . " AND fl_form2_id=" . intval($target_sub_to_use));
        $element_to_write = $elementq[0]['fl_key2'];
        $value_source = $elementq[0]['fl_key1'];
        $value_source_form = $elementq[0]['fl_form1_id'];
    }
    if (0 == strlen($element_to_write)) {
        error_log("Relationship {$frid} for subform {$subform_id} on form {$fid} is invalid.");
        $to_return = array("c1" => "", "c2" => "", "sigle" => "");
        global $xoopsUser;
        if (is_object($xoopsUser) and in_array(XOOPS_GROUP_ADMIN, $xoopsUser->getGroups())) {
            if (0 == $frid) {
                $to_return['single'] = "This subform cannot be shown because no relationship is active.";
            } else {
                $to_return['single'] = "This subform cannot be shown because relationship {$frid} for subform " . "{$subform_id} on form {$fid} is invalid.";
            }
        }
        return $to_return;
    }
    // check for adding of a sub entry, and handle accordingly -- added September 4 2006
    static $subformInstance;
    $subformInstance = !isset($subformInstance) ? 100 : $subformInstance;
    $subformInstance++;
    if ($_POST['target_sub'] and $_POST['target_sub'] == $subform_id and $_POST['target_sub_instance'] == $subformElementId . $subformInstance) {
        // important we only do this on the run through for that particular sub form (hence target_sub == sfid), and also only for the specific instance of this subform on the page too, since not all entries may apply to all subform instances any longer with conditions in effect now
        // need to handle things differently depending on whether it's a common value or a linked selectbox type of link
        // uid links need to result in a "new" value in the displayElement boxes -- odd things will happen if people start adding linked values to entries that aren't theirs!
        if ($element_to_write != 0) {
            if ($elementq[0]['fl_common_value']) {
                // grab the value from the parent element -- assume that it is a textbox of some kind!
                if (isset($_POST['de_' . $value_source_form . '_' . $entry . '_' . $value_source])) {
                    $value_to_write = $_POST['de_' . $value_source_form . '_' . $entry . '_' . $value_source];
                } else {
                    // get this entry and see what the source value is
                    $data_handler = new formulizeDataHandler($value_source_form);
                    $value_to_write = $data_handler->getElementValueInEntry($entry, $value_source);
                }
            } else {
                $value_to_write = $entry;
            }
            $sub_entry_new = "";
            for ($i = 0; $i < $_POST['numsubents']; $i++) {
                // actually goahead and create the requested number of new sub entries...start with the key field, and then do all textboxes with defaults too...
                //$subEntWritten = writeElementValue($_POST['target_sub'], $element_to_write, "new", $value_to_write, "", "", true); // Last param is override that allows direct writing to linked selectboxes if we have prepped the value first!
                if ($overrideOwnerOfNewEntries) {
                    $creation_user_touse = $mainFormOwner;
                } else {
                    $creation_user_touse = "";
                }
                $subEntWritten = writeElementValue($_POST['target_sub'], $element_to_write, "new", $value_to_write, $creation_user_touse, "", true);
                // Last param is override that allows direct writing to linked selectboxes if we have prepped the value first!
                $element_handler = xoops_getmodulehandler('elements', 'formulize');
                if (!isset($elementsForDefaults)) {
                    $criteria = new CriteriaCompo();
                    $criteria->add(new Criteria('ele_type', 'text'), 'OR');
                    $criteria->add(new Criteria('ele_type', 'textarea'), 'OR');
                    $criteria->add(new Criteria('ele_type', 'date'), 'OR');
                    $criteria->add(new Criteria('ele_type', 'radio'), 'OR');
                    $elementsForDefaults = $element_handler->getObjects($criteria, $_POST['target_sub']);
                    // get all the text or textarea elements in the form
                }
                foreach ($elementsForDefaults as $thisDefaultEle) {
                    // need to write in any default values for any text boxes or text areas that are in the subform.  Perhaps other elements could be included too, but that would take too much work right now. (March 9 2009)
                    $defaultTextToWrite = "";
                    $ele_value_for_default = $thisDefaultEle->getVar('ele_value');
                    switch ($thisDefaultEle->getVar('ele_type')) {
                        case "text":
                            $defaultTextToWrite = getTextboxDefault($ele_value_for_default[2], $_POST['target_sub'], $subEntWritten);
                            // position 2 is default value for text boxes
                            break;
                        case "textarea":
                            $defaultTextToWrite = getTextboxDefault($ele_value_for_default[0], $_POST['target_sub'], $subEntWritten);
                            // position 0 is default value for text boxes
                            break;
                        case "date":
                            $defaultTextToWrite = getDateElementDefault($ele_value_for_default[0]);
                            if (false === $defaultTextToWrite) {
                                $defaultTextToWrite = "";
                            } else {
                                $defaultTextToWrite = date("c", $defaultTextToWrite);
                            }
                            break;
                        case "radio":
                            $thisDefaultEleValue = $thisDefaultEle->getVar('ele_value');
                            $defaultTextToWrite = array_search(1, $thisDefaultEleValue);
                    }
                    if ($defaultTextToWrite) {
                        writeElementValue($_POST['target_sub'], $thisDefaultEle->getVar('ele_id'), $subEntWritten, $defaultTextToWrite);
                    }
                }
                $sub_entry_written[] = $subEntWritten;
            }
        } else {
            $sub_entry_new = "new";
            // this happens in uid-link situations?
            $sub_entry_written = "";
        }
        // need to also enforce any equals conditions that are on the subform element, if any, and assign those values to the entries that were just added
        if (is_array($subformConditions)) {
            $filterValues = array();
            foreach ($subformConditions[1] as $i => $thisOp) {
                if ($thisOp == "=" and $subformConditions[3][$i] != "oom" and $subformConditions[2][$i] != "{BLANK}") {
                    $conditionElementObject = $element_handler->get($subformConditions[0][$i]);
                    $filterValues[$subformConditions[0][$i]] = prepareLiteralTextForDB($conditionElementObject, $subformConditions[2][$i]);
                }
            }
            if (count($filterValues) > 0) {
                foreach ($sub_entry_written as $thisSubEntry) {
                    formulize_writeEntry($filterValues, $thisSubEntry);
                }
            }
        }
    }
    // need to do a number of checks here, including looking for single status on subform, and not drawing in add another if there is an entry for a single
    $sub_single_result = getSingle($subform_id, $uid, $groups, $member_handler, $gperm_handler, $mid);
    $sub_single = $sub_single_result['flag'];
    if ($sub_single) {
        unset($sub_entries);
        $sub_entries[$subform_id][0] = $sub_single_result['entry'];
    }
    if (!is_array($sub_entries[$subform_id])) {
        $sub_entries[$subform_id] = array();
    }
    if ($sub_entry_new and !$sub_single and $_POST['target_sub'] == $subform_id) {
        for ($i = 0; $i < $_POST['numsubents']; $i++) {
            array_unshift($sub_entries[$subform_id], $sub_entry_new);
        }
    }
    if (is_array($sub_entry_written) and !$sub_single and $_POST['target_sub'] == $subform_id) {
        foreach ($sub_entry_written as $sew) {
            array_unshift($sub_entries[$subform_id], $sew);
        }
    }
    if (!$customCaption) {
        // get the title of this subform
        // help text removed for F4.0 RC2, this is an experiment
        $subtitle = q("SELECT desc_form FROM " . $xoopsDB->prefix("formulize_id") . " WHERE id_form = {$subform_id}");
        $col_one = "<p id=\"subform-caption-f{$fid}-sf{$subform_id}\" class=\"subform-caption\"><b>" . trans($subtitle[0]['desc_form']) . "</b></p>";
        // <p style=\"font-weight: normal;\">" . _formulize_ADD_HELP;
    } else {
        $col_one = "<p id=\"subform-caption-f{$fid}-sf{$subform_id}\" class=\"subform-caption\"><b>" . trans($customCaption) . "</b></p>";
        // <p style=\"font-weight: normal;\">" . _formulize_ADD_HELP;
    }
    /*if(intval($sub_entries[$subform_id][0]) != 0 OR $sub_entry_new OR is_array($sub_entry_written)) {
    		if(!$nosubforms) { $col_one .= "<br>" . _formulize_ADD_HELP2; }
    		$col_one .= "<br>" . _formulize_ADD_HELP3;
    	} */
    // list the entries, including links to them and delete checkboxes
    // get the headerlist for the subform and convert it into handles
    // note big assumption/restriction that we are only using the first header found (ie: only specify one header for a sub form!)
    // setup the array of elements to draw
    if (is_array($customElements)) {
        $headingDescriptions = array();
        $headerq = q("SELECT ele_caption, ele_colhead, ele_desc, ele_id FROM " . $xoopsDB->prefix("formulize") . " WHERE ele_id IN (" . implode(", ", $customElements) . ") ORDER BY ele_order");
        foreach ($headerq as $thisHeaderResult) {
            $elementsToDraw[] = $thisHeaderResult['ele_id'];
            $headingDescriptions[] = $thisHeaderResult['ele_desc'] ? $thisHeaderResult['ele_desc'] : "";
            if ($captionsForHeadings) {
                $headersToDraw[] = $thisHeaderResult['ele_caption'];
            } else {
                $headersToDraw[] = $thisHeaderResult['ele_colhead'] ? $thisHeaderResult['ele_colhead'] : $thisHeaderResult['ele_caption'];
            }
        }
    } else {
        $subHeaderList = getHeaderList($subform_id);
        $subHeaderList1 = getHeaderList($subform_id, true);
        if (isset($subHeaderList[0])) {
            $headersToDraw[] = trans($subHeaderList[0]);
        }
        if (isset($subHeaderList[1])) {
            $headersToDraw[] = trans($subHeaderList[1]);
        }
        if (isset($subHeaderList[2])) {
            $headersToDraw[] = trans($subHeaderList[2]);
        }
        $elementsToDraw = array_slice($subHeaderList1, 0, 3);
    }
    $need_delete = 0;
    $drawnHeadersOnce = false;
    if ($rowsOrForms == "row" or $rowsOrForms == '') {
        $col_two = "<table id=\"formulize-subform-table-{$subform_id}\" class=\"formulize-subform-table\">";
    } else {
        $col_two = "";
        if (!strstr($_SERVER['PHP_SELF'], "formulize/printview.php")) {
            $col_two .= "<div id=\"subform-{$subformElementId}\" class=\"subform-accordion-container\" subelementid=\"{$subformElementId}\" style=\"display: none;\">";
        }
        $col_two .= "<input type='hidden' name='subform_entry_" . $subformElementId . "_active' id='subform_entry_" . $subformElementId . "_active' value='' />";
        include_once XOOPS_ROOT_PATH . "/modules/formulize/class/data.php";
        $data_handler = new formulizeDataHandler($subform_id);
    }
    $deFrid = $frid ? $frid : "";
    // need to set this up so we can pass it as part of the displayElement function, necessary to establish the framework in case this is a framework and no subform element is being used, just the default draw-in-the-one-to-many behaviour
    // if there's been no form submission, and there's no sub_entries, and there are default blanks to show, then do everything differently -- sept 8 2007
    if (!$_POST['form_submitted'] and count($sub_entries[$subform_id]) == 0 and $defaultblanks > 0 and ($rowsOrForms == "row" or $rowsOrForms == '')) {
        for ($i = 0; $i < $defaultblanks; $i++) {
            // nearly same header drawing code as in the 'else' for drawing regular entries
            if (!$drawnHeadersOnce) {
                $col_two .= "<tr><td>\n";
                $col_two .= "<input type=\"hidden\" name=\"formulize_subformValueSource_{$subform_id}\" value=\"{$value_source}\">\n";
                $col_two .= "<input type=\"hidden\" name=\"formulize_subformValueSourceForm_{$subform_id}\" value=\"{$value_source_form}\">\n";
                $col_two .= "<input type=\"hidden\" name=\"formulize_subformValueSourceEntry_{$subform_id}\" value=\"{$entry}\">\n";
                $col_two .= "<input type=\"hidden\" name=\"formulize_subformElementToWrite_{$subform_id}\" value=\"{$element_to_write}\">\n";
                $col_two .= "<input type=\"hidden\" name=\"formulize_subformSourceType_{$subform_id}\" value=\"" . $elementq[0]['fl_common_value'] . "\">\n";
                $col_two .= "<input type=\"hidden\" name=\"formulize_subformId_{$subform_id}\" value=\"{$subform_id}\">\n";
                // this is probably redundant now that we're tracking sfid in the names of the other elements
                $col_two .= "</td>\n";
                foreach ($headersToDraw as $x => $thishead) {
                    if ($thishead) {
                        $headerHelpLinkPart1 = $headingDescriptions[$i] ? "<a href=\"#\" onclick=\"return false;\" alt=\"" . $headingDescriptions[$x] . "\" title=\"" . $headingDescriptions[$x] . "\">" : "";
                        $headerHelpLinkPart2 = $headerHelpLinkPart1 ? "</a>" : "";
                        $col_two .= "<th><p>{$headerHelpLinkPart1}<b>{$thishead}</b>{$headerHelpLinkPart2}</p></th>\n";
                    }
                }
                $col_two .= "</tr>\n";
                $drawnHeadersOnce = true;
            }
            $col_two .= "<tr>\n<td>";
            $col_two .= "</td>\n";
            include_once XOOPS_ROOT_PATH . "/modules/formulize/include/elementdisplay.php";
            foreach ($elementsToDraw as $thisele) {
                if ($thisele) {
                    ob_start();
                    // critical that we *don't* ask for displayElement to return the element object, since this way the validation logic is passed back through the global space also (ugh).  Otherwise, no validation logic possible for subforms.
                    $renderResult = displayElement($deFrid, $thisele, "subformCreateEntry_" . $i . "_" . $subformElementId);
                    $col_two_temp = ob_get_contents();
                    ob_end_clean();
                    if ($col_two_temp or $renderResult == "rendered") {
                        // only draw in a cell if there actually is an element rendered (some elements might be rendered as nothing (such as derived values)
                        $col_two .= "<td>{$col_two_temp}</td>\n";
                    } else {
                        $col_two .= "<td>******</td>";
                    }
                }
            }
            $col_two .= "</tr>\n";
        }
    } elseif (count($sub_entries[$subform_id]) > 0) {
        // need to figure out the proper order for the sub entries based on the properties set for this form
        // for now, hard code to the word number field to suit the map site only
        // if it's the word subform, then sort the entries differently
        /*if($subform_id == 281) {
        			$sortClause = " fas_281, block_281, word_number ";
        		} 
        		elseif ($subform_id == 283) {
        			$sortClause = " fas_283 ";
        		}
        		else {*/
        $sortClause = " entry_id ";
        //}
        $sformObject = $form_handler->get($subform_id);
        $subEntriesOrderSQL = "SELECT entry_id FROM " . $xoopsDB->prefix("formulize_" . $sformObject->getVar('form_handle')) . " WHERE entry_id IN (" . implode(",", $sub_entries[$subform_id]) . ") ORDER BY {$sortClause}";
        if ($subEntriesOrderRes = $xoopsDB->query($subEntriesOrderSQL)) {
            $sub_entries[$subform_id] = array();
            while ($subEntriesOrderArray = $xoopsDB->fetchArray($subEntriesOrderRes)) {
                $sub_entries[$subform_id][] = $subEntriesOrderArray['entry_id'];
            }
        }
        $currentSubformInstance = $subformInstance;
        foreach ($sub_entries[$subform_id] as $sub_ent) {
            if ($sub_ent != "") {
                if ($rowsOrForms == 'row' or $rowsOrForms == '') {
                    if (!$drawnHeadersOnce) {
                        $col_two .= "<tr><th></th>\n";
                        foreach ($headersToDraw as $i => $thishead) {
                            if ($thishead) {
                                $headerHelpLinkPart1 = $headingDescriptions[$i] ? "<a href=\"#\" onclick=\"return false;\" alt=\"" . $headingDescriptions[$i] . "\" title=\"" . $headingDescriptions[$i] . "\">" : "";
                                $headerHelpLinkPart2 = $headerHelpLinkPart1 ? "</a>" : "";
                                $col_two .= "<th><p>{$headerHelpLinkPart1}<b>{$thishead}</b>{$headerHelpLinkPart2}</p></th>\n";
                            }
                        }
                        $col_two .= "</tr>\n";
                        $drawnHeadersOnce = true;
                    }
                    $col_two .= "<tr>\n<td>";
                    // check to see if we draw a delete box or not
                    if ($sub_ent !== "new" and "hideaddentries" != $hideaddentries and formulizePermHandler::user_can_delete_entry($subform_id, $uid, $sub_ent) and !strstr($_SERVER['PHP_SELF'], "formulize/printview.php")) {
                        // note: if the add/delete entry buttons are hidden, then these delete checkboxes are hidden as well
                        $need_delete = 1;
                        $col_two .= "<input type=checkbox name=delbox{$sub_ent} value={$sub_ent}></input>";
                    }
                    $col_two .= "</td>\n";
                    include_once XOOPS_ROOT_PATH . "/modules/formulize/include/elementdisplay.php";
                    foreach ($elementsToDraw as $thisele) {
                        if ($thisele) {
                            ob_start();
                            // critical that we *don't* ask for displayElement to return the element object, since this way the validation logic is passed back through the global space also (ugh).  Otherwise, no validation logic possible for subforms.
                            $renderResult = displayElement($deFrid, $thisele, $sub_ent);
                            $col_two_temp = ob_get_contents();
                            ob_end_clean();
                            if ($col_two_temp or $renderResult == "rendered") {
                                // only draw in a cell if there actually is an element rendered (some elements might be rendered as nothing (such as derived values)
                                $col_two .= "<td>{$col_two_temp}</td>\n";
                            } else {
                                $col_two .= "<td>******</td>";
                            }
                        }
                    }
                    if (!$nosubforms and $showViewButtons and !strstr($_SERVER['PHP_SELF'], "formulize/printview.php")) {
                        $col_two .= "<td><input type=button name=view" . $sub_ent . " value='" . _formulize_SUBFORM_VIEW . "' onclick=\"javascript:goSub('{$sub_ent}', '{$subform_id}');return false;\"></input></td>\n";
                    }
                    $col_two .= "</tr>\n";
                } else {
                    // display the full form
                    $headerValues = array();
                    foreach ($elementsToDraw as $thisele) {
                        $value = $data_handler->getElementValueInEntry($sub_ent, $thisele);
                        $element_object = _getElementObject($thisele);
                        $value = prepvalues($value, $element_object->getVar("ele_handle"), $sub_ent);
                        if (is_array($value)) {
                            $value = implode(" - ", $value);
                        }
                        // may be an array if the element allows multiple selections (checkboxes, multiselect list boxes, etc)
                        $headerValues[] = $value;
                    }
                    $headerToWrite = implode(" &mdash; ", $headerValues);
                    if (str_replace(" &mdash; ", "", $headerToWrite) == "") {
                        $headerToWrite = _AM_ELE_SUBFORM_NEWENTRY_LABEL;
                    }
                    // check to see if we draw a delete box or not
                    $deleteBox = "";
                    if ($sub_ent !== "new" and formulizePermHandler::user_can_delete_entry($subform_id, $uid, $sub_ent) and !strstr($_SERVER['PHP_SELF'], "formulize/printview.php")) {
                        $need_delete = 1;
                        $deleteBox = "<input type=checkbox name=delbox{$sub_ent} value={$sub_ent}></input>&nbsp;&nbsp;";
                    }
                    if (!strstr($_SERVER['PHP_SELF'], "formulize/printview.php")) {
                        $col_two .= "<div class=\"subform-deletebox\">{$deleteBox}</div><div class=\"subform-entry-container\" id=\"subform-" . $subform_id . "-" . "{$sub_ent}\">\r\n\t<p class=\"subform-header\"><a href=\"#\"><span class=\"accordion-name\">" . $headerToWrite . "</span></a></p>\r\n\t<div class=\"accordion-content content\">";
                    }
                    ob_start();
                    $GLOBALS['formulize_inlineSubformFrid'] = $frid;
                    if ($display_screen = get_display_screen_for_subform($subform_element_object)) {
                        $subScreen_handler = xoops_getmodulehandler('formScreen', 'formulize');
                        $subScreenObject = $subScreen_handler->get($display_screen);
                        $subScreen_handler->render($subScreenObject, $sub_ent, null, true);
                    } else {
                        // SHOULD CHANGE THIS TO USE THE DEFAULT SCREEN FOR THE FORM!!!!!!????
                        $renderResult = displayForm($subform_id, $sub_ent, "", "", "", "", "formElementsOnly");
                    }
                    if (!$nestedSubform) {
                        unset($GLOBALS['formulize_inlineSubformFrid']);
                    }
                    $col_two_temp = ob_get_contents();
                    ob_end_clean();
                    $col_two .= $col_two_temp;
                    if (!strstr($_SERVER['PHP_SELF'], "formulize/printview.php")) {
                        $col_two .= "</div>\n</div>\n";
                    }
                }
            }
        }
        $subformInstance = $currentSubformInstance;
        // instance counter might have changed because the form could include other subforms
    }
    if ($rowsOrForms == 'row' or $rowsOrForms == '') {
        // complete the table if we're drawing rows
        $col_two .= "</table>";
    } else {
        if (!strstr($_SERVER['PHP_SELF'], "formulize/printview.php")) {
            $col_two .= "</div>";
            // close of the subform-accordion-container
        }
        static $jqueryUILoaded = false;
        if (!$jqueryUILoaded) {
            $col_two .= "<script type=\"text/javascript\" src=\"" . XOOPS_URL . "/modules/formulize/libraries/jquery/jquery-ui-1.8.2.custom.min.js\"></script>\n";
            $col_two .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"" . XOOPS_URL . "/modules/formulize/libraries/jquery/css/start/jquery-ui-1.8.2.custom.css\">\n";
            $jqueryUILoaded = true;
        }
        $col_two .= "\n\r\n<script type=\"text/javascript\">\r\n\tjQuery(document).ready(function() {\r\n\t\tjQuery(\"#subform-{$subformElementId}\").accordion({\r\n\t\t\tautoHeight: false, // no fixed height for sections\r\n\t\t\tcollapsible: true, // sections can be collapsed\r\n\t\t\tactive: ";
        if ($_POST['target_sub_instance'] == $subformElementId . $subformInstance and $_POST['target_sub'] == $subform_id) {
            $col_two .= count($sub_entries[$subform_id]) - $_POST['numsubents'];
        } elseif (is_numeric($_POST['subform_entry_' . $subformElementId . '_active'])) {
            $col_two .= $_POST['subform_entry_' . $subformElementId . '_active'];
        } else {
            $col_two .= 'false';
        }
        $col_two .= ",\r\n\t\t\theader: \"> div > p.subform-header\"\r\n\t\t});\r\n\t\tjQuery(\"#subform-{$subformElementId}\").fadeIn();\r\n\t});\r\n</script>";
    }
    // end of if we're closing the subform inferface where entries are supposed to be collapsable forms
    $deleteButton = "";
    if ((count($sub_entries[$subform_id]) > 0 and $sub_entries[$subform_id][0] != "" or $sub_entry_new or is_array($sub_entry_written)) and $need_delete) {
        $deleteButton = "&nbsp;&nbsp;&nbsp;<input type=button name=deletesubs value='" . _formulize_DELETE_CHECKED . "' onclick=\"javascript:sub_del('{$subform_id}');\">";
        static $deletesubsflagIncluded = false;
        if (!$deletesubsflagIncluded) {
            $col_one .= "\n<input type=hidden name=deletesubsflag value=''>\n";
            $deletesubsflagIncluded = true;
        }
    }
    // if the 'add x entries button' should be hidden or visible
    if ("hideaddentries" != $hideaddentries) {
        $allowed_to_add_entries = false;
        if ("subform" == $hideaddentries or 1 == $hideaddentries) {
            // for compatability, accept '1' which is the old value which corresponds to the new use-subform-permissions (saved as "subform")
            // user can add entries if they have permission on the sub form
            $allowed_to_add_entries = $gperm_handler->checkRight("add_own_entry", $subform_id, $groups, $mid);
        } else {
            // user can add entries if they have permission on the main form
            // the user should only be able to add subform entries if they can *edit* the main form entry, since adding a subform entry
            //  is like editing the main form entry. otherwise they could add subform entries on main form entries owned by other users
            $allowed_to_add_entries = formulizePermHandler::user_can_edit_entry($fid, $uid, $entry);
        }
        if ($allowed_to_add_entries and !strstr($_SERVER['PHP_SELF'], "formulize/printview.php")) {
            if (count($sub_entries[$subform_id]) == 1 and $sub_entries[$subform_id][0] === "" and $sub_single) {
                $col_two .= "<p><input type=button name=addsub value='" . _formulize_ADD_ONE . "' onclick=\"javascript:add_sub('{$subform_id}', 1, " . $subformElementId . $subformInstance . ");\"></p>";
            } elseif (!$sub_single) {
                $use_simple_add_one_button = isset($subform_element_object->ele_value["simple_add_one_button"]) ? 1 == $subform_element_object->ele_value["simple_add_one_button"] : false;
                $col_two .= "<p><input type=button name=addsub value='" . ($use_simple_add_one_button ? trans($subform_element_object->ele_value['simple_add_one_button_text']) : _formulize_ADD) . "' onclick=\"javascript:add_sub('{$subform_id}', window.document.formulize.addsubentries{$subform_id}{$subformElementId}{$subformInstance}.value, " . $subformElementId . $subformInstance . ");\">";
                if ($use_simple_add_one_button) {
                    $col_two .= "<input type=\"hidden\" name=addsubentries{$subform_id}{$subformElementId}{$subformInstance} id=addsubentries{$subform_id}{$subformElementId}{$subformInstance} value=\"1\">";
                } else {
                    $col_two .= "<input type=text name=addsubentries{$subform_id}{$subformElementId}{$subformInstance} id=addsubentries{$subform_id}{$subformElementId}{$subformInstance} value=1 size=2 maxlength=2>";
                    $col_two .= $addEntriesText;
                }
                $col_two .= $deleteButton . "</p>";
            }
        }
    }
    $to_return['c1'] = $col_one;
    $to_return['c2'] = $col_two;
    $to_return['single'] = $col_one . $col_two;
    if (is_object($subform_element_object)) {
        global $xoopsUser;
        $show_element_edit_link = (is_object($xoopsUser) and in_array(XOOPS_GROUP_ADMIN, $xoopsUser->getGroups()));
        $edit_link = "";
        if ($show_element_edit_link) {
            $edit_link = "<a class=\"formulize-element-edit-link\" tabindex=\"-1\" href=\"" . XOOPS_URL . "/modules/formulize/admin/ui.php?page=element&aid=0&ele_id=" . $subform_element_object->getVar("ele_id") . "\" target=\"_blank\">edit element</a>";
        }
        $to_return['single'] = "<div class=\"formulize-subform-" . $subform_element_object->getVar("ele_handle") . "\">{$edit_link} {$col_one} {$col_two}</div>";
    }
    return $to_return;
}
 function constructElement($form_ele_id, $ele_value, $entry, $isDisabled = false, $screen = null)
 {
     if (strstr(getCurrentURL(), "printview.php")) {
         $isDisabled = true;
         // disabled all elements if we're on the printable view
     }
     global $xoopsUser, $xoopsModuleConfig, $separ, $myts;
     $myts =& MyTextSanitizer::getInstance();
     // $form_ele_id contains the ele_id of the current link select box, but we have to remove "ele_" from the front of it.
     //print "form_ele_id: $form_ele_id<br>"; // debug code
     if (strstr($form_ele_id, "de_")) {
         // display element uses a slightly different element name so it can be distinguished on subsequent page load from regular elements...THIS IS NOT TRUE/NECESSARY ANYMORE SINCE FORMULIZE 3, WHERE ALL ELEMENTS ARE DISPLAY ELEMENTS
         $true_ele_id = str_replace("de_" . $this->_ele->getVar('id_form') . "_" . $entry . "_", "", $form_ele_id);
         $displayElementInEffect = true;
     } else {
         $true_ele_id = str_replace("ele_", "", $form_ele_id);
         $displayElementInEffect = false;
     }
     // added July 6 2005.
     if (!$xoopsModuleConfig['delimeter']) {
         // assume that we're accessing a form from outside the Formulize module, therefore the Formulize delimiter setting is not available, so we have to query for it directly.
         global $xoopsDB;
         $delimq = q("SELECT conf_value FROM " . $xoopsDB->prefix("config") . ", " . $xoopsDB->prefix("modules") . " WHERE " . $xoopsDB->prefix("modules") . ".mid=" . $xoopsDB->prefix("config") . ".conf_modid AND " . $xoopsDB->prefix("modules") . ".dirname=\"formulize\" AND " . $xoopsDB->prefix("config") . ".conf_name=\"delimeter\"");
         $delimSetting = $delimq[0]['conf_value'];
     } else {
         $delimSetting = $xoopsModuleConfig['delimeter'];
     }
     $customElementHasData = false;
     $id_form = $this->_ele->getVar('id_form');
     $ele_caption = $this->_ele->getVar('ele_caption', 'e');
     $ele_caption = preg_replace('/\\{SEPAR\\}/', '', $ele_caption);
     // $ele_caption = stripslashes($ele_caption);
     // next line commented out to accomodate passing of ele_value from index.php
     // $ele_value = $this->_ele->getVar('ele_value');
     $ele_type = $this->_ele->getVar('ele_type');
     // call the text sanitizer, first try to convert HTML chars, and if there were no conversions, then do a textarea conversion to automatically make links clickable
     $ele_caption = trans($ele_caption);
     $htmlCaption = htmlspecialchars_decode($myts->undoHtmlSpecialChars($ele_caption));
     // do twice, because we need to handle &amp;lt; and other stupid stuff...do first time through XOOPS myts just because it might be doing a couple extra things that are useful...can probably just use PHP's own filter twice, not too big a deal
     if ($htmlCaption == $ele_caption) {
         $ele_caption = $myts->displayTarea($ele_caption);
     } else {
         $ele_caption = $htmlCaption;
     }
     $ele_caption = $this->formulize_replaceCurlyBracketVariables($ele_caption, $entry, $id_form);
     // ele_desc added June 6 2006 -- jwe
     $ele_desc = $this->_ele->getVar('ele_desc', "f");
     // the f causes no stupid reformatting by the ICMS core to take place
     // determine the entry owner
     if ($entry != "new") {
         $owner = getEntryOwner($entry, $id_form);
     } else {
         $owner = $xoopsUser ? $xoopsUser->getVar('uid') : 0;
     }
     // setup the previous entry UI if necessary -- this is an option that can be specified for certain screens
     $previousEntryUI = "";
     if ($screen and $ele_type != "derived") {
         if ($screen->getVar('paraentryform') > 0) {
             $previousEntryUI = $this->formulize_setupPreviousEntryUI($screen, $true_ele_id, $ele_type, $owner, $displayElementInEffect, $entry, $this->_ele->getVar('ele_handle'), $this->_ele->getVar('id_form'));
         }
     }
     $form_handler = xoops_getmodulehandler('forms', 'formulize');
     $formObject = $form_handler->get($id_form);
     switch ($ele_type) {
         case 'derived':
             if ($entry != "new") {
                 $form_ele = new xoopsFormLabel($this->_ele->getVar('ele_caption'), formulize_numberFormat($ele_value[5], $this->_ele->getVar('ele_handle')));
                 $form_ele->setDescription(html_entity_decode($ele_desc, ENT_QUOTES));
             } else {
                 $form_ele = new xoopsFormLabel($this->_ele->getVar('ele_caption'), _formulize_VALUE_WILL_BE_CALCULATED_AFTER_SAVE);
                 $form_ele->setDescription(html_entity_decode($ele_desc, ENT_QUOTES));
             }
             break;
         case 'ib':
             if (get_magic_quotes_gpc()) {
                 $ele_value[0] = stripslashes($ele_value[0]);
             }
             if (trim($ele_value[0]) == "") {
                 $ele_value[0] = $ele_caption;
             }
             if (strstr($ele_value[0], "\$value=") or strstr($ele_value[0], "\$value =")) {
                 $form_id = $id_form;
                 $entry_id = $entry;
                 $entryData = $this->formulize_getCachedEntryData($id_form, $entry);
                 $creation_datetime = display($entryData, "creation_datetime");
                 $evalResult = eval($ele_value[0]);
                 if ($evalResult === false) {
                     $ele_value[0] = _formulize_ERROR_IN_LEFTRIGHT;
                 } else {
                     $ele_value[0] = $value;
                     // value is supposed to be the thing set in the eval'd code
                 }
             }
             $ele_value[0] = $this->formulize_replaceCurlyBracketVariables($ele_value[0], $entry, $id_form);
             $form_ele = $ele_value;
             // an array, item 0 is the contents of the break, item 1 is the class of the table cell (for when the form is table rendered)
             break;
         case 'text':
             $ele_value[2] = stripslashes($ele_value[2]);
             //        $ele_value[2] = $myts->displayTarea($ele_value[2]); // commented by jwe 12/14/04 so that info displayed for viewing in a form box does not contain HTML formatting
             $ele_value[2] = getTextboxDefault($ele_value[2], $id_form, $entry);
             //if placeholder value is set
             if ($ele_value[11]) {
                 $placeholder = $ele_value[2];
                 $ele_value[2] = "";
             }
             if (!strstr(getCurrentURL(), "printview.php")) {
                 // nmc 2007.03.24 - added
                 $form_ele = new XoopsFormText($ele_caption, $form_ele_id, $ele_value[0], $ele_value[1], $ele_value[2]);
             } else {
                 // nmc 2007.03.24 - added
                 $form_ele = new XoopsFormLabel($ele_caption, formulize_numberFormat($ele_value[2], $this->_ele->getVar('ele_handle')));
                 // nmc 2007.03.24 - added
             }
             //if placeholder value is set
             if ($ele_value[11]) {
                 $form_ele->setExtra("placeholder='" . $placeholder . "'");
             }
             //if numbers-only option is set
             if ($ele_value[3]) {
                 $form_ele->setExtra("class='numbers-only-textbox'");
             }
             // if required unique option is set, create validation javascript that will ask the database if the value is unique or not
             if ($ele_value[9]) {
                 $eltname = $form_ele_id;
                 $eltcaption = $ele_caption;
                 $eltmsg = empty($eltcaption) ? sprintf(_FORM_ENTER, $eltname) : sprintf(_FORM_ENTER, $eltcaption);
                 $eltmsg = str_replace('"', '\\"', stripslashes($eltmsg));
                 $eltmsgUnique = empty($eltcaption) ? sprintf(_formulize_REQUIRED_UNIQUE, $eltname) : sprintf(_formulize_REQUIRED_UNIQUE, $eltcaption);
                 if ($this->_ele->getVar('ele_req')) {
                     // need to manually handle required setting, since only one validation routine can run for an element, so we need to include required checking in this unique checking routine, if the user selected required too
                     $form_ele->customValidationCode[] = "\nif ( myform.{$eltname}.value == '' ) {\n";
                     $form_ele->customValidationCode[] = "window.alert(\"{$eltmsg}\");\n myform.{$eltname}.focus();\n return false;\n";
                     $form_ele->customValidationCode[] = "}\n";
                 }
                 $form_ele->customValidationCode[] = "if(formulize_xhr_returned_check_for_unique_value != 'notreturned') {\n";
                 // a value has already been returned from xhr, so let's check that out...
                 $form_ele->customValidationCode[] = "if(formulize_xhr_returned_check_for_unique_value != 'valuenotfound') {\n";
                 // request has come back, form has been resubmitted, but the check turned up postive, ie: value is not unique, so we have to halt submission , and reset the check for unique flag so we can check again when the user has typed again and is ready to submit
                 $form_ele->customValidationCode[] = "window.alert(\"{$eltmsgUnique}\");\n";
                 $form_ele->customValidationCode[] = "formulize_xhr_returned_check_for_unique_value = 'notreturned'\n";
                 $form_ele->customValidationCode[] = "myform.{$eltname}.focus();\n return false;\n";
                 $form_ele->customValidationCode[] = "}\n";
                 $form_ele->customValidationCode[] = "} else {\n";
                 // do not submit the form, just send off the request, which will trigger a resubmission after setting the returned flag above to true so that we won't send again on resubmission
                 $form_ele->customValidationCode[] = "\nvar formulize_xhr_params = []\n";
                 $form_ele->customValidationCode[] = "formulize_xhr_params[0] = myform.{$eltname}.value;\n";
                 $form_ele->customValidationCode[] = "formulize_xhr_params[1] = " . $this->_ele->getVar('ele_id') . ";\n";
                 $xhr_entry_to_send = is_numeric($entry) ? $entry : 0;
                 $form_ele->customValidationCode[] = "formulize_xhr_params[2] = " . $xhr_entry_to_send . ";\n";
                 $form_ele->customValidationCode[] = "formulize_xhr_send('check_for_unique_value', formulize_xhr_params);\n";
                 $form_ele->customValidationCode[] = "return false;\n";
                 $form_ele->customValidationCode[] = "}\n";
             } elseif ($this->_ele->getVar('ele_req') and !$isDisabled) {
                 $eltname = $form_ele_id;
                 $eltcaption = $ele_caption;
                 $eltmsg = empty($eltcaption) ? sprintf(_FORM_ENTER, $eltname) : sprintf(_FORM_ENTER, $eltcaption);
                 $eltmsg = str_replace('"', '\\"', stripslashes($eltmsg));
                 $form_ele->customValidationCode[] = "if (myform.{$eltname}.value == \"\") { window.alert(\"{$eltmsg}\"); myform.{$eltname}.focus(); return false; }";
             }
             break;
         case 'textarea':
             $ele_value[0] = stripslashes($ele_value[0]);
             //        $ele_value[0] = $myts->displayTarea($ele_value[0]); // commented by jwe 12/14/04 so that info displayed for viewing in a form box does not contain HTML formatting
             $ele_value[0] = getTextboxDefault($ele_value[0], $id_form, $entry);
             if (!strstr(getCurrentURL(), "printview.php") and !$isDisabled) {
                 // nmc 2007.03.24 - added
                 if (isset($ele_value['use_rich_text']) and $ele_value['use_rich_text']) {
                     include_once XOOPS_ROOT_PATH . "/class/xoopsform/formeditor.php";
                     $form_ele = new XoopsFormEditor($ele_caption, 'FCKeditor', $editor_configs = array("name" => $form_ele_id, "value" => $ele_value[0]), $noHtml = false, $OnFailure = "");
                     $eltname = $form_ele_id;
                     $eltcaption = $ele_caption;
                     $eltmsg = empty($eltcaption) ? sprintf(_FORM_ENTER, $eltname) : sprintf(_FORM_ENTER, $eltcaption);
                     $eltmsg = str_replace('"', '\\"', stripslashes($eltmsg));
                     $form_ele->customValidationCode[] = "\n var FCKGetInstance = FCKeditorAPI.GetInstance('{$form_ele_id}');\n";
                     $form_ele->customValidationCode[] = "var getText = FCKGetInstance.EditorDocument.body.innerHTML; \n";
                     $form_ele->customValidationCode[] = "var StripTag = getText.replace(/(<([^>]+)>)/ig,''); \n";
                     $form_ele->customValidationCode[] = "if(StripTag=='' || StripTag=='&nbsp;') {\n";
                     $form_ele->customValidationCode[] = "window.alert(\"{$eltmsg}\");\n FCKGetInstance.Focus();\n return false;\n";
                     $form_ele->customValidationCode[] = "}\n";
                     $GLOBALS['formulize_fckEditors'] = true;
                 } else {
                     $form_ele = new XoopsFormTextArea($ele_caption, $form_ele_id, $ele_value[0], $ele_value[1], $ele_value[2]);
                 }
             } else {
                 // nmc 2007.03.24 - added
                 $form_ele = new XoopsFormLabel($ele_caption, str_replace("\n", "<br>", undoAllHTMLChars($ele_value[0], ENT_QUOTES)));
                 // nmc 2007.03.24 - added
             }
             break;
         case 'areamodif':
             if (strstr($ele_value[0], "\$value=") or strstr($ele_value[0], "\$value =")) {
                 $form_id = $id_form;
                 $entry_id = $entry;
                 $entryData = $this->formulize_getCachedEntryData($id_form, $entry);
                 $creation_datetime = display($entryData, "creation_datetime");
                 $evalResult = eval($ele_value[0]);
                 if ($evalResult === false) {
                     $ele_value[0] = _formulize_ERROR_IN_LEFTRIGHT;
                 } else {
                     $ele_value[0] = $value;
                     // value is supposed to be the thing set in the eval'd code
                 }
             }
             $ele_value[0] = $this->formulize_replaceCurlyBracketVariables($ele_value[0], $entry, $id_form);
             $form_ele = new XoopsFormLabel($ele_caption, $ele_value[0]);
             break;
         case 'select':
             if (is_string($ele_value[2]) and strstr($ele_value[2], "#*=:*")) {
                 // new process for handling links...May 10 2008...new datastructure for formulize 3.0
                 $boxproperties = explode("#*=:*", $ele_value[2]);
                 $sourceFid = $boxproperties[0];
                 $sourceHandle = $boxproperties[1];
                 $sourceEntryIds = explode(",", trim($boxproperties[2], ","));
                 // grab the user's groups and the module id
                 global $regcode;
                 if ($regcode) {
                     // if we're dealing with a registration code, determine group membership based on the code
                     $reggroupsq = q("SELECT reg_codes_groups FROM " . XOOPS_DB_PREFIX . "_reg_codes WHERE reg_codes_code=\"{$regcode}\"");
                     $groups = explode("&8(%\$", $reggroupsq[0]['reg_codes_groups']);
                     if ($groups[0] === "") {
                         unset($groups);
                     }
                     // if a code has no groups associated with it, then kill the null value that will be in position 0 in the groups array.
                     $groups[] = XOOPS_GROUP_USERS;
                     $groups[] = XOOPS_GROUP_ANONYMOUS;
                 } else {
                     $groups = $xoopsUser ? $xoopsUser->getGroups() : array(0 => XOOPS_GROUP_ANONYMOUS);
                 }
                 $module_id = getFormulizeModId();
                 global $xoopsDB;
                 $pgroups = array();
                 // handle new linkscope option -- August 30 2006
                 $emptylist = false;
                 if ($ele_value[3]) {
                     $scopegroups = explode(",", $ele_value[3]);
                     if (!in_array("all", $scopegroups)) {
                         if ($ele_value[4]) {
                             // limit by user's groups
                             foreach ($groups as $gid) {
                                 // want to loop so we can get rid of reg users group simply
                                 if ($gid == XOOPS_GROUP_USERS) {
                                     continue;
                                 }
                                 if (in_array($gid, $scopegroups)) {
                                     $pgroups[] = $gid;
                                 }
                             }
                         } else {
                             // just use scopegroups
                             $pgroups = $scopegroups;
                         }
                         if (count($pgroups) == 0) {
                             // specific scope was specified, and nothing found, so we should show nothing
                             $emptylist = true;
                         }
                     } else {
                         if ($ele_value[4]) {
                             // all groups selected, but limiting by user's groups is turned on
                             foreach ($groups as $gid) {
                                 // want to loop so we can get rid of reg users group simply
                                 if ($gid == XOOPS_GROUP_USERS) {
                                     continue;
                                 }
                                 $pgroups[] = $gid;
                             }
                         } else {
                             // all groups should be used
                             unset($pgroups);
                             $allgroupsq = q("SELECT groupid FROM " . $xoopsDB->prefix("groups"));
                             //  . " WHERE groupid != " . XOOPS_GROUP_USERS); // use all groups now, if all groups are picked, with no restrictions on membership or anything, then use all groups
                             foreach ($allgroupsq as $thisgid) {
                                 $pgroups[] = $thisgid['groupid'];
                             }
                         }
                     }
                 }
                 // Note: OLD WAY: if no groups were found, then pguidq will be empty and so all entries will be shown, no restrictions
                 // NEW WAY: if a specific group(s) was specified, and no match with the current user was found, then we return an empty list
                 array_unique($pgroups);
                 // remove duplicate groups from the list
                 if ($ele_value[6] and count($pgroups) > 0) {
                     $pgroupsfilter = " (";
                     $start = true;
                     foreach ($pgroups as $thisPgroup) {
                         if (!$start) {
                             $pgroupsfilter .= " AND ";
                         }
                         $pgroupsfilter .= "EXISTS(SELECT 1 FROM " . $xoopsDB->prefix("formulize_entry_owner_groups") . " AS t2 WHERE t2.groupid={$thisPgroup} AND t2.fid={$sourceFid} AND t2.entry_id=t1.entry_id)";
                         $start = false;
                     }
                     $pgroupsfilter .= ")";
                 } elseif (count($pgroups) > 0) {
                     $pgroupsfilter = " t2.groupid IN (" . formulize_db_escape(implode(",", $pgroups)) . ") AND t2.entry_id=t1.entry_id AND t2.fid={$sourceFid}";
                 } else {
                     $pgroupsfilter = "";
                 }
                 $sourceFormObject = $form_handler->get($sourceFid);
                 list($conditionsfilter, $conditionsfilter_oom, $parentFormFrom) = buildConditionsFilterSQL($ele_value[5], $sourceFid, $entry, $owner, $formObject, "t1");
                 // if there is a restriction in effect, then add some SQL to reject options that have already been selected ??
                 $restrictSQL = "";
                 if ($ele_value[9]) {
                     $t4_ele_value = $this->_ele->getVar('ele_value');
                     if ($t4_ele_value[1]) {
                         // allows multiple selections
                         $restrictSQL = " AND (\n\t\t\t\t\t\tNOT EXISTS (\n\t\t\t\t\t\tSELECT 1 FROM " . $xoopsDB->prefix("formulize_" . $formObject->getVar('form_handle')) . " AS t4 WHERE t4.`" . $this->_ele->getVar('ele_handle') . "` LIKE CONCAT( '%,', t1.`entry_id` , ',%' ) AND t4.entry_id != " . intval($entry);
                     } else {
                         $restrictSQL = " AND (\n                                                    NOT EXISTS (\n                                                    SELECT 1 FROM " . $xoopsDB->prefix("formulize_" . $formObject->getVar('form_handle')) . " AS t4 WHERE t4.`" . $this->_ele->getVar('ele_handle') . "` = t1.`entry_id` AND t4.entry_id != " . intval($entry);
                         $restrictSQL .= $this->addEntryRestrictionSQL($ele_value[9], $id_form, $groups);
                         // pass in the flag about restriction scope, and the form id, and the groups
                         $restrictSQL .= " ) OR EXISTS (\n                                                    SELECT 1 FROM " . $xoopsDB->prefix("formulize_" . $formObject->getVar('form_handle')) . " AS t4 WHERE t4.`" . $this->_ele->getVar('ele_handle') . "` = t1.`entry_id` AND t4.entry_id = " . intval($entry);
                     }
                     $restrictSQL .= $this->addEntryRestrictionSQL($ele_value[9], $id_form, $groups);
                     // pass in the flag about restriction scope, and the form id, and the groups
                     $restrictSQL .= " ) OR EXISTS (\n\t\t\t\t\t\tSELECT 1 FROM " . $xoopsDB->prefix("formulize_" . $formObject->getVar('form_handle')) . " AS t4 WHERE t4.`" . $this->_ele->getVar('ele_handle') . "` LIKE CONCAT( '%,', t1.`entry_id` , ',%' ) AND t4.entry_id = " . intval($entry);
                     $restrictSQL .= $this->addEntryRestrictionSQL($ele_value[9], $id_form, $groups);
                     $restrictSQL .= ") )";
                 }
                 static $cachedSourceValuesQ = array();
                 static $cachedSourceValuesAutocompleteFile = array();
                 static $cachedSourceValuesAutocompleteLength = array();
                 // setup the sort order based on ele_value[12], which is an element id number
                 $sortOrder = $ele_value[15] == 2 ? " DESC" : "ASC";
                 if ($ele_value[12] == "none" or !$ele_value[12]) {
                     $sortOrderClause = " ORDER BY t1.`{$sourceHandle}` {$sortOrder}";
                 } else {
                     list($sortHandle) = convertElementIdsToElementHandles(array($ele_value[12]), $sourceFormObject->getVar('id_form'));
                     $sortOrderClause = " ORDER BY t1.`{$sortHandle}` {$sortOrder}";
                 }
                 // if no extra elements are selected for display as a form element, then display the linked element
                 if (0 == count($ele_value[EV_MULTIPLE_FORM_COLUMNS]) or $ele_value[EV_MULTIPLE_FORM_COLUMNS][0] == 'none') {
                     $linked_columns = array($boxproperties[1]);
                 } else {
                     $linked_columns = convertElementIdsToElementHandles($ele_value[EV_MULTIPLE_FORM_COLUMNS], $sourceFormObject->getVar('id_form'));
                     // remove empty entries, which can happen if the "use the linked field selected above" option is selected
                     $linked_columns = array_filter($linked_columns);
                 }
                 if (is_array($linked_columns)) {
                     $select_column = "t1.`" . implode("`, t1.`", $linked_columns) . "`";
                 } else {
                     $select_column = "t1.`{$linked_columns}`";
                     // in this case, it's just one linked column
                 }
                 // if there is a groups filter, then join to the group ownership table
                 $extra_clause = "";
                 if ($pgroupsfilter) {
                     $extra_clause = ", " . $xoopsDB->prefix("formulize_entry_owner_groups") . " AS t2 {$parentFormFrom} WHERE {$pgroupsfilter}";
                 } else {
                     $extra_clause = " {$parentFormFrom} WHERE t1.entry_id>0";
                 }
                 $sourceValuesQ = "SELECT t1.entry_id, " . $select_column . " FROM " . $xoopsDB->prefix("formulize_" . $sourceFormObject->getVar('form_handle')) . " AS t1" . $extra_clause . "{$conditionsfilter} {$conditionsfilter_oom} {$restrictSQL}" . "GROUP BY t1.entry_id {$sortOrderClause}";
                 if (!$isDisabled) {
                     // set the default selections, based on the entry_ids that have been selected as the defaults, if applicable
                     $hasNoValues = trim($boxproperties[2]) == "" ? true : false;
                     $useDefaultsWhenEntryHasNoValue = $ele_value[14];
                     if (($entry == "new" or $useDefaultsWhenEntryHasNoValue and $hasNoValues) and (is_array($ele_value[13]) and count($ele_value[13]) > 0 or $ele_value[13])) {
                         $defaultSelected = $ele_value[13];
                     } else {
                         $defaultSelected = "";
                     }
                     $form_ele = new XoopsFormSelect($ele_caption, $form_ele_id, $defaultSelected, $ele_value[0], $ele_value[1]);
                     $form_ele->setExtra("onchange=\"javascript:formulizechanged=1;\" jquerytag='{$form_ele_id}'");
                     if ($ele_value[0] == 1) {
                         // add the initial default entry, singular or plural based on whether the box is one line or not.
                         $form_ele->addOption("none", _AM_FORMLINK_PICK);
                     }
                 } else {
                     $disabledHiddenValue = array();
                     $disabledOutputText = array();
                 }
                 if (!isset($cachedSourceValuesQ[$sourceValuesQ])) {
                     $element_handler = xoops_getmodulehandler('elements', 'formulize');
                     $sourceElementObject = $element_handler->get($boxproperties[1]);
                     if ($sourceElementObject->isLinked) {
                         // need to jump one more level back to get value that this value is pointing at
                         $sourceEleValue = $sourceElementObject->getVar('ele_value');
                         $originalSource = explode("#*=:*", $sourceEleValue[2]);
                         include_once XOOPS_ROOT_PATH . "/modules/formulize/class/data.php";
                         $data_handler = new formulizeDataHandler($originalSource[0]);
                     }
                     $reslinkedvaluesq = $xoopsDB->query($sourceValuesQ);
                     if ($reslinkedvaluesq) {
                         $linked_column_count = count($linked_columns);
                         while ($rowlinkedvaluesq = $xoopsDB->fetchRow($reslinkedvaluesq)) {
                             $linked_column_values = array();
                             foreach (range(1, $linked_column_count) as $linked_column_index) {
                                 if ($rowlinkedvaluesq[$linked_column_index] === "") {
                                     $linked_column_values[] = "";
                                 } else {
                                     if ($sourceElementObject->isLinked) {
                                         $linked_value = prepvalues($rowlinkedvaluesq[$linked_column_index], $boxproperties[1], $rowlinkedvaluesq[0]);
                                         $linked_column_values[] = $linked_value[0];
                                     } else {
                                         $linked_column_values[] = strip_tags(trim($rowlinkedvaluesq[$linked_column_index]));
                                     }
                                 }
                             }
                             $linkedElementOptions[$rowlinkedvaluesq[0]] = implode(" - ", $linked_column_values);
                         }
                     }
                     $cachedSourceValuesQ[$sourceValuesQ] = $linkedElementOptions;
                     /* ALTERED - 20100318 - freeform - jeff/julian - start */
                     if (!$isDisabled and $ele_value[8] == 1) {
                         // write the possible values to a cached file so we can look them up easily when we need them, don't want to actually send them to the browser, since it could be huge, but don't want to replicate all the logic that has already gathered the values for us, each time there's an ajax request
                         $cachedLinkedOptionsFileName = "formulize_linkedOptions_" . str_replace(".", "", microtime(true));
                         formulize_scandirAndClean(XOOPS_ROOT_PATH . "/cache/", "formulize_linkedOptions_");
                         $maxLength = 10;
                         $the_values = array();
                         asort($linkedElementOptions);
                         foreach ($linkedElementOptions as $id => $text) {
                             $the_values[$id] = trans($text);
                             $thisTextLength = strlen($text);
                             $maxLength = $thisTextLength > $maxLength ? $thisTextLength : $maxLength;
                         }
                         file_put_contents(XOOPS_ROOT_PATH . "/cache/{$cachedLinkedOptionsFileName}", "<?php\n\${$cachedLinkedOptionsFileName} = " . var_export($the_values, true) . ";\n");
                         $cachedSourceValuesAutocompleteFile[$sourceValuesQ] = $cachedLinkedOptionsFileName;
                         $cachedSourceValuesAutocompleteLength[$sourceValuesQ] = $maxLength;
                     }
                 }
                 if ($boxproperties[2]) {
                     $default_value = $boxproperties[2];
                     $default_value_user = $cachedSourceValuesQ[$sourceValuesQ][$boxproperties[2]];
                 }
                 // if we're rendering an autocomplete box
                 if (!$isDisabled and $ele_value[8] == 1) {
                     $renderedComboBox = $this->formulize_renderQuickSelect($form_ele_id, $cachedSourceValuesAutocompleteFile[$sourceValuesQ], $default_value, $default_value_user, $cachedSourceValuesAutocompleteLength[$sourceValuesQ]);
                     $form_ele = new xoopsFormLabel($ele_caption, $renderedComboBox);
                     $form_ele->setDescription(html_entity_decode($ele_desc, ENT_QUOTES));
                 } elseif ($isDisabled) {
                     $disabledOutputText[] = $default_value_user;
                 }
                 // only do this if we're rendering a normal element, that is not disabled
                 if (!$isDisabled and $ele_value[8] == 0) {
                     $form_ele->addOptionArray($cachedSourceValuesQ[$sourceValuesQ]);
                 }
                 // only do this if we're rendering a normal element (may be disabled)
                 if ($ele_value[8] == 0) {
                     foreach ($sourceEntryIds as $thisEntryId) {
                         if (!$isDisabled) {
                             $form_ele->setValue($thisEntryId);
                         } else {
                             $disabledName = $ele_value[1] ? $form_ele_id . "[]" : $form_ele_id;
                             $disabledHiddenValue[] = "<input type=hidden name=\"{$disabledName}\" value=\"{$thisEntryId}\">";
                             $disabledOutputText[] = $cachedSourceValuesQ[$sourceValuesQ][$thisEntryId];
                             // the text value of the option(s) that are currently selected
                         }
                     }
                 }
                 if ($isDisabled) {
                     $form_ele = new XoopsFormLabel($ele_caption, implode(", ", $disabledOutputText) . implode("\n", $disabledHiddenValue));
                     $form_ele->setDescription(html_entity_decode($ele_desc, ENT_QUOTES));
                 } elseif ($ele_value[8] == 0) {
                     // this is a hack because the size attribute is private and only has a getSize and not a setSize, setting the size can only be done through the constructor
                     $count = count($form_ele->getOptions());
                     $size = $ele_value[0];
                     $new_size = $count < $size ? $count : $size;
                     $form_ele->_size = $new_size;
                 }
                 /* ALTERED - 20100318 - freeform - jeff/julian - stop */
             } else {
                 $selected = array();
                 $options = array();
                 $disabledOutputText = array();
                 $disabledHiddenValue = array();
                 $disabledHiddenValues = "";
                 // add the initial default entry, singular or plural based on whether the box is one line or not.
                 if ($ele_value[0] == 1) {
                     $options["none"] = _AM_FORMLINK_PICK;
                 }
                 // set opt_count to 1 if the box is NOT a multiple selection box. -- jwe 7/26/04
                 if ($ele_value[1]) {
                     $opt_count = 0;
                 } else {
                     $opt_count = 1;
                 }
                 $hiddenOutOfRangeValuesToWrite = array();
                 while (is_array($ele_value[2]) and $i = each($ele_value[2])) {
                     // handle requests for full names or usernames -- will only kick in if there is no saved value (otherwise ele_value will have been rewritten by the loadValues function in the form display
                     // note: if the user is about to make a proxy entry, then the list of users displayed will be from their own groups, but not from the groups of the user they are about to make a proxy entry for.  ie: until the proxy user is known, the choice of users for this list can only be based on the current user.  This could lead to confusing or buggy situations, such as users being selected who are outside the groups of the proxy user (who will become the owner) and so there will be an invalid value stored for this element in the db.
                     if ($i['key'] === "{FULLNAMES}" or $i['key'] === "{USERNAMES}") {
                         // ADDED June 18 2005 to handle pulling in usernames for the user's group(s)
                         if ($i['key'] === "{FULLNAMES}") {
                             $nametype = "name";
                         }
                         if ($i['key'] === "{USERNAMES}") {
                             $nametype = "uname";
                         }
                         if (isset($ele_value[2]['{OWNERGROUPS}'])) {
                             $groups = $ele_value[2]['{OWNERGROUPS}'];
                         } else {
                             global $regcode;
                             if ($regcode) {
                                 // if we're dealing with a registration code, determine group membership based on the code
                                 $reggroupsq = q("SELECT reg_codes_groups FROM " . XOOPS_DB_PREFIX . "_reg_codes WHERE reg_codes_code=\"{$regcode}\"");
                                 $groups = explode("&8(%\$", $reggroupsq[0]['reg_codes_groups']);
                                 if ($groups[0] === "") {
                                     unset($groups);
                                 }
                                 // if a code has no groups associated with it, then kill the null value that will be in position 0 in the groups array.
                                 $groups[] = XOOPS_GROUP_USERS;
                                 $groups[] = XOOPS_GROUP_ANONYMOUS;
                             } else {
                                 global $xoopsUser;
                                 $groups = $xoopsUser ? $xoopsUser->getGroups() : array(0 => XOOPS_GROUP_ANONYMOUS);
                             }
                         }
                         $pgroups = array();
                         $declaredUsersGroups = $groups;
                         if ($ele_value[3]) {
                             $scopegroups = explode(",", $ele_value[3]);
                             if (!in_array("all", $scopegroups)) {
                                 $groups = $scopegroups;
                             } else {
                                 // use all
                                 if (!$ele_value[4]) {
                                     // really use all (otherwise, we're just going with all user's groups, so existing value of $groups will be okay
                                     unset($groups);
                                     global $xoopsDB;
                                     $allgroupsq = q("SELECT groupid FROM " . $xoopsDB->prefix("groups"));
                                     //  . " WHERE groupid != " . XOOPS_GROUP_USERS); // removed exclusion of registered users group March 18 2009, since it doesn't make sense in this situation.  All groups should mean everyone, period.
                                     foreach ($allgroupsq as $thisgid) {
                                         $groups[] = $thisgid['groupid'];
                                     }
                                 }
                             }
                         }
                         $namelist = gatherNames($groups, $nametype, $ele_value[6], $ele_value[5], $ele_value[4], $declaredUsersGroups);
                         foreach ($namelist as $auid => $aname) {
                             $options[$auid] = $aname;
                         }
                     } elseif ($i['key'] === "{SELECTEDNAMES}") {
                         // loadValue in formDisplay will create a second option with this key that contains an array of the selected values
                         $selected = $i['value'];
                     } elseif ($i['key'] === "{OWNERGROUPS}") {
                         // do nothing with this piece of metadata that gets set in loadValue, since it's used above
                     } else {
                         // regular selection list....
                         $options[$opt_count] = $myts->stripSlashesGPC($i['key']);
                         if (strstr($i['key'], _formulize_OUTOFRANGE_DATA)) {
                             $hiddenOutOfRangeValuesToWrite[$opt_count] = str_replace(_formulize_OUTOFRANGE_DATA, "", $i['key']);
                             // if this is an out of range value, grab the actual value so we can stick it in a hidden element later
                         }
                         if ($i['value'] > 0) {
                             $selected[] = $opt_count;
                         }
                         $opt_count++;
                     }
                 }
                 $count = count($options);
                 $size = $ele_value[0];
                 $final_size = $count < $size ? $count : $size;
                 $form_ele1 = new XoopsFormSelect($ele_caption, $form_ele_id, $selected, $final_size, $ele_value[1]);
                 $form_ele1->setExtra("onchange=\"javascript:formulizechanged=1;\" jquerytag='{$form_ele_id}'");
                 // must check the options for uitext before adding to the element -- aug 25, 2007
                 foreach ($options as $okey => $ovalue) {
                     $options[$okey] = formulize_swapUIText($ovalue, $this->_ele->getVar('ele_uitext'));
                 }
                 $form_ele1->addOptionArray($options);
                 if ($selected) {
                     if (is_array($selected)) {
                         $hiddenElementName = $ele_value[1] ? $form_ele1->getName() . "[]" : $form_ele1->getName();
                         foreach ($selected as $thisSelected) {
                             $disabledOutputText[] = $options[$thisSelected];
                             $disabledHiddenValue[] = "<input type=hidden name=\"{$hiddenElementName}\" value=\"{$thisSelected}\">";
                         }
                     } elseif ($ele_value[1]) {
                         // need to keep [] in the hidden element name if multiple values are expected, even if only one is chosen
                         $disabledOutputText[] = $options[$selected];
                         $disabledHiddenValue[] = "<input type=hidden name=\"" . $form_ele1->getName() . "[]\" value=\"{$selected}\">";
                     } else {
                         $disabledOutputText[] = $options[$selected];
                         $disabledHiddenValue[] = "<input type=hidden name=\"" . $form_ele1->getName() . "\" value=\"{$selected}\">";
                     }
                 }
                 $renderedHoorvs = "";
                 if (count($hiddenOutOfRangeValuesToWrite) > 0) {
                     foreach ($hiddenOutOfRangeValuesToWrite as $hoorKey => $hoorValue) {
                         $thisHoorv = new xoopsFormHidden('formulize_hoorv_' . $true_ele_id . '_' . $hoorKey, $hoorValue);
                         $renderedHoorvs .= $thisHoorv->render() . "\n";
                         unset($thisHoorv);
                     }
                 }
                 if ($isDisabled) {
                     $disabledHiddenValues = implode("\n", $disabledHiddenValue);
                     // glue the individual value elements together into a set of values
                     $renderedElement = implode(", ", $disabledOutputText);
                 } elseif ($ele_value[8] == 1) {
                     // autocomplete construction: make sure that $renderedElement is the final output of this chunk of code
                     // write the possible values to a cached file so we can look them up easily when we need them,
                     //don't want to actually send them to the browser, since it could be huge,
                     //but don't want to replicate all the logic that has already gathered the values for us, each time there's an ajax request
                     $cachedLinkedOptionsFileName = "formulize_Options_" . str_replace(".", "", microtime(true));
                     formulize_scandirAndClean(XOOPS_ROOT_PATH . "/cache/", "formulize_Options_");
                     $maxLength = 10;
                     $the_values = array();
                     foreach ($options as $id => $text) {
                         $the_values[$id] = trans($text);
                         $thisTextLength = strlen($the_values[$id]);
                         $maxLength = $thisTextLength > $maxLength ? $thisTextLength : $maxLength;
                     }
                     file_put_contents(XOOPS_ROOT_PATH . "/cache/{$cachedLinkedOptionsFileName}", "<?php\n\${$cachedLinkedOptionsFileName} = " . var_export($the_values, true) . ";\n");
                     $defaultSelected = is_array($selected) ? $selected[0] : $selected;
                     $renderedComboBox = $this->formulize_renderQuickSelect($form_ele_id, $cachedLinkedOptionsFileName, $defaultSelected, $options[$defaultSelected], $maxLength);
                     $form_ele2 = new xoopsFormLabel($ele_caption, $renderedComboBox);
                     $renderedElement = $form_ele2->render();
                 } else {
                     // normal element
                     $renderedElement = $form_ele1->render();
                 }
                 $form_ele = new XoopsFormLabel($ele_caption, "<nobr>{$renderedElement}</nobr>\n{$renderedHoorvs}\n{$disabledHiddenValues}\n");
                 $form_ele->setDescription(html_entity_decode($ele_desc, ENT_QUOTES));
             }
             // end of if we have a link on our hands. -- jwe 7/29/04
             // set required validation code
             if ($this->_ele->getVar('ele_req') and !$isDisabled) {
                 $eltname = $form_ele_id;
                 $eltcaption = $ele_caption;
                 $eltmsg = empty($eltcaption) ? sprintf(_FORM_ENTER, $eltname) : sprintf(_FORM_ENTER, $eltcaption);
                 $eltmsg = str_replace('"', '\\"', stripslashes($eltmsg));
                 if ($ele_value[8] == 1) {
                     // Has been edited in order to not allow the user to submit a form when "No match found" or "Choose an Option" is selected from the quickselect box.
                     $form_ele->customValidationCode[] = "\nif ( myform.{$eltname}.value == '' || myform.{$eltname}.value == 'none'  ) {\n window.alert(\"{$eltmsg}\");\n myform.{$eltname}_user.focus();\n return false;\n }\n";
                 } elseif ($ele_value[0] == 1) {
                     $form_ele->customValidationCode[] = "\nif ( myform.{$eltname}.options[0].selected ) {\n window.alert(\"{$eltmsg}\");\n myform.{$eltname}.focus();\n return false;\n }\n";
                 } elseif ($ele_value[0] > 1) {
                     $form_ele->customValidationCode[] = "selection = false;\n";
                     $form_ele->customValidationCode[] = "\nfor(i=0;i<myform.{$eltname}.options.length;i++) {\n";
                     $form_ele->customValidationCode[] = "if(myform.{$eltname}.options[i].selected) {\n";
                     $form_ele->customValidationCode[] = "selection = true;\n";
                     $form_ele->customValidationCode[] = "}\n";
                     $form_ele->customValidationCode[] = "}\n";
                     $form_ele->customValidationCode[] = "if(selection == false) { window.alert(\"{$eltmsg}\");\n myform.{$eltname}.focus();\n return false;\n }\n";
                 }
             }
             if ($isDisabled) {
                 $isDisabled = false;
                 // disabled stuff handled here in element, so don't invoke generic disabled handling below (which is only for textboxes and their variations)
             }
             break;
         case 'checkbox':
             $selected = array();
             $options = array();
             $disabledHiddenValue = array();
             $disabledHiddenValues = "";
             $disabledOutputText = array();
             $opt_count = 1;
             while ($i = each($ele_value)) {
                 $options[$opt_count] = $myts->stripSlashesGPC($i['key']);
                 if ($i['value'] > 0) {
                     $selected[] = $opt_count;
                     $disabledHiddenValue[] = "<input type=hidden name=\"" . $form_ele_id . "[]\" value=\"{$opt_count}\">";
                 }
                 $opt_count++;
             }
             if ($this->_ele->getVar('ele_delim') != "") {
                 $delimSetting = $this->_ele->getVar('ele_delim');
             }
             $delimSetting =& $myts->undoHtmlSpecialChars($delimSetting);
             if ($delimSetting == "br") {
                 $delimSetting = "<br />";
             }
             $hiddenOutOfRangeValuesToWrite = array();
             switch ($delimSetting) {
                 case 'space':
                     $form_ele1 = new XoopsFormCheckBox($ele_caption, $form_ele_id, $selected);
                     $counter = 0;
                     // counter used for javascript that works with 'Other' box
                     while ($o = each($options)) {
                         $o = formulize_swapUIText($o, $this->_ele->getVar('ele_uitext'));
                         $other = $this->optOther($o['value'], $form_ele_id, $entry, $counter, true);
                         if ($other != false) {
                             $form_ele1->addOption($o['key'], _formulize_OPT_OTHER . $other);
                             if (in_array($o['key'], $selected)) {
                                 $disabledOutputText[] = _formulize_OPT_OTHER . $other;
                             }
                         } else {
                             $form_ele1->addOption($o['key'], $o['value']);
                             if (in_array($o['key'], $selected)) {
                                 $disabledOutputText[] = $o['value'];
                             }
                             if (strstr($o['value'], _formulize_OUTOFRANGE_DATA)) {
                                 $hiddenOutOfRangeValuesToWrite[$o['key']] = str_replace(_formulize_OUTOFRANGE_DATA, "", $o['value']);
                                 // if this is an out of range value, grab the actual value so we can stick it in a hidden element later
                             }
                         }
                         $counter++;
                     }
                     $form_ele1->setExtra(" onchange=\"javascript:formulizechanged=1;\" jquerytag=\"{$form_ele_id}\" ");
                     break;
                 default:
                     $form_ele1 = new XoopsFormElementTray($ele_caption, $delimSetting);
                     $counter = 0;
                     // counter used for javascript that works with 'Other' box
                     while ($o = each($options)) {
                         $o = formulize_swapUIText($o, $this->_ele->getVar('ele_uitext'));
                         $other = $this->optOther($o['value'], $form_ele_id, $entry, $counter, true);
                         $t = new XoopsFormCheckBox('', $form_ele_id . '[]', $selected, $delimSetting);
                         if ($other != false) {
                             $t->addOption($o['key'], _formulize_OPT_OTHER . $other);
                             if (in_array($o['key'], $selected)) {
                                 $disabledOutputText[] = _formulize_OPT_OTHER . $other;
                             }
                         } else {
                             $t->addOption($o['key'], $o['value']);
                             if (in_array($o['key'], $selected)) {
                                 $disabledOutputText[] = $o['value'];
                             }
                             if (strstr($o['value'], _formulize_OUTOFRANGE_DATA)) {
                                 $hiddenOutOfRangeValuesToWrite[$o['key']] = str_replace(_formulize_OUTOFRANGE_DATA, "", $o['value']);
                                 // if this is an out of range value, grab the actual value so we can stick it in a hidden element later
                             }
                         }
                         $t->setExtra(" onchange=\"javascript:formulizechanged=1;\" jquerytag=\"{$form_ele_id}\" ");
                         $form_ele1->addElement($t);
                         unset($t);
                         $counter++;
                     }
                     break;
             }
             $renderedHoorvs = "";
             if (count($hiddenOutOfRangeValuesToWrite) > 0) {
                 foreach ($hiddenOutOfRangeValuesToWrite as $hoorKey => $hoorValue) {
                     $thisHoorv = new xoopsFormHidden('formulize_hoorv_' . $true_ele_id . '_' . $hoorKey, $hoorValue);
                     $renderedHoorvs .= $thisHoorv->render() . "\n";
                     unset($thisHoorv);
                 }
             }
             if ($isDisabled) {
                 $disabledHiddenValues = implode("\n", $disabledHiddenValue);
                 // glue the individual value elements together into a set of values
                 $renderedElement = implode(", ", $disabledOutputText);
             } else {
                 $renderedElement = $form_ele1->render();
             }
             $form_ele = new XoopsFormLabel($ele_caption, "{$renderedElement}\n{$renderedHoorvs}\n{$disabledHiddenValues}\n");
             $form_ele->setDescription(html_entity_decode($ele_desc, ENT_QUOTES));
             if ($this->_ele->getVar('ele_req') and !$isDisabled) {
                 $eltname = $form_ele_id;
                 $eltcaption = $ele_caption;
                 $eltmsg = empty($eltcaption) ? sprintf(_FORM_ENTER, $eltname) : sprintf(_FORM_ENTER, $eltcaption);
                 $eltmsg = str_replace('"', '\\"', stripslashes($eltmsg));
                 $form_ele->customValidationCode[] = "selection = true;\n";
                 $form_ele->customValidationCode[] = "checkboxes = \$('[jquerytag={$eltname}]:checked');\n";
                 // need to use this made up attribute here, because there is no good way to select the checkboxes using the name or anything else that XOOPS/Impress is giving us!!
                 $form_ele->customValidationCode[] = "if(checkboxes.length == 0) { window.alert(\"{$eltmsg}\");\n \$('[jquerytag={$eltname}]').focus();\n return false;\n }\n";
             }
             if ($isDisabled) {
                 $isDisabled = false;
                 // disabled stuff handled here in element, so don't invoke generic disabled handling below (which is only for textboxes and their variations)
             }
             break;
         case 'radio':
         case 'yn':
             $selected = '';
             $disabledHiddenValue = "";
             $options = array();
             $opt_count = 1;
             while ($i = each($ele_value)) {
                 switch ($ele_type) {
                     case 'radio':
                         $options[$opt_count] = $myts->stripSlashesGPC($i['key']);
                         $options[$opt_count] = $myts->displayTarea($options[$opt_count]);
                         break;
                     case 'yn':
                         $options[$opt_count] = constant($i['key']);
                         $options[$opt_count] = $myts->stripSlashesGPC($options[$opt_count]);
                         break;
                 }
                 if ($i['value'] > 0) {
                     $selected = $opt_count;
                 }
                 $opt_count++;
             }
             if ($this->_ele->getVar('ele_delim') != "") {
                 $delimSetting = $this->_ele->getVar('ele_delim');
             }
             $delimSetting =& $myts->undoHtmlSpecialChars($delimSetting);
             if ($delimSetting == "br") {
                 $delimSetting = "<br />";
             }
             $hiddenOutOfRangeValuesToWrite = array();
             switch ($delimSetting) {
                 case 'space':
                     $form_ele1 = new XoopsFormRadio('', $form_ele_id, $selected);
                     $counter = 0;
                     while ($o = each($options)) {
                         $o = formulize_swapUIText($o, $this->_ele->getVar('ele_uitext'));
                         $other = $this->optOther($o['value'], $form_ele_id, $entry, $counter);
                         if ($other != false) {
                             $form_ele1->addOption($o['key'], _formulize_OPT_OTHER . $other);
                             if ($o['key'] == $selected) {
                                 $disabledOutputText = _formulize_OPT_OTHER . $other;
                             }
                         } else {
                             $o['value'] = get_magic_quotes_gpc() ? stripslashes($o['value']) : $o['value'];
                             $form_ele1->addOption($o['key'], $o['value']);
                             if ($o['key'] == $selected) {
                                 $disabledOutputText = $o['value'];
                             }
                             if (strstr($o['value'], _formulize_OUTOFRANGE_DATA)) {
                                 $hiddenOutOfRangeValuesToWrite[$o['key']] = str_replace(_formulize_OUTOFRANGE_DATA, "", $o['value']);
                                 // if this is an out of range value, grab the actual value so we can stick it in a hidden element later
                             }
                         }
                         $counter++;
                     }
                     $form_ele1->setExtra("onchange=\"javascript:formulizechanged=1;\"");
                     break;
                 default:
                     $form_ele1 = new XoopsFormElementTray('', $delimSetting);
                     $counter = 0;
                     while ($o = each($options)) {
                         $o = formulize_swapUIText($o, $this->_ele->getVar('ele_uitext'));
                         $t = new XoopsFormRadio('', $form_ele_id, $selected);
                         $other = $this->optOther($o['value'], $form_ele_id, $entry, $counter);
                         if ($other != false) {
                             $t->addOption($o['key'], _formulize_OPT_OTHER . "</label><label>{$other}");
                             // epic hack to terminate radio button's label so it doesn't include the clickable 'other' box!!
                             if ($o['key'] == $selected) {
                                 $disabledOutputText = _formulize_OPT_OTHER . $other;
                             }
                         } else {
                             $o['value'] = get_magic_quotes_gpc() ? stripslashes($o['value']) : $o['value'];
                             $t->addOption($o['key'], $o['value']);
                             if ($o['key'] == $selected) {
                                 $disabledOutputText = $o['value'];
                             }
                             if (strstr($o['value'], _formulize_OUTOFRANGE_DATA)) {
                                 $hiddenOutOfRangeValuesToWrite[$o['key']] = str_replace(_formulize_OUTOFRANGE_DATA, "", $o['value']);
                                 // if this is an out of range value, grab the actual value so we can stick it in a hidden element later
                             }
                         }
                         $t->setExtra("onchange=\"javascript:formulizechanged=1;\"");
                         $form_ele1->addElement($t);
                         unset($t);
                         $counter++;
                     }
                     break;
             }
             $renderedHoorvs = "";
             if (count($hiddenOutOfRangeValuesToWrite) > 0) {
                 foreach ($hiddenOutOfRangeValuesToWrite as $hoorKey => $hoorValue) {
                     $thisHoorv = new xoopsFormHidden('formulize_hoorv_' . $true_ele_id . '_' . $hoorKey, $hoorValue);
                     $renderedHoorvs .= $thisHoorv->render() . "\n";
                     unset($thisHoorv);
                 }
             }
             if ($isDisabled) {
                 $disabledHiddenValue = "<input type=hidden name=\"" . $form_ele_id . "\" value=\"{$selected}\">\n";
                 $renderedElement = $disabledOutputText;
                 // just text for disabled elements
             } else {
                 $renderedElement = $form_ele1->render();
             }
             $form_ele = new XoopsFormLabel($ele_caption, "{$renderedElement}\n{$renderedHoorvs}\n{$disabledHiddenValue}\n");
             $form_ele->setDescription(html_entity_decode($ele_desc, ENT_QUOTES));
             if ($this->_ele->getVar('ele_req') and !$isDisabled) {
                 $eltname = $form_ele_id;
                 $eltcaption = $ele_caption;
                 $eltmsg = empty($eltcaption) ? sprintf(_FORM_ENTER, $eltname) : sprintf(_FORM_ENTER, $eltcaption);
                 $eltmsg = str_replace('"', '\\"', stripslashes($eltmsg));
                 $form_ele->customValidationCode[] = "selection = false;\n";
                 $form_ele->customValidationCode[] = "if(myform.{$eltname}.length) {\n";
                 $form_ele->customValidationCode[] = "for(var i=0;i<myform.{$eltname}.length;i++){\n";
                 $form_ele->customValidationCode[] = "if(myform.{$eltname}[i].checked){\n";
                 $form_ele->customValidationCode[] = "selection = true;\n";
                 $form_ele->customValidationCode[] = "}\n";
                 $form_ele->customValidationCode[] = "}\n";
                 $form_ele->customValidationCode[] = "}\n";
                 $form_ele->customValidationCode[] = "if(selection == false) { window.alert(\"{$eltmsg}\");\n myform.{$eltname}.focus();\n return false;\n }\n";
             }
             if ($isDisabled) {
                 $isDisabled = false;
                 // disabled stuff handled here in element, so don't invoke generic disabled handling below (which is only for textboxes and their variations)
             }
             break;
         case 'date':
             // if there's no value (ie: it's blank) ... OR it's the default value because someone submitted a date field without actually specifying a date, that last part added by jwe 10/23/04
             if ($ele_value[0] == "" or $ele_value[0] == "YYYY-mm-dd") {
                 $form_ele = new XoopsFormTextDateSelect($ele_caption, $form_ele_id, 15, "");
                 $form_ele->setExtra(" onchange=\"javascript:formulizechanged=1;\" jquerytag=\"{$form_ele_id}\" ");
             } else {
                 $form_ele = new XoopsFormTextDateSelect($ele_caption, $form_ele_id, 15, getDateElementDefault($ele_value[0]));
                 $form_ele->setExtra(" onchange=\"javascript:formulizechanged=1;\" jquerytag=\"{$form_ele_id}\" ");
             }
             // end of check to see if the default setting is for real
             // added validation code - sept 5 2007 - jwe
             if ($this->_ele->getVar('ele_req') and !$isDisabled) {
                 $eltname = $form_ele_id;
                 $eltcaption = $ele_caption;
                 $eltmsg = empty($eltcaption) ? sprintf(_FORM_ENTER, $eltname) : sprintf(_FORM_ENTER, $eltcaption);
                 $eltmsg = str_replace('"', '\\"', stripslashes($eltmsg));
                 // parseInt() is used to determine if the element value contains a number
                 // Date.parse() would be better, except that it will fail for dd-mm-YYYY format, ie: 22-11-2013
                 $form_ele->customValidationCode[] = "\nif (isNaN(parseInt(myform.{$eltname}.value))) {\n window.alert(\"{$eltmsg}\");\n myform.{$eltname}.focus();\n return false;\n }\n";
             }
             if (!$isDisabled) {
                 $limit_past = (isset($ele_value["date_limit_past"]) and $ele_value["date_limit_past"] != "");
                 $limit_future = (isset($ele_value["date_limit_future"]) and $ele_value["date_limit_future"] != "");
                 if ($limit_past or $limit_future) {
                     $reference_date = time();
                     if ("new" != $entry) {
                         $entryData = $this->formulize_getCachedEntryData($id_form, $entry);
                         $reference_date = strtotime(display($entryData, "creation_date"));
                     }
                     if ($limit_past) {
                         $form_ele->setExtra(" min-date='" . date("Y-m-d", strtotime("-" . max(0, intval($ele_value["date_past_days"])) . " days", $reference_date)) . "' ");
                     }
                     if ($limit_future) {
                         $form_ele->setExtra(" max-date='" . date("Y-m-d", strtotime("+" . max(0, intval($ele_value["date_future_days"])) . " days", $reference_date)) . "' ");
                     }
                     $form_ele->setExtra(" onchange=\"javascript:formulizechanged=1;check_date_limits('{$form_ele_id}');\" onclick=\"javascript:check_date_limits('{$form_ele_id}');\" onblur=\"javascript:check_date_limits('{$form_ele_id}');\" jquerytag=\"{$form_ele_id}\" ");
                 } else {
                     $form_ele->setExtra(" onchange=\"javascript:formulizechanged=1;\" jquerytag=\"{$form_ele_id}\" ");
                 }
             }
             break;
         case 'sep':
             //$ele_value[0] = $myts->displayTarea($ele_value[0]);
             $ele_value[0] = $myts->xoopsCodeDecode($ele_value[0]);
             $form_ele = new XoopsFormLabel($ele_caption, $ele_value[0]);
             break;
         case 'upload':
             $form_ele = new XoopsFormFile($ele_caption, $form_ele_id, $ele_value[1]);
             break;
             /*
              * Hack by F�lix<INBOX International>
              * Adding colorpicker form element
              */
         /*
          * Hack by F�lix<INBOX International>
          * Adding colorpicker form element
          */
         case 'colorpick':
             if ($ele_value[0] == "") {
                 //print "Bad date";
                 $form_ele = new XoopsFormColorPicker($ele_caption, $form_ele_id, "");
             } else {
                 //print "good date";
                 $form_ele = new XoopsFormColorPicker($ele_caption, $form_ele_id, $ele_value[0]);
             }
             // end of check to see if the default setting is for real
             break;
             /*
              * End of Hack by F�lix<INBOX International>
              * Adding colorpicker form element
              */
         /*
          * End of Hack by F�lix<INBOX International>
          * Adding colorpicker form element
          */
         default:
             if (file_exists(XOOPS_ROOT_PATH . "/modules/formulize/class/" . $ele_type . "Element.php")) {
                 $elementTypeHandler = xoops_getmodulehandler($ele_type . "Element", "formulize");
                 $form_ele = $elementTypeHandler->render($ele_value, $ele_caption, $form_ele_id, $isDisabled, $this->_ele, $entry, $screen);
                 // $ele_value as passed in here, $caption, name that we use for the element in the markup, flag for whether it's disabled or not, element object, entry id number that this element belongs to, $screen is the screen object that was passed in, if any
                 // if form_ele is an array, then we want to treat it the same as an "insertbreak" element, ie: it's not a real form element object
                 if (is_object($form_ele)) {
                     if (!$isDisabled and ($this->_ele->getVar('ele_req') or $this->_ele->alwaysValidateInputs) and $this->_ele->hasData) {
                         // if it's not disabled, and either a declared required element according to the webmaster, or the element type itself always forces validation...
                         $form_ele->customValidationCode = $elementTypeHandler->generateValidationCode($ele_caption, $form_ele_id, $this->_ele, $entry);
                     }
                     $form_ele->setDescription(html_entity_decode($ele_desc, ENT_QUOTES));
                     $isDisabled = false;
                     // the render method must handle providing a disabled output, so as far as the rest of the logic here goes, the element is not disabled but should be rendered as is
                     $baseCustomElementObject = $elementTypeHandler->create();
                     if ($baseCustomElementObject->hasData) {
                         $customElementHasData = true;
                     }
                 }
             } else {
                 return false;
             }
             break;
     }
     // end element-type case
     if (is_object($form_ele) and !$isDisabled and $this->_ele->hasData) {
         if ($previousEntryUI) {
             $previousEntryUIRendered = "&nbsp;&nbsp;" . $previousEntryUI->render();
         } else {
             $previousEntryUIRendered = "";
         }
         // $ele_type is the type value...only put in a cue for certain kinds of elements, and definitely not for blank subforms
         if (substr($form_ele_id, 0, 9) != "desubform" and ($ele_type == "text" or $ele_type == "textarea" or $ele_type == "select" or $ele_type == "radio" or $ele_type == "checkbox" or $ele_type == "date" or $ele_type == "colorpick" or $ele_type == "yn" or $customElementHasData)) {
             $elementCue = "\n<input type=\"hidden\" id=\"decue_" . trim($form_ele_id, "de_") . "\" name=\"decue_" . trim($form_ele_id, "de_") . "\" value=1>\n";
         } else {
             $elementCue = "";
         }
         $form_ele->setExtra(" onchange=\"javascript:formulizechanged=1;\"");
         // reuse caption, put two spaces between element and previous entry UI
         $form_ele_new = new xoopsFormLabel($form_ele->getCaption(), $form_ele->render() . $previousEntryUIRendered . $elementCue);
         $form_ele_new->formulize_element = $this->_ele;
         if ($ele_desc != "") {
             $ele_desc = html_entity_decode($ele_desc, ENT_QUOTES);
             $ele_desc = $myts->makeClickable($ele_desc);
             $form_ele_new->setDescription($ele_desc);
         }
         $form_ele_new->setName($form_ele_id);
         // need to set this as the name, in case it is required and then the name will be picked up by any "required" checks that get done and used in the required validation javascript for textboxes
         if (!empty($form_ele->customValidationCode)) {
             $form_ele_new->customValidationCode = $form_ele->customValidationCode;
         }
         if ($form_ele->isRequired()) {
             $form_ele_new->setRequired();
         }
         return $form_ele_new;
     } elseif (is_object($form_ele) and $isDisabled and $this->_ele->hasData) {
         // element is disabled
         $form_ele = $this->formulize_disableElement($form_ele, $ele_type, $ele_desc);
         return $form_ele;
     } else {
         // form ele is not an object...and/or has no data.  Happens for IBs and for non-interactive elements, like grids.
         return $form_ele;
     }
 }
             ${$k} = $v;
         }
     } elseif (substr($k, 0, 3) == 'de_') {
         $keyParts = explode("_", $k);
         // ANY KEY PASSED THAT IS THE NAME OF A DE_ ELEMENT IN MARKUP, WILL GET UNPACKED AS A VALUE THAT CAN BE SUBBED IN WHEN DOING LOOKUPS LATER ON.
         $passedEntryId = $keyParts[2];
         $passedElementId = $keyParts[3];
         $passedElementObject = $element_handler->get($passedElementId);
         $handle = $passedElementObject->getVar('ele_handle');
         $databaseReadyValue = prepDataForWrite($passedElementObject, $v);
         $databaseReadyValue = $databaseReadyValue === "{WRITEASNULL}" ? NULL : $databaseReadyValue;
         if (substr($v, 0, 9) == "newvalue:") {
             $sendBackValue[$k] = $databaseReadyValue;
         }
         $GLOBALS['formulize_asynchronousFormDataInDatabaseReadyFormat'][$passedEntryId][$handle] = $databaseReadyValue;
         $apiFormatValue = prepvalues($databaseReadyValue, $handle, $passedEntryId);
         // will be an array
         if (is_array($apiFormatValue) and count($apiFormatValue) == 1) {
             $apiFormatValue = $apiFormatValue[0];
             // take the single value if there's only one, same as display function does
         }
         $GLOBALS['formulize_asynchronousFormDataInAPIFormat'][$passedEntryId][$handle] = $apiFormatValue;
     }
 }
 $elementObject = $element_handler->get($elementId);
 $html = "";
 if ($onetoonekey) {
     // the onetoonekey is what changed, not a regular conditional element, so in that case, we need to re-determine the entryId that we should be displaying
     // rebuild entries and fids so it only has the main form entry in it, since we want to get the correct other one-to-one entries back
     $onetooneentries = array($onetoonefid => array($onetooneentries[$onetoonefid][0]));
     $onetoonefids = array($onetoonefid);