/** * Populate the history of entries for the form field if the storage module handles history. * @param I2CE_FormField $form_field * @return boolean */ public function FF_populateHistory($form_field) { $field = $form_field->getName(); $form = $form_field->getContainer(); if (!$form instanceof I2CE_Form) { return false; } $field_name = $form_field->getName(); $fields = $this->lookupField($form->getName(), $form->getId(), array($field_name), false); if (!is_array($fields) || !array_key_exists($field_name, $fields)) { //no data to populate return true; } $last_modified = I2CE_Date::blank(); $entry = new I2CE_Entry($last_modified, 1, 0, $form_field->getFromDB($fields[$field_name])); $form_field->addHistory($entry); return true; }
/** * update value of each instance of a given form field by a sql function call * @param I2CE_FormField $form_field * @param array $where Array of where data * @param string $set_sql sql used to update the field */ public function globalFieldUpdateBySQL($form_field, $where, $set_sql) { if (!$form_field instanceof I2CE_FormField) { I2CE::raiseError("Not passed form_field"); return false; } $formObj = $form_field->getContainer(); if (!$formObj instanceof I2CE_Form) { I2CE::raiseError("No form as a container for the form field"); return false; } $form = $formObj->getName(); if (!$set_sql) { I2CE::raiseError("No SQL provided to update {$form}+{$field}"); return false; } $sub_qry = $this->getRequiredFieldsQuery($form, array($form_field->getName())); $where_qry = $formObj->generateWhereClause($where); if (!$where_qry) { I2CE::raiseError("Could not gernerate where clasue for {$form} by\n" . print_r($where, true)); return false; } $qry = "UPDATE config_alt JOIN ({$sub_qry}) AS data " . "ON parent = CONCAT( '/I2CE/formsData/forms/{$form}/', `{$form}+id` , '/fields' ) " . "SET value = {$set_sql} " . " WHERE (name = '" . $form_field->getName() . "' AND ({$where_qry}))"; //I2CE::raiseError("Updating by $qry"); $res = $this->db->exec($qry); I2CE::getConfig()->clearCache(false); //since we did a write to the DB, need to clear cache if (I2CE::pearError("Cannot update by:\n{$qry}", $res)) { return false; } return true; }
/** * Populate the history of entries for the form field if the storage module handles history. * @param I2CE_FormField $form_field * @return boolean */ public function FF_populateHistory($form_field) { $field = $form_field->getName(); $form = $form_field->getContainer(); if (!$form instanceof I2CE_Form) { return false; } $fieldQry = $this->getRequiredFieldsQuery($form->getName(), array($field), $form->getId()); $result = $this->db->getRow($fieldQry); if (I2CE::pearError($result, "Error populating field {$field} of form " . $form->getName())) { return false; } $ref = strtolower($form->getName() . '+' . $field); $entry = new I2CE_Entry(I2CE_Date::blank(), 1, 0, $form_field->getFromDB($result->{$ref})); $form_field->addHistory($entry); return true; }
/** * Generic (internal fuzzy method for) processing menu for a particular limit style * @param I2CE_FormField $fieldObj the object the fuzzy method was called on * @param array $params are the calling parameters. 0=>array $vals the values we are processing. 1=>string $reportformfield * which defaults to null. in the case of null, we except keys of the form $limit_field in the case of non-null, * we expect $reportformfield to be of the form "$reportform+$field" and then the keys are of the form * "limit_value_FORM_{$reportform}_FIELD_{$field}_LIMIT_{$style}_VALUE_{$field}"; 2=>boolean $strict. which * defaults to true. if true we check that the key is in $vals and if not, return error. * @param string $style The style * @returns mixed. false on failure. on sucess an array of relevant values for this limit style. The keys are * the short version of the keys e.g. 'max' instead of 'limit_value_FORM_person_FIELD_password_LIMIT_between' * */ protected function PROCESS_generic($style, $fieldObj, $vals = array(), $strict = true) { if (!$fieldObj instanceof I2CE_FormField) { return; } if (!array_key_exists($style, self::$menudata)) { I2CE::raiseError("Do not know how to deal with style {$style}"); return false; } $data = array(); foreach (self::$menudata[$style]['fields'] as $field) { if (!is_array($vals) || !array_key_exists($field, $vals)) { if ($strict) { I2CE::raiseError("Value {$field} was not set"); return false; } else { continue; } } if ($field == 'offset') { $offset = $vals['offset']; if (!(is_int($offset) && $offset >= 0 || is_string($offset) && strlen($offset) > 0 && ctype_digit($offset))) { I2CE::raiseError("Bad offset ({$strict})"); if ($strict) { I2CE::raiseError("Invalid offset set"); return false; } else { continue; } } } if ($field == 'allow_null') { //no error checking -- let it eval to true/false } if ($field == 'linked_field') { $formObj = $fieldObj->getContainer(); if ($formObj instanceof I2CE_Form) { $fieldNames = $formObj->getFieldNames(); } else { $fieldNames = array(); } $fieldNames[] = 'parent'; if (!in_array($vals['linked_field'], $fieldNames)) { if ($strict) { I2CE::raiseError("Invalid linked field set" . $vals['linked_field']); return false; } else { continue; } } } $data[$field] = $vals[$field]; } return $data; }
/** * Get/prepare the prepared statement for the given field obj * @param I2CE_FormField $fieldObj * @returns mixed. false om failure. a mdb2 preapred statement object on success */ protected function getFieldSave($fieldObj) { $formName = $fieldObj->getContainer()->getName(); $fieldName = $fieldObj->getName(); if (!array_key_exists($formName, $this->fieldSaves)) { $this->fieldSaves[$formName] = array(); } if (!array_key_exists($fieldName, $this->fieldSaves[$formName])) { $cols = $this->getSaveColumns($fieldObj->getContainer()); $table = $this->getTable($formName); if (!$table || !array_key_exists($fieldName, $cols)) { $this->fieldSaves[$formName][$fieldName] = false; return false; } $stmt = "UPDATE {$table} SET `{$cols[$fieldName]}` = ? WHERE `{$cols['id']}` = ?"; $prepStmt = $this->db->prepare($stmt, array($fieldObj->getMDB2Type(), 'text'), MDB2_PREPARE_MANIP); if (I2CE::pearError($prepStmt, "Error preparing save statemnt for " . $fieldObj->getName() . "\n" . $stmt)) { $prepStmt = false; } $this->fieldSaves[$formName][$fieldName] = $prepStmt; } return $this->fieldSaves[$formName][$fieldName]; }
/** * Populate the history of entries for the form field if the storage module handles history. * @param I2CE_FormField $form_field * @return boolean */ public function FF_populateHistory($form_field) { if ($form_field instanceof I2CE_FormField_STRING_PASS) { return false; } if ($form_field->hasAttribute('populated_history') && $form_field->getAttribute('populated_history')) { return true; } $storageMechanism = self::getStorageMechanism($form_field->getContainer()->getName()); if (!$storageMechanism) { return false; } $form_field->setAttribute('populated_history', 1); return $storageMechanism->FF_populateHistory($form_field); }
/** * update value of each instance of a given form field by a sql function call * @param I2CE_FormField $form_field * @param array $where Array of where data * @param string $set_sql sql used to update the field */ public function globalFieldUpdateBySQL($form_field, $where, $set_sql) { if (!$form_field instanceof I2CE_FormField) { I2CE::raiseError("Not passed form_field"); return false; } $formObj = $form_field->getContainer(); if (!$formObj instanceof I2CE_Form) { I2CE::raiseError("No form as a container for the form field"); return false; } $form = $formObj->getName(); if (!$set_sql) { I2CE::raiseError("No SQL provided to update {$form}+{$field}"); return false; } $where_qry = $formObj->generateWhereClause($where); if (!$where_qry) { I2CE::raiseError("Could not gernerate where clasue for {$form} by\n" . print_r($where, true)); return false; } $this->setupForm($formObj); $referenceCallback = $this->generateReferenceCallback_2($form, $form_field->getName()); if (!$referenceCallback) { return false; } if ($form_field->getName() == 'parent') { $formID = $this->getFormId($form, true); if (!$formID) { //form has not been saved to yet return false; } $last_entry_fields_qry = $this->_getRequiredFieldsQuery($form, array($form_field->getName()), null, false, null, -1, true); if (!$last_entry_fields_qry) { I2CE::raiseError("Could not generage field query for " . $form_field->getName()); return false; } $qry = "UPDATE record JOIN ({$last_entry_fields_qry} ) AS data ON record.id = data.`{$form}+id` SET " . "record.parent_form = SUBSTR({$set_sql},1,LOCATE('|',{$set_sql})-1)," . "record.parent_id = CONVERT(SUBSTR({$set_sql},LOCATE('|',{$set_sql})+1),SIGNED INTEGER) WHERE ( (record.form = {$formID} )AND ({$where_qry}))"; //I2CE::raiseError("Updating by $qry"); $res = $this->db->exec($qry); if (I2CE::pearError("Cannot update by:\n{$qry}", $res)) { return false; } } else { $last_entry_fields_qry = $this->_getRequiredFieldsQuery($form, array($form_field->getName()), null, false, null, -1, true); $entry_fields_qry = $this->_getRequiredFieldsQuery($form, array($form_field->getName()), null, false, null, -1, false); if (!$last_entry_fields_qry) { I2CE::raiseError("Could not generage field query for " . $form_field->getName()); return false; } if (!$entry_fields_qry) { I2CE::raiseError("Could not generage field query for " . $form_field->getName()); return false; } $details = $this->getFormFieldIdAndType($form, $form_field->getName()); if (!is_array($details) || !array_key_exists('type', $details)) { // This shoueld be rare but could happen if no data has been saved yet. Interpret as nothing to update return true; } $qry = "UPDATE last_entry JOIN ({$last_entry_fields_qry} ) AS data ON last_entry.record = data.`{$form}+id` SET " . 'last_entry.`' . $details['type'] . '_value` = ' . $set_sql . ' WHERE (last_entry.form_field = ' . $details['id'] . " AND ({$where_qry}))"; //I2CE::raiseError("Updating by $qry"); $res = $this->db->exec($qry); if (I2CE::pearError("Cannot update by:\n{$qry}", $res)) { return false; } $qry = "UPDATE entry JOIN ({$entry_fields_qry} ) AS data ON entry.record = data.`{$form}+id` SET " . 'entry.`' . $details['type'] . '_value` = ' . $set_sql . ' WHERE (entry.form_field = ' . $details['id'] . " AND ({$where_qry}) )"; //I2CE::raiseError("Updating by $qry"); $res = $this->db->exec($qry); if (I2CE::pearError("Cannot update by:\n{$qry}", $res)) { return false; } } return true; }
/** * Hooked Function to check if a field is unique * @param I2CE_FormField $field_obj */ public function validate_formfield($field_obj) { if (!$field_obj->hasOption('unique') || !$field_obj->getOption('unique') || !$field_obj->isValid()) { return; } if (!$field_obj->hasOption('unique_field')) { return; } $unique = $field_obj->getOption('unique_field'); if (strpos($unique, ':') === false) { //the value is not a mapped thing. this is handled by hooked mehtod defined in I2CE_FormStorage return; } $form_obj = $field_obj->getContainer(); if (!$form_obj instanceof I2CE_Form) { return; } $factory = I2CE_FormFactory::instance(); //$unique should have the form 'unqique_field:form2(+field2):..:..:formM(+fieldM):...:formN //example $unique = 'region:country' or 'region+region+country:country' are the same. // means that $field_obj needs to be unqiue when reseticted to the set of forms within a country and all of its regions // the country and the region that is specified is the // in this case, we need that region is a field of $form_obj //example: $unqiue = 'county:district+region:region:country' or 'county:district:region:country' are the same // means that $field_obj needs to be unique when resitrcicted to a country, any of its regions any of those regions // in this case, we need that county is a field of $form_obj //example: $unqiue = '[location]county:district+region:region:country' or 'county:district:region:country' are the same // means that $field_obj needs to be unique when resitrcicted to a country, any of its regions any of those regions // in this case, we need that location is a field of $form_obj $unique_fields = explode(',', $unique); $matches = null; $names = array(); $main_where = array('operator' => 'FIELD_LIMIT', 'style' => 'equals', 'field' => $field_obj->getName(), 'data' => array('value' => $field_obj->getDBValue())); foreach ($unique_fields as $unique_field) { if ($matches === false) { break; } if (strpos($unique_field, ':') === false) { //this field is not mapped... just handle it as a regular value. if (!($unique_field_obj = $form_obj->getField($unique_field)) instanceof I2CE_FormField) { I2CE::raiseError("Invalid field {$unqiue_field}"); return; } if ($unique_field_obj->hasHeader('default')) { $names[] = $unique_field_obj->getHeader('default'); } else { $names[] = $unique_field_obj->getName(); } $where = array($main_where); if ($unique_field_obj->getDBValue()->isValid()) { $where[] = array('operator' => 'FIELD_LIMIT', 'style' => 'equals', 'field' => $unique_field_obj->getName(), 'data' => array('value' => $unique_field_obj->getDBValue())); } else { $where[] = array('operator' => 'OR', 'operand' => array(0 => array('operator' => 'FIELD_LIMIT', 'style' => 'equals', 'field' => $unique_field_obj->getName(), 'data' => array('value' => $unique_field_obj->getDBValue())), 1 => array('operator' => 'FIELD_LIMIT', 'style' => 'null', 'field' => $unique_field_obj->getName()))); } if (count($where) > 1) { $where = array('operator' => 'AND', 'operand' => $where); } $found = I2CE_FormStorage::search($form_obj->getName(), false, $where); foreach ($found as &$f) { $f = (string) $f; } $matches = count($found) > 0 && in_array((string) $form_obj->getId(), $found, true); } else { $field_path = explode(':', $unique_field); $restricted_field = false; if (preg_match('/^\\[(.*?)\\](.*)$/', $field_path[0])) { $restricted_field = $matches[1]; $field_path[0] = $matches[2]; } else { if (preg_match('/^(.*?)\\+(.*)$/', $field_path[0], $matches)) { $restricted_field = $matches[1]; } else { $restricted_field = $field_path[0]; } } $restricted_field_obj = $form_obj->getField($restricted_field); if (!$restricted_field_obj instanceof I2CE_FormField_MAP) { I2CE::raiseError("Invalid field passed as restricted field for " . $form_obj->getName() . ": {$unique_field}"); return; } if ($restricted_field_obj->hasHeader('default')) { $names[] = $restricted_field_obj->getHeader('default'); } else { $names[] = $restricted_field_obj->getName(); } //now let's split up field_path into the forms and the fields $top_formid = I2CE_List::walkupFieldPath($field_path, $restricted_field_obj->getDBValue()); if ($top_formid === false) { //the value is not set. or inappropriately set. error silently. //this is handled by hooked method defined in I2CE_Module_Form. return; } //now we get all forms under $top_formid defined by the field path $field_name = $field_obj->getName(); $field_val = $field_obj->getDBValue(); $form_id = $form_obj->getID(); $dtree_path = $field_path; array_unshift($dtree_path, $form_obj->getName()); list($top_form, $top_id) = explode('|', $top_formid, 2); $dtree_limits = array($top_form => array('operator' => 'FIELD_LIMIT', 'style' => 'equals', 'field' => 'id', 'data' => array('value' => $top_id)), $form_obj->getName() => $main_where); $options = I2CE_List::buildDataTree($dtree_path, array($form_obj->getName()), $dtree_limits); $options = I2CE_List::flattenDataTree($options); if (count($options) == 1) { // If there's only one match and it is this form then don't block // changes. if ($options[0]['value'] != $form_obj->getNameId()) { $matches = true; } } elseif (count($options) > 1) { $matches = true; } /* array_pop($field_path); $options = I2CE_List::monsterMash( $form_obj->getName(), //facility $restricted_field, //location $top_formid, //country|10 $field_path, //array(county+district,district+region,region+country) $field_name, //name false ); //starts get all facility where location = country|10 // get all regions region|X where region+country = country|10 // this means we need to start with // link_field = country (e.g link_field_path[$len-1] // list(sub_form,sub_link_field) = explode(+,end(subfields) ) == (region,country) // //next get all facility where location = residence|X $option_matches = false; foreach ($options as $id=>$data) { if (array_key_exists($field_name,$data) && ($data[$field_name] == $field_val) && ( $id != $form_id)) { $option_matches =true; break; } } $matches = ($option_matches); */ } } if ($matches === true) { if (count($names) > 1) { $field_obj->setInvalidMessage('unique_fields', null, ' ' . implode(', ', $names)); } else { if (count($names) == 1) { $field_obj->setInvalidMessage('unique_field', null, ' ' . implode(', ', $names)); } else { $field_obj->setInvalidMessage('unique'); } } return; } }