$category->category_description = $category_description; if ($category->category_parent != $category_parent || $action == "add") { if ($category_parent > 0) { $q = $db->prepare("SELECT IFNULL(MAX(category_order), 0) AS ord FROM phph_categories WHERE category_parent = ?"); $res = $db->execute($q, $category_parent); } else { $q = $db->prepare("SELECT IFNULL(MAX(category_order)) AS ord FROM phph_categories WHERE category_parent IS NULL"); $res = $db->execute($q, $category_parent); } $row = $res->fetchRow(); $category->category_order = $row['ord'] + 1; } if ($category_parent > 0) { $category->category_parent = $category_parent; } else { $category->category_parent = DB_DataObject_Cast::sql("NULL"); } if ($action == "edit") { $r = $category->update(); } elseif ($action == "add") { $r = $category->insert(); } if (PEAR::isError($r)) { throw new Exception2(_INTERNAL_ERROR, $r->getMessage()); } if (!empty($ref)) { header("Location: " . $ref); } $pane = new HTML_MessagePane("upd", $action == "add" ? _ADMIN_CATEGORY_CREATED : _ADMIN_CATEGORY_UPDATED, "", "a_ok_pane", "a_ok_pane_hdr"); $pane->show(); } catch (Exception2 $e) {
/** * DB_DataObject_FormBuilder::processForm() * * This will take the submitted form data and put it back into the object's properties. * If the primary key is not set or NULL, it will be assumed that you wish to insert a new * element into the database, so DataObject's insert() method is invoked. * Otherwise, an update() will be performed. * <i><b>Careful:</b> If you're using natural keys or cross-referencing tables where you don't have * one dedicated primary key, this will always assume that you want to do an update! As there * won't be a matching entry in the table, no action will be performed at all - the reason * for this behaviour can be very hard to detect. Thus, if you have such a situation in one * of your tables, simply override this method so that instead of the key check it will try * to do a SELECT on the table using the current settings. If a match is found, do an update. * If not, do an insert.</i> * This method is perfect for use with QuickForm's process method. Example: * <code> * if ($form->validate()) { * $form->freeze(); * $form->process(array(&$formGenerator,'processForm'), false); * } * </code> * * If you wish to enforce a special type of query, use the forceQueryType() method. * * Always remember to pass your objects by reference - otherwise, if the operation was * an insert, the primary key won't get updated with the new database ID because processForm() * was using a local copy of the object! * * If a method named "preProcessForm()" exists in your derived class, it will be called before * processForm() starts doing its magic. The data that has been submitted by the form * will be passed to that method as a parameter. * Same goes for a method named "postProcessForm()", with the only difference - you might * have guessed this by now - that it's called after the insert/update operations have * been done. Use this for filtering data, notifying users of changes etc.pp. ... * * @param array $values The values of the submitted form * @return mixed TRUE if database operations were performed, FALSE if not, PEAR_Error on error * @access public */ function processForm($values) { $origDo = clone $this->_do; if ($this->elementNamePrefix !== '' || $this->elementNamePostfix !== '') { $origValues = $values; $values = $this->_getMyValues($values); } $this->debug('<br>...processing form data...<br>'); if ($this->isCallableAndExists($this->preProcessFormCallback)) { call_user_func_array($this->preProcessFormCallback, array(&$values, &$this)); } $editableFields = array_intersect($this->_getUserEditableFields(), array_keys($this->_getFieldsToRender())); $tableFields = $this->_do->table(); if (!is_array($links = $this->_do->links())) { $links = array(); } foreach ($values as $field => $value) { $this->debug('Field ' . $field . ' '); // Double-check if the field may be edited by the user... if not, don't // set the submitted value, it could have been faked! if (in_array($field, $editableFields)) { if (isset($tableFields[$field])) { if ($tableFields[$field] & DB_DATAOBJECT_DATE || in_array($field, $this->dateFields)) { $this->debug('DATE CONVERSION for using callback from ' . $value . ' ...'); if ($this->isCallableAndExists($this->dateToDatabaseCallback)) { $value = call_user_func($this->dateToDatabaseCallback, $value); } else { $this->debug('WARNING: dateToDatabaseCallback not callable', 'FormBuilder'); } } elseif ($tableFields[$field] & DB_DATAOBJECT_TIME || in_array($field, $this->timeFields)) { $this->debug('TIME CONVERSION for using callback from ' . $value . ' ...'); if ($this->isCallableAndExists($this->dateToDatabaseCallback)) { $value = call_user_func($this->dateToDatabaseCallback, $value); } else { $this->debug('WARNING: dateToDatabaseCallback not callable', 'FormBuilder'); } } elseif (is_array($value)) { if (isset($value['tmp_name'])) { $this->debug(' (converting file array) '); $value = $value['name']; //JUSTIN //This is not really a valid assumption IMHO. This should only be done if the type is // date or the field is in dateFields /*} else { $this->debug("DATE CONVERSION using callback from $value ..."); $value = call_user_func($this->dateToDatabaseCallback, $value);*/ } } if (isset($links[$field])) { if ($value == $this->linkNewValueText && $tableFields[$field] & DB_DATAOBJECT_INT) { $value = 0; } elseif ($value === '') { $this->debug('Casting to NULL'); require_once 'DB/DataObject/Cast.php'; $value = DB_DataObject_Cast::sql('NULL'); } } $this->debug('is substituted with "' . print_r($value, true) . '".<br/>'); // See if a setter method exists in the DataObject - if so, use that one if ($this->useMutators && method_exists($this->_do, 'set' . $field)) { $this->_do->{'set' . $field}($value); } else { // Otherwise, just set the property 'normally'... $this->_do->{$field} = $value; } } else { $this->debug('is not a valid field.<br/>'); } } else { $this->debug('is defined not to be editable by the user!<br/>'); } } foreach ($this->booleanFields as $boolField) { if (in_array($boolField, $editableFields) && !isset($values[$boolField])) { if ($this->useMutators && method_exists($this->_do, 'set' . $boolField)) { $this->_do->{'set' . $boolField}(0); } else { $this->_do->{$boolField} = 0; } } } foreach ($tableFields as $field => $type) { if ($type & DB_DATAOBJECT_BOOL && in_array($field, $editableFields) && !isset($values[$field])) { if ($this->useMutators && method_exists($this->_do, 'set' . $field)) { $this->_do->{'set' . $field}(0); } else { $this->_do->{$field} = 0; } } } $dbOperations = true; if ($this->validateOnProcess === true) { $this->debug('Validating data... '); if (is_array($errors = $this->validateData())) { $dbOperations = false; } } $pk = $this->_getPrimaryKey($this->_do); // Data is valid, let's store it! if ($dbOperations) { //take care of linkNewValues /*if (isset($values['__DB_DataObject_FormBuilder_linkNewValue_'])) { foreach ($values['__DB_DataObject_FormBuilder_linkNewValue_'] as $elName => $subTable) {*/ if (isset($this->_form->_linkNewValueForms)) { foreach (array_keys($this->_form->_linkNewValueForms) as $elName) { $subTable = $this->_form->_linkNewValueDOs[$elName]->tableName(); if (isset($values['__DB_DataObject_FormBuilder_linkNewValue__' . $elName])) { if ($values[$elName] == $this->linkNewValueText) { //$this->_form->_prepareForLinkNewValue($elName, $subTable); $ret = $this->_form->_linkNewValueForms[$elName]->process(array(&$this->_form->_linkNewValueFBs[$elName], 'processForm'), false); if (PEAR::isError($ret)) { $this->debug('Error processing linkNewValue for ' . serialize($this->_form->_linkNewValueDOs[$elName])); return PEAR::raiseError('Error processing linkNewValue - Error from processForm: ' . $ret->getMessage(), null, null, null, $this->_form->_linkNewValueDOs[$elName]); } $subPk = $this->_form->_linkNewValueFBs[$elName]->_getPrimaryKey($this->_form->_linkNewValueDOs[$elName]); $this->_do->{$elName} = $values[$elName] = $this->_form->_linkNewValueDOs[$elName]->{$subPk}; } } } } $action = $this->_queryType; if ($this->_queryType == DB_DATAOBJECT_FORMBUILDER_QUERY_AUTODETECT) { // Could the primary key be detected? if ($pk === false) { // Nope, so let's exit and return false. Sorry, you can't store data using // processForm with this DataObject unless you do some tweaking :-( $this->debug('Primary key not detected - storing data not possible.'); return false; } $action = DB_DATAOBJECT_FORMBUILDER_QUERY_FORCEUPDATE; if (!isset($this->_do->{$pk}) || !strlen($this->_do->{$pk})) { $action = DB_DATAOBJECT_FORMBUILDER_QUERY_FORCEINSERT; } } switch ($action) { case DB_DATAOBJECT_FORMBUILDER_QUERY_FORCEINSERT: if (false === ($id = $this->_do->insert())) { $this->debug('Insert of main record failed'); return $this->_raiseDoError('Insert of main record failed', $this->_do); } $this->debug('ID (' . $pk . ') of the new object: ' . $id . '<br/>'); break; case DB_DATAOBJECT_FORMBUILDER_QUERY_FORCEUPDATE: if (false === $this->_do->update($origDo)) { $this->debug('Update of main record failed'); return $this->_raiseDoError('Update of main record failed', $this->_do); } $this->debug('Object updated.<br/>'); break; } // process tripleLinks foreach ($this->tripleLinks as $tripleLink) { $tripleLinkName = $this->_sanitizeFieldName('__tripleLink_' . $tripleLink['table'] . '_' . $tripleLink['fromField'] . '_' . $tripleLink['toField1'] . '_' . $tripleLink['toField2']); if (in_array($tripleLinkName, $editableFields)) { unset($do); $do = DB_DataObject::factory($tripleLink['table']); $fromField = $tripleLink['fromField']; $toField1 = $tripleLink['toField1']; $toField2 = $tripleLink['toField2']; if (isset($values[$tripleLinkName])) { $rows = $values[$tripleLinkName]; } else { $rows = array(); } $links = $do->links(); list($linkTable, $linkField) = explode(':', $links[$fromField]); $do->{$fromField} = $this->_do->{$linkField}; $do->selectAdd(); $do->selectAdd($toField1); $do->selectAdd($toField2); if ($doKey = $this->_getPrimaryKey($do)) { $do->selectAdd($doKey); } if ($this->isCallableAndExists($this->prepareLinkedDataObjectCallback)) { call_user_func_array($this->prepareLinkedDataObjectCallback, array(&$do, $tripleLinkName)); } $oldFieldValues = array(); if ($do->find()) { while ($do->fetch()) { if (isset($rows[$do->{$toField1}]) && isset($rows[$do->{$toField1}][$do->{$toField2}])) { $oldFieldValues[$do->{$toField1}][$do->{$toField2}] = true; } else { if (false === $do->delete()) { $this->debug('Failed to delete tripleLink ' . serialize($do)); return $this->_raiseDoError('Failed to delete tripleLink', $do); } } } } if (count($rows) > 0) { foreach ($rows as $rowid => $row) { if (count($row) > 0) { foreach ($row as $fieldvalue => $on) { if (!isset($oldFieldValues[$rowid]) || !isset($oldFieldValues[$rowid][$fieldvalue])) { unset($do); $do = DB_DataObject::factory($tripleLink['table']); $do->{$fromField} = $this->_do->{$linkField}; $do->{$toField1} = $rowid; $do->{$toField2} = $fieldvalue; if (false === $do->insert()) { $this->debug('Failed to insert tripleLink ' . serialize($do)); return $this->_raiseDoError('Failed to insert tripleLink', $do); } } } } } } } } //process crossLinks foreach ($this->crossLinks as $crossLink) { $crossLinkName = $this->_sanitizeFieldName('__crossLink_' . $crossLink['table'] . '_' . $crossLink['fromField'] . '_' . $crossLink['toField']); if (in_array($crossLinkName, $editableFields)) { unset($do); $do = DB_DataObject::factory($crossLink['table']); $fromField = $crossLink['fromField']; $toField = $crossLink['toField']; if (isset($values[$crossLinkName])) { if ($crossLink['type'] == 'select') { $fieldvalues = array(); foreach ($values[$crossLinkName] as $value) { $fieldvalues[$value] = $value; } } else { $fieldvalues = $values[$crossLinkName]; } } else { $fieldvalues = array(); } /*if (isset($values['__crossLink_'.$crossLink['table'].'__extraFields'])) { $extraFieldValues = $values['__crossLink_'.$crossLink['table'].'__extraFields']; } else { $extraFieldValues = array(); }*/ $links = $do->links(); list($linkTable, $linkField) = explode(':', $links[$fromField]); $do->{$fromField} = $this->_do->{$linkField}; $do->selectAdd(); $do->selectAdd($toField); $do->selectAdd($fromField); if ($doKey = $this->_getPrimaryKey($do)) { $do->selectAdd($doKey); } if ($this->isCallableAndExists($this->prepareLinkedDataObjectCallback)) { call_user_func_array($this->prepareLinkedDataObjectCallback, array(&$do, $crossLinkName)); } $oldFieldValues = array(); if ($do->find()) { while ($do->fetch()) { if (isset($fieldvalues[$do->{$toField}])) { $oldFieldValues[$do->{$toField}] = clone $do; } else { if (false === $do->delete()) { $this->debug('Failed to delete crossLink ' . serialize($do)); return $this->_raiseDoError('Failed to delete crossLink', $do); } } } } if (count($fieldvalues) > 0) { foreach ($fieldvalues as $fieldvalue => $on) { $crossLinkPrefix = $this->elementNamePrefix . $crossLinkName . '__' . $fieldvalue . '_'; $crossLinkPostfix = '_' . $this->elementNamePostfix; if (isset($oldFieldValues[$fieldvalue])) { if (isset($do->fb_crossLinkExtraFields) && (!isset($crossLink['type']) || $crossLink['type'] !== 'select')) { $ret = $this->_extraFieldsFb[$crossLinkPrefix . $crossLinkPostfix]->processForm(isset($origValues) ? $origValues : $values); if (PEAR::isError($ret)) { $this->debug('Failed to process extraFields for crossLink ' . serialize($do)); return PEAR::raiseError('Failed to process extraFields crossLink - Error from processForm: ' . $ret->getMessage(), null, null, null, $do); } } } else { if (isset($do->fb_crossLinkExtraFields) && (!isset($crossLink['type']) || $crossLink['type'] !== 'select')) { $insertValues = isset($origValues) ? $origValues : $values; $insertValues[$crossLinkPrefix . $fromField . $crossLinkPostfix] = $this->_do->{$linkField}; $insertValues[$crossLinkPrefix . $toField . $crossLinkPostfix] = $fieldvalue; $this->_extraFieldsFb[$crossLinkPrefix . $crossLinkPostfix]->fieldsToRender[] = $fromField; $this->_extraFieldsFb[$crossLinkPrefix . $crossLinkPostfix]->fieldsToRender[] = $toField; $ret = $this->_extraFieldsFb[$crossLinkPrefix . $crossLinkPostfix]->processForm($insertValues); if (PEAR::isError($ret)) { $this->debug('Failed to process extraFields for crossLink ' . serialize($do)); return PEAR::raiseError('Failed to process extraFields crossLink - Error from processForm: ' . $ret->getMessage(), null, null, null, $do); } } else { unset($do); $do = DB_DataObject::factory($crossLink['table']); $do->{$fromField} = $this->_do->{$linkField}; $do->{$toField} = $fieldvalue; if (false === $do->insert()) { $this->debug('Failed to insert crossLink ' . serialize($do)); return $this->_raiseDoError('Failed to insert crossLink', $do); } } } } } } } foreach ($this->reverseLinks as $reverseLink) { $elName = $this->_sanitizeFieldName('__reverseLink_' . $reverseLink['table'] . '_' . $reverseLink['field']); if (in_array($elName, $editableFields)) { // Check for subforms if (isset($this->linkElementTypes[$elName]) && $this->linkElementTypes[$elName] == 'subForm') { foreach ($reverseLink['SFs'] as $sfkey => $subform) { // Process each subform that was rendered. if ($subform->validate()) { $ret = $subform->process(array(&$reverseLink['FBs'][$sfkey], 'processForm'), false); if (PEAR::isError($ret)) { $this->debug('Failed to process subForm for reverseLink ' . serialize($reverseLink['FBs'][$sfkey]->_do)); return PEAR::raiseError('Failed to process extraFields crossLink - Error from processForm: ' . $ret->getMessage(), null, null, null, $reverseLink['FBs'][$sfkey]->_do); } } } } else { unset($do); $do = DB_DataObject::factory($reverseLink['table']); if ($this->isCallableAndExists($this->prepareLinkedDataObjectCallback)) { call_user_func_array($this->prepareLinkedDataObjectCallback, array(&$do, $key)); } if (!is_array($rLinks = $do->links())) { $rLinks = array(); } $rPk = $this->_getPrimaryKey($do); $rFields = $do->table(); list($lTable, $lField) = explode(':', $rLinks[$reverseLink['field']]); if ($do->find()) { while ($do->fetch()) { unset($newVal); if (isset($values[$elName][$do->{$rPk}])) { if ($do->{$reverseLink['field']} != $this->_do->{$lField}) { $do->{$reverseLink['field']} = $this->_do->{$lField}; if (false === $do->update()) { $this->debug('Failed to update reverseLink ' . serialize($do)); return $this->_raiseDoError('Failed to update reverseLink', $do); } } } elseif ($do->{$reverseLink['field']} == $this->_do->{$lField}) { if (isset($reverseLink['defaultLinkValue'])) { $do->{$reverseLink['field']} = $reverseLink['defaultLinkValue']; if (false === $do->update()) { $this->debug('Failed to update reverseLink ' . serialize($do)); return $this->_raiseDoError('Failed to update reverseLink', $do); } } else { if ($rFields[$reverseLink['field']] & DB_DATAOBJECT_NOTNULL) { //ERROR!! $this->debug('Checkbox in reverseLinks unset when link field may not be null'); } else { require_once 'DB/DataObject/Cast.php'; $do->{$reverseLink['field']} = DB_DataObject_Cast::sql('NULL'); if (false === $do->update()) { $this->debug('Failed to update reverseLink ' . serialize($do)); return $this->_raiseDoError('Failed to update reverseLink', $do); } } } } } } } } } } if ($this->isCallableAndExists($this->postProcessFormCallback)) { call_user_func_array($this->postProcessFormCallback, array(&$values, &$this)); } return $dbOperations; }
/** * DB_DataObject_FormBuilder::processForm() * * This will take the submitted form data and put it back into the object's properties. * If the primary key is not set or NULL, it will be assumed that you wish to insert a new * element into the database, so DataObject's insert() method is invoked. * Otherwise, an update() will be performed. * <i><b>Careful:</b> If you're using natural keys or cross-referencing tables where you don't have * one dedicated primary key, this will always assume that you want to do an update! As there * won't be a matching entry in the table, no action will be performed at all - the reason * for this behaviour can be very hard to detect. Thus, if you have such a situation in one * of your tables, simply override this method so that instead of the key check it will try * to do a SELECT on the table using the current settings. If a match is found, do an update. * If not, do an insert.</i> * This method is perfect for use with QuickForm's process method. Example: * <code> * if ($form->validate()) { * $form->freeze(); * $form->process(array(&$formGenerator,'processForm'), false); * } * </code> * * If you wish to enforce a special type of query, use the forceQueryType() method. * * Always remember to pass your objects by reference - otherwise, if the operation was * an insert, the primary key won't get updated with the new database ID because processForm() * was using a local copy of the object! * * If a method named "preProcessForm()" exists in your derived class, it will be called before * processForm() starts doing its magic. The data that has been submitted by the form * will be passed to that method as a parameter. * Same goes for a method named "postProcessForm()", with the only difference - you might * have guessed this by now - that it's called after the insert/update operations have * been done. Use this for filtering data, notifying users of changes etc.pp. ... * * @param array $values The values of the submitted form * @param string $queryType If the standard query behaviour ain't good enough for you, you can force a certain type of query * @return boolean TRUE if database operations were performed, FALSE if not * @access public */ function processForm($values) { if ($this->elementNamePrefix !== '' || $this->elementNamePostfix !== '') { $values = $this->_getMyValues($values); } $this->debug('<br>...processing form data...<br>'); if (method_exists($this->_do, 'preprocessform')) { if ($this->useCallTimePassByReference) { $this->_do->preProcessForm(&$values); } else { $this->_do->preProcessForm($values); } } $editableFields = $this->_getUserEditableFields(); $tableFields = $this->_do->table(); $links = $this->_do->links(); foreach ($values as $field => $value) { $this->debug('Field ' . $field . ' '); // Double-check if the field may be edited by the user... if not, don't // set the submitted value, it could have been faked! if (in_array($field, $editableFields)) { if (isset($tableFields[$field])) { if ($tableFields[$field] & DB_DATAOBJECT_DATE || in_array($field, $this->dateFields)) { $this->debug('DATE CONVERSION for using callback from ' . $value . ' ...'); $value = call_user_func($this->dateToDatabaseCallback, $value); } elseif ($tableFields[$field] & DB_DATAOBJECT_TIME || in_array($field, $this->timeFields)) { $this->debug('TIME CONVERSION for using callback from ' . $value . ' ...'); $value = call_user_func($this->dateToDatabaseCallback, $value); } elseif (is_array($value)) { if (isset($value['tmp_name'])) { $this->debug(' (converting file array) '); $value = $value['name']; //JUSTIN //This is not really a valid assumption IMHO. This should only be done if the type is // date or the field is in dateFields /*} else { $this->debug("DATE CONVERSION using callback from $value ..."); $value = call_user_func($this->dateToDatabaseCallback, $value);*/ } } if (is_array($links) && isset($links[$field])) { if ($value === '') { $this->debug('Casting to NULL'); require_once 'DB/DataObject/Cast.php'; $value = DB_DataObject_Cast::sql('NULL'); } } $this->debug('is substituted with "' . print_r($value, true) . '".<br/>'); // See if a setter method exists in the DataObject - if so, use that one if (method_exists($this->_do, 'set' . $field)) { $this->_do->{'set' . $field}($value); } else { // Otherwise, just set the property 'normally'... $this->_do->{$field} = $value; } } else { $this->debug('is not a valid field.<br/>'); } } else { $this->debug('is defined not to be editable by the user!<br/>'); } } foreach ($this->booleanFields as $boolField) { if (!isset($values[$boolField])) { $this->_do->{$boolField} = 0; } } $dbOperations = true; if ($this->validateOnProcess === true) { $this->debug('Validating data... '); if (is_array($this->validateData())) { $dbOperations = false; } } $pk = $this->_getPrimaryKey($this->_do); // Data is valid, let's store it! if ($dbOperations) { $action = $this->_queryType; if ($this->_queryType == DB_DATAOBJECT_FORMBUILDER_QUERY_AUTODETECT) { // Could the primary key be detected? if ($pk === false) { // Nope, so let's exit and return false. Sorry, you can't store data using // processForm with this DataObject unless you do some tweaking :-( $this->debug('Primary key not detected - storing data not possible.'); return false; } $action = DB_DATAOBJECT_FORMBUILDER_QUERY_FORCEUPDATE; if (!isset($this->_do->{$pk}) || !strlen($this->_do->{$pk})) { $action = DB_DATAOBJECT_FORMBUILDER_QUERY_FORCEINSERT; } } switch ($action) { case DB_DATAOBJECT_FORMBUILDER_QUERY_FORCEINSERT: $id = $this->_do->insert(); $this->debug('ID (' . $pk . ') of the new object: ' . $id . '<br/>'); break; case DB_DATAOBJECT_FORMBUILDER_QUERY_FORCEUPDATE: $this->_do->update(); $this->debug('Object updated.<br/>'); break; } //triple/crossLinks only work when a primark key is set if ($pk && isset($this->_do->{$pk}) && strlen($this->_do->{$pk})) { // process tripleLinks foreach ($this->tripleLinks as $tripleLink) { $do = DB_DataObject::factory($tripleLink['table']); $links = $do->links(); $fromField = $tripleLink['fromField']; $toField1 = $tripleLink['toField1']; $toField2 = $tripleLink['toField2']; if (isset($values['__tripleLink_' . $tripleLink['table']])) { $rows = $values['__tripleLink_' . $tripleLink['table']]; } else { $rows = array(); } $do->{$fromField} = $this->_do->{$pk}; $do->selectAdd(); $do->selectAdd($toField1); $do->selectAdd($toField2); $do->find(); $oldFieldValues = array(); while ($do->fetch()) { if (isset($rows[$do->{$toField1}]) && in_array($do->{$toField2}, $rows[$do->{$toField1}])) { $oldFieldValues[$do->{$toField1}][$do->{$toField2}] = true; } else { $do->delete(); } } if (count($rows) > 0) { foreach ($rows as $rowid => $row) { if (count($row) > 0) { foreach ($row as $fieldvalue) { if (!isset($oldFieldValues[$rowid]) || !isset($oldFieldValues[$rowid][$fieldvalue])) { $do = DB_DataObject::factory($tripleLink['table']); $do->{$fromField} = $this->_do->{$pk}; $do->{$toField1} = $rowid; $do->{$toField2} = $fieldvalue; $do->insert(); } } } } } } //process crossLinks foreach ($this->crossLinks as $crossLink) { $do = DB_DataObject::factory($crossLink['table']); $links = $do->links(); $fromField = $crossLink['fromField']; $toField = $crossLink['toField']; if (isset($values['__crossLink_' . $crossLink['table']])) { $fieldvalues = $values['__crossLink_' . $crossLink['table']]; } else { $fieldvalues = array(); } if (isset($values['__crossLink_' . $crossLink['table'] . '__extraFields'])) { $extraFieldValues = $values['__crossLink_' . $crossLink['table'] . '__extraFields']; } else { $extraFieldValues = array(); } $do->{$fromField} = $this->_do->{$pk}; $do->selectAdd(); $do->selectAdd($toField); $do->selectAdd($fromField); if ($doKeys = $do->sequenceKey()) { $do->selectAdd($doKeys[0]); } $do->find(); $oldFieldValues = array(); while ($do->fetch()) { if (isset($fieldvalues[$do->{$toField}])) { $oldFieldValues[$do->{$toField}] = clone $do; } else { $do->delete(); } } if (count($fieldvalues) > 0) { foreach ($fieldvalues as $fieldvalue) { if (isset($oldFieldValues[$fieldvalue])) { if (isset($do->fb_crossLinkExtraFields)) { $do = $oldFieldValues[$fieldvalue]; $update = false; foreach ($do->fb_crossLinkExtraFields as $extraField) { if ($do->{$extraField} !== $extraFieldValues[$fieldvalue][$extraField]) { $update = true; $do->{$extraField} = $extraFieldValues[$fieldvalue][$extraField]; } } if ($update) { $do->update(); } } } else { $do = DB_DataObject::factory($crossLink['table']); $do->{$fromField} = $this->_do->{$pk}; $do->{$toField} = $fieldvalue; if (isset($do->fb_crossLinkExtraFields)) { foreach ($do->fb_crossLinkExtraFields as $extraField) { $do->{$extraField} = $extraFieldValues[$do->{$toField}][$extraField]; } } $do->insert(); } } } } foreach ($this->reverseLinks as $reverseLink) { $elName = '__reverseLink_' . $reverseLink['table'] . '_' . $reverseLink['field']; $do = DB_DataObject::factory($reverseLink['table']); if (method_exists($this->_do, 'preparelinkeddataobject')) { if ($this->useCallTimePassByReference) { $this->_do->prepareLinkedDataObject(&$do, $key); } else { $this->_do->prepareLinkedDataObject($do, $key); } } $rLinks = $do->links(); $rPk = $this->_getPrimaryKey($do); $rFields = $do->table(); list($lTable, $lField) = explode(':', $rLinks[$reverseLink['field']]); if ($do->find()) { while ($do->fetch()) { unset($newVal); if (isset($values[$elName][$do->{$rPk}])) { if ($do->{$reverseLink['field']} != $this->_do->{$lField}) { $do->{$reverseLink['field']} = $this->_do->{$lField}; $do->update(); } } elseif ($do->{$reverseLink['field']} == $this->_do->{$lField}) { if (isset($reverseLink['defaultLinkValue'])) { $do->{$reverseLink['field']} = $reverseLink['defaultLinkValue']; $do->update(); } else { if ($rFields[$reverseLink['field']] & DB_DATAOBJECT_NOTNULL) { //ERROR!! $this->debug('Checkbox in reverseLinks unset when link field may not be null'); } else { require_once 'DB/DataObject/Cast.php'; $do->{$reverseLink['field']} = DB_DataObject_Cast::sql('NULL'); $do->update(); } } } } } } } } if (method_exists($this->_do, 'postprocessform')) { if ($this->useCallTimePassByReference) { $this->_do->postProcessForm(&$values); } else { $this->_do->postProcessForm($values); } } return $dbOperations; }