/** * Process the form to the database * * @return string Insert id */ public function processToDB() { $profiler = JProfiler::getInstance('Application'); JDEBUG ? $profiler->mark('processToDb: start') : null; $pluginManager = FabrikWorker::getPluginManager(); $listModel = $this->getListModel(); $origId = $this->prepareForCopy(); $this->formData = $listModel->removeTableNameFromSaveData($this->formData, '___'); JDEBUG ? $profiler->mark('processToDb, submitToDatabase: start') : null; $insertId = $this->storeMainRow ? $this->submitToDatabase($this->rowId) : $this->rowId; $this->updateReferrer($origId, $insertId); $this->setInsertId($insertId); // Store join data JDEBUG ? $profiler->mark('processToDb, processGroups: start') : null; $this->processGroups($insertId); // Enable db join checkboxes in repeat groups to save data JDEBUG ? $profiler->mark('processToDb, processElements: start') : null; $this->processElements(); JDEBUG ? $profiler->mark('processToDb, onBeforeCalculations plugins: start') : null; if (in_array(false, $pluginManager->runPlugins('onBeforeCalculations', $this))) { return $insertId; } JDEBUG ? $profiler->mark('processToDb, doCalculations: start') : null; $this->listModel->doCalculations(); JDEBUG ? $profiler->mark('processToDb: end') : null; return $insertId; }
/** * Process the form to the database * * @return void */ public function processToDB() { $pluginManager = FabrikWorker::getPluginManager(); $app = JFactory::getApplication(); $input = $app->input; $listModel = $this->getListModel(); $item = $listModel->getTable(); $origid = $this->prepareForCopy(); $this->formData = $listModel->removeTableNameFromSaveData($this->formData, '___'); $insertId = $this->storeMainRow ? $this->submitToDatabase($this->rowId) : $this->rowId; $this->updateRefferrer($origid, $insertId); $this->setInsertId($insertId); // Store join data $this->processGroups(); // Enable db join checkboxes in repeat groups to save data $this->processElements(); if (in_array(false, $pluginManager->runPlugins('onBeforeCalculations', $this))) { return $insertId; } $this->listModel->doCalculations(); return $insertId; }
/** * Process the data to the database * * @return null */ public function processToDB() { $listModel = $this->getListModel(); $listModel->setBigSelects(); $item = $listModel->getTable(); $origTableName = $item->db_table_name; $origTableKey = $item->db_primary_key; $pluginManager = FabrikWorker::getPluginManager(); // COPY function should create new records if (array_key_exists('Copy', $this->_formData)) { $this->_rowId = ''; // $$$ rob dont pass in $item->db_primary_key directly into safeColName as its then // modified permanently by this function $k = $item->db_primary_key; $k = FabrikString::safeColNameToArrayKey($k); $origid = $this->_formData[$k]; $this->_formData[$k] = ''; $this->_formData['rowid'] = ''; } /* get an array of the joins to process note this was processJoin() but now preProcessJoin() does the same except no longer stores the results - do this after the main form data has been saved and u have an id to use for the foreign key value*/ $aPreProcessedJoins = $listModel->preProcessJoin(); $joinKeys = array(); /* Needed for plugins that are run after the data is submitted to the db * $$$ rob moved to outside processToDB() as this data is needed regardless of * whether we store in the db or not (for email data) * $this->_formDataWithTableName = $this->_formData; */ $this->_formData = $listModel->removeTableNameFromSaveData($this->_formData, '___'); if ($this->_storeMainRow) { $insertId = $this->submitToDatabase($this->_rowId); } else { $insertId = $this->_rowId; } // Set the redirect page to the form's url if making a copy and set the id // to the new insertid if (array_key_exists('Copy', $this->_formData)) { $u = str_replace('rowid=' . $origid, 'rowid=' . $insertId, JRequest::getVar('HTTP_REFERER', '', 'server')); JRequest::setVar('fabrik_referrer', $u); } $tmpKey = str_replace("`", "", $item->db_primary_key); $joinKeys[$tmpKey] = $insertId; $tmpKey = str_replace('.', '___', $tmpKey); $this->_formData[$tmpKey] = $insertId; $this->_formData[$tmpKey . '_raw'] = $insertId; $this->_formData[FabrikString::shortColName($item->db_primary_key)] = $insertId; $this->_formData[FabrikString::shortColName($item->db_primary_key) . '_raw'] = $insertId; // Need for things like the redirect plugin $this->_fullFormData[$tmpKey] = $insertId; $this->_fullFormData[$tmpKey . '_raw'] = $insertId; $this->_fullFormData['rowid'] = $insertId; $this->_formData['rowid'] = $insertId; $this->_formDataWithTableName['rowid'] = $insertId; $_REQUEST[$tmpKey] = $insertId; $_POST[$tmpKey] = $insertId; $_POST['rowid'] = $insertId; $_REQUEST['rowid'] = $insertId; // $$$ hugh - pretty sure we need to unset 'usekey' now, as it is not relavent to joined data, // and it messing with storeRow of joins JRequest::setVar('usekey', ''); $_POST['usekey'] = ''; $_REQUEST['usekey'] = ''; // Save join data $this->_removeIgnoredData($this->_formData); $aDeleteRecordId = ''; // $$$ hugh - can't do this, as might be repeat element with no data, // like checkbox join with no selections, and no other joins on form if (!isset($this->_formData['join'])) { $this->_formData['join'] = array(); } foreach ($aPreProcessedJoins as $tmpJKey => $aPreProcessedJoin) { if (!array_key_exists('join', $aPreProcessedJoin)) { continue; } $oJoin = $aPreProcessedJoin['join']; // 3.0 test on repeatElement param type if (is_string($oJoin->params)) { $oJoin->params = json_decode($oJoin->params); } if (!isset($oJoin->params->pk) || empty($oJoin->params->pk)) { $cols = $joinDb->getTableColumns($oJoin->table_join, false); $oJoinPk = $oJoin->table_join . '___'; foreach ($cols as $col) { if ($col->Key == 'PRI') { $oJoinPk .= $col->Field; } } } else { $oJoinPk = FabrikString::safeColNameToArrayKey($oJoin->params->pk); } if (array_key_exists('Copy', $this->_formData)) { $this->_rowId = ''; /* $$$ hugh - nope, this is wrong, builds the wrong element name, we need to use the join's PK, not it's FK, * so we need the new 'pk' param if available, or build it from first principles. * So ... moved that code to just above, where we now build the oJoinPk. * $this->_formData['join'][$oJoin->id][$oJoin->table_join . '___' . $oJoin->table_key] = ''; */ if (is_array($this->_formData['join'][$oJoin->id][$oJoinPk])) { foreach ($this->_formData['join'][$oJoin->id][$oJoinPk] as &$ojpk) { $ojpk = ''; } } else { $this->_formData['join'][$oJoin->id][$oJoinPk] = ''; } $this->_formData['rowid'] = ''; } // $$$ rob 22/02/2011 could be a mutlfileupload with no images selected? if (!array_key_exists($oJoin->id, $this->_formData['join'])) { // Continue; } $data = FArrayHelper::getValue($this->_formData['join'], $oJoin->id, array(), 'array'); $groups = $this->getGroupsHiarachy(); $repeatTotals = JRequest::getVar('fabrik_repeat_group', array(0), 'post', 'array'); $joinType = isset($oJoin->params->type) ? $oJoin->params->type : ''; if ((int) $oJoin->group_id !== 0 && $joinType !== 'repeatElement') { $joinGroup = $groups[$oJoin->group_id]; // Find the primary key for the join table $listModel->getTable()->db_table_name = $oJoin->table_join; } else { // Repeat element join $elementModel = $this->getElement($oJoin->element_id, true); /* $$$ hugh - covers case where repeat element is read only, * so isn't submitting any join data, versus editable element * which is empty (like checkbox join), so isn't submitting any data. */ if (!$elementModel->canUse()) { continue; } $joinGroup = JModel::getInstance('Group', 'FabrikFEModel'); /* Need to set the fake group's form and id to that of the current elements form/group * $joinGroup->set('_form', $this); * $joinGroup->setId($elementModel->getGroup()->getId()); */ $joinGroup->getGroup()->id = -1; $joinGroup->getGroup()->is_join = 1; // Set join groups repeat to that of the elements options if ($elementModel->isJoin()) { $joinGroup->getParams()->set('repeat_group_button', 1); // Set repeat count if ($elementModel->getGroup()->isJoin()) { // Repeat element in a repeat group :S $groupJoin = $elementModel->getGroup()->getJoinModel(); $dataPks = JArrayHelper::getValue($data, $oJoin->table_join . '___id', array()); for ($r = 0; $r < count($dataPks); $r++) { $repeatTotals['el' . $elementModel->getId()][$r] = count($dataPks[$r]); } } else { $repeatTotals[$oJoin->group_id] = $elementModel->getJoinRepeatCount($data, $oJoin); } } else { // "Not a repeat element (el id = $oJoin->element_id)<br>"; } // Copy the repeating element into the join group $idElementModel = FabrikHelperElement::makeIdElement($elementModel); $parentElement = FabrikHelperElement::makeParentElement($elementModel); $joinGroup->publishedElements = array(); $joinGroup->publishedElements[''] = array($elementModel, $idElementModel, $parentElement); $data[$oJoin->table_join . '___' . $oJoin->table_join_key] = JArrayHelper::getValue($repeatTotals, $oJoin->group_id, 0) === 0 ? array() : array_fill(0, $repeatTotals[$oJoin->group_id], $insertId); $this->groups[] = $joinGroup; $listModel->getTable()->db_table_name = $oJoin->table_join; } $joinGroupTable = $joinGroup->getGroup(); // $$$ rob - erm is $fields needed? $fields = $listModel->getDBFields($listModel->getTable()->db_table_name); $aKey = $listModel->getPrimaryKeyAndExtra(); if (!$aKey) { // $$$ hugh - most likely a view, so lets not try and store it continue; } $aKey = $aKey[0]; $listModel->getTable()->db_primary_key = $aKey['colname']; $joinDb = $listModel->getDb(); // Back on track if (is_array($data) && array_key_exists($oJoin->table_join . '___' . $oJoin->table_join_key, $data)) { $fullforeginKey = $oJoin->table_join . '___' . $oJoin->table_join_key; $repeatParams = array(); $paramKey = $listModel->getTable()->db_table_name . '___params'; $repeatParams = JArrayHelper::getValue($data, $paramKey, array()); if ($joinGroup->canRepeat()) { // Find out how many repeated groups were entered $repeatedGroupCount = JArrayHelper::getValue($repeatTotals, $oJoin->group_id, 0, 'int'); $elementModels = $joinGroup->getPublishedElements(); $aUpdatedRecordIds = array(); $joinCnn = $listModel->getConnection(); $joinDb = $joinCnn->getDb(); for ($c = 0; $c < $repeatedGroupCount; $c++) { // Get the data for each group and record it seperately $repData = array(); foreach ($elementModels as $elementModel) { $element = $elementModel->getElement(); $n = $elementModel->getFullName(false, true, false); $v = array_key_exists($n, $data) && is_array($data[$n]) && array_key_exists($c, $data[$n]) ? $data[$n][$c] : ''; $repData[$element->name] = $v; $n_raw = $n . '_raw'; // $$$ rob 11/04/2012 - repeat elements don't have raw values so use the value as the default raw value $defaultRaw = $joinType == 'repeatElement' ? $v : ''; $v_raw = array_key_exists($n_raw, $data) && is_array($data[$n_raw]) && array_key_exists($c, $data[$n_raw]) ? $data[$n_raw][$c] : $defaultRaw; $repData[$element->name . '_raw'] = $v_raw; // Store any params set in the individual plug-in (see fabrikfileupload::processUpload()->crop() $thisRepeatParams = JArrayHelper::getValue($repeatParams, $c); if (!is_null($thisRepeatParams) && $elementModel->isJoin()) { $repData['params'] = $thisRepeatParams; } } // $$$ rob didn't work for 2nd joined data set // $repData[$oJoin->table_join_key] = $insertId; unset($repData[$oJoin->table_join_key . '_raw']); $listJoinKey = $oJoin->join_from_table . '.' . $oJoin->table_key; $repData[$oJoin->table_join_key] = JArrayHelper::getValue($joinKeys, $listJoinKey, $insertId); // $$$ rob test for issue with importing joined csv data if (is_array($repData[$oJoin->table_join_key])) { $repData[$oJoin->table_join_key] = $repData[$oJoin->table_join_key][$c]; } // Find the primary key for the join table $item->db_table_name = $oJoin->table_join; // $$$ rob - erm is $fields needed -perhaps just pass $item->db_table_name into getPrimaryKeyAndExtra? $fields = $listModel->getDBFields($item->db_table_name); $aKey = $listModel->getPrimaryKeyAndExtra(); $aKey = $aKey[0]; $item->db_primary_key = $aKey['colname']; $joinRowId = $repData[$item->db_primary_key]; $aDeleteRecordId = $joinDb->Quote($repData[$oJoin->table_join_key]); /* $$$ hugh - need to give it the table name!! * $$$ rob no no no this is not the issue, on SOME setups $item is NOT a reference to $listModel->_table - this is where the issue is * not passing in the correct table name - see notes line 720 for explaination * $listModel->storeRow($repData, $joinRowId, true, $item->db_table_name); */ $listModel->storeRow($repData, $joinRowId, true, $joinGroupTable); if ((int) $joinRowId === 0) { $joinRowId = $listModel->lastInsertId; // $$$ hugh - need to set PK element value for things like email plugin $this->_formData['join'][$oJoin->id][$oJoinPk][$c] = $joinRowId; $this->_formDataWithTableName['join'][$oJoin->id][$oJoinPk][$c] = $joinRowId; $this->_fullFormData['join'][$oJoin->id][$oJoinPk][$c] = $joinRowId; $this->_formData['join'][$oJoin->id][$oJoinPk . '_raw'][$c] = $joinRowId; $this->_formDataWithTableName['join'][$oJoin->id][$oJoinPk . '_raw'][$c] = $joinRowId; } $aUpdatedRecordIds[] = $joinRowId; $tmpKey = $oJoin->table_join . '.' . $oJoin->table_key; $joinKeys[$tmpKey] = $listModel->lastInsertId; } $query = $joinDb->getQuery(true); if ($repeatedGroupCount === 0) { // All repeat group data was removed $query->delete($oJoin->table_join)->where("{$oJoin->table_join_key} = {$insertId}"); } else { // Remove any joins that have been deleted with the groups "delete" button if (!$data) { $query->delete($oJoin->table_join)->where("{$oJoin->table_join_key} = {$aDeleteRecordId}"); } else { $updateIds = implode(',', $aUpdatedRecordIds); $query->delete($oJoin->table_join)->where("!({$item->db_primary_key} IN (" . $updateIds . ")) AND ({$oJoin->table_join_key} = {$aDeleteRecordId})"); } } $joinDb->setQuery($query); $joinDb->query(); } else { /* $$$ hugh - trying to get one-to-one joins working where parent.fk = child.pk (ie where parent points to child) * So ... if we have that situation, what we will see next is * * if (($fullforeginKey != $oJoinPk || (int) $data['rowid'] === 0) * && ($fullforeginKey != "{$oJoin->table_join}___{$oJoin->table_key}" || $oJoin->table_key === $oJoin->table_join_key)) {} * * which we need NOT to be true, otherwise (as per Rob's comment) we'll actually be overwriting the PK. * Then, after that we are going to see ... * if ($fullforeginKey == $oJoinPk) {} * which needs to be true in order for the code to go back and write the new joined rows PK * into the parenjt's FK element. * So ... although it doesn't really make sense, in the one-to-one, parent.fk = child.pk scenario, * we need $fullforeginKey to be the same as $oJoinPk. So we need to work out if the FK is on parent or child ... * Which I think means testing to see if the $oJoinPk == $oJoin->table_join + $oJoin->table_join_key. * if it does, then element the user selected on the joined (child) table is NOT the FK. Which means * the FK is actually the element they selected on the main table (parent). In which case, we need to set * $fullforeginKey = $oJoinPk, which although it isn't, will satisfy the following code!! */ if ($oJoinPk == $oJoin->table_join . '___' . $oJoin->table_join_key) { $fullforeginKey = $oJoinPk; } /* $$$rob test if the joined to table's key (as part of the join) is the same as its primary key * if it is then we dont want to overwrite the foreginkey as we will in fact be overwriting the pk * * $$$ rob - 1) altered now so that this test only returns true if we are editing an existing record * * 2) also test if the foreign key isnt the same as the joins key - hard to explain cos its v confusing but * when you had 2 joins with both of them key'd to the main table things went horribly wrong * if (($fullforeginKey != $oJoinPk || (int) $data['rowid'] === 0) && $fullforeginKey != "{$oJoin->table_join}___{$oJoin->table_key}") { * $$$ rob - 3) hmm (2) was incorrect if your table had a pk called the same as the joined table's fk - eg. * tbl, venture pk venture_id, tbl access, fk venture_id * $$$ hugh - FIXME - something in this is hosing up when creating new one-to-one record where * parent.fk points to child.pk * OK, tried but couldn't understand why the rowid==0 test, which seems to make it impossible to do. Trying without this. * Seems to work (with my change above) without the rowid test, for edit/new */ if ($fullforeginKey != $oJoinPk && ($fullforeginKey != $oJoin->table_join . '___' . $oJoin->table_key || $oJoin->table_key === $oJoin->table_join_key)) { /* $$$ hugh - at this point we are assuming that we have a situation where the FK is on the joined table, * pointing to PK on main table. BUT ... we may have a situation where neither of the selected keys are * a PK, i.e. two records are joined by some other field. In which case we do not want to set the FK val! * So, we need some logic here to handle that! * $$$ hugh - OK, I think this is the test we need to see if neither ends of the join are a PK, * and if so, don't modify any data, as we're joining on some other field that isn't the PK of either table. */ /* $$$ Jaanus: tested succesfully one idea to allow to write next step joins fk, eg when joined table is joined to * joined table. * Yet not tested whether it works also with 3rd, 4th etc step joins. But I can confirm it hasn't any impact to * the rather rarely used "parent.fk points to child.pk" case (that I got fully work only by using mysql trigger). * Anyway, most important is that we got data submission work with joins table1->table2->table3->table# :) * The following "if" prevented it so I commented it out. */ /*if ($oJoin->join_from_table . '.' . $oJoin->table_key == $origTableKey) {*/ $fkVal = JArrayHelper::getValue($joinKeys, $oJoin->join_from_table . '.' . $oJoin->table_key, $insertId); $data[$fullforeginKey] = $fkVal; $data[$fullforeginKey . '_raw'] = $fkVal; // } } if ($item->db_primary_key == '') { return JError::raiseWarning(500, JText::_('COM_FABRIK_MUST_SELECT_PRIMARY_KEY')); } $joinRowId = $data[$item->db_table_name . '___' . $item->db_primary_key]; $data = $listModel->removeTableNameFromSaveData($data); /* $$$ hugh - need to give it the table name!! * $$$ rob no no no this is not the issue, on SOME setups $item is NOT a reference to $listModel->_table - this is where the issue is * not passing in the correct table name - see notes line 720 for explaination * $listModel->storeRow($repData, $joinRowId, true, $item->db_table_name); */ $listModel->storeRow($data, $joinRowId, true, $joinGroupTable); /* $$$ Les: shouldn't we store the row id of the newly stored row back in data????? * Copied the following lines from the equivalent code for repeated groups * ...removing the $c group counter */ if ($joinRowId == '') { $joinRowId = $listModel->lastInsertId; $this->_formData['join'][$oJoin->id][$oJoinPk] = $joinRowId; $this->_formDataWithTableName['join'][$oJoin->id][$oJoinPk] = $joinRowId; $this->_fullFormData['join'][$oJoin->id][$oJoinPk] = $joinRowId; $this->_formData['join'][$oJoin->id][$oJoinPk . '_raw'] = $joinRowId; $this->_formDataWithTableName['join'][$oJoin->id][$oJoinPk . '_raw'] = $joinRowId; } /* $$$rob if the fk was the same as the pk then go back to the main table and * update its fk to match the * pk of the inserted table */ // $$$ hugh - FIXME another point where things aren't right for one-to-one // where parent.fk = child.pk if ($fullforeginKey == $oJoinPk) { $pkVal = $listModel->lastInsertId; $fk = $oJoin->table_key; $this->_formData[$fk] = $pkVal; // Because storeRow takes _raw if the key exists, which it does $this->_formData[$fk . '_raw'] = $pkVal; /* Reset the table's values to the main table * $$$ rob same issues as above with $item not being a reference to $listModel->_table * $item->db_table_name = $origTableName; * $item->db_primary_key = $origTableKey; */ $listModel->getTable()->db_table_name = $origTableName; $listModel->getTable()->db_primary_key = $origTableKey; $listModel->storeRow($this->_formData, $insertId); $insertId = $listModel->lastInsertId; } $tmpKey = $oJoin->table_join . '.' . $oJoin->table_key; $joinKeys[$tmpKey] = $listModel->lastInsertId; } } else { // No join data found so delete all joined records $k = $oJoin->join_from_table . '___' . $oJoin->table_key; $delPkVal = JArrayHelper::getValue($this->_formData, $k, ''); if ($delPkVal !== '') { $query = $joinDb->getQuery(true); $query->delete($oJoin->table_join)->where("({$oJoin->table_join_key} = {$delPkVal})"); $joinDb->setQuery($query); $joinDb->query(); } } } // Testing for saving pages JRequest::setVar('rowid', $insertId); if (in_array(false, $pluginManager->runPlugins('onBeforeCalculations', $this))) { return; } $this->_listModel->doCalculations(); }