function copy($record, $vals = array(), $force = true) { foreach ($vals as $k => $v) { if (strpos($v, '=') === 0) { $vals[$k] = $this->evaluate($v, $k, $record); } } $del = $record->_table->getDelegate(); if (isset($del) and method_exists($del, 'beforeCopy')) { $res = $del->beforeCopy($record, $vals); if (PEAR::isError($res)) { return $res; } } $this->warnings = array(); // Step 1: Load the record - it has been passed // Step 2: build sql query to copy the record $query = $this->buildCopyQuery($record, $vals, $force); if (PEAR::isError($query)) { return $query; } $res = df_query($query); if (!$res) { return PEAR::raiseError("Failed to copy record '" . $record->getTitle() . "' due to an SQL error:" . xf_db_error()); } if (PEAR::isError($res)) { return $res; } $ret = null; if ($auto_field_id = $record->_table->getAutoIncrementField()) { $insert_id = df_insert_id(); $copied =& df_get_record($record->_table->tablename, array($auto_field_id => $insert_id)); $ret = $copied; } else { $ret = new Dataface_Record($record->_table->tablename, array_merge($record->vals(), $vals)); } if (isset($del) and method_exists($del, 'afterCopy')) { $res = $del->afterCopy($record, $ret); if (PEAR::isError($res)) { return $res; } } return $ret; }
/** * Takes an array of SQL query strings and performs them sequentially. * Will replace special value "__Tablename__auto_increment__" with the insert_id * from the table "Tablename" if one of the provided sql queries inserts a record * into Tablename. * * @param $sql An associative array [Table name] -> [SQL Query] of sql statements * to be executed. */ function performSQL($sql) { $ids = array(); $queue = $sql; $names = array_keys($sql); $tables = implode('|', $names); $skips = 0; // keep track of number of consecutive times we skip an iteration so we know when we have reached // a deadlock. if (func_num_args() >= 2) { $duplicates =& func_get_arg(1); if (!is_array($duplicates)) { trigger_error(df_translate('scripts.Dataface.IO.performSQL.ERROR_PARAMETER_2', "In Dataface_IO::performSQL() 2nd argument is expected to be an array but received '" . get_class($duplicates) . "'.", array('class' => get_class($duplicates))) . Dataface_Error::printStackTrace(), E_USER_ERROR); } } else { $duplicates = array(); } $queryAttempts = array(); $numQueries = count($queue); while (count($queue) > 0 and $skips < $numQueries) { $current_query = array_shift($queue); $current_table = array_shift($names); if (!isset($queryAttempts[$current_query])) { $queryAttempts[$current_query] = 1; } else { $queryAttempts[$current_query]++; } $matches = array(); if (preg_match('/__(' . $tables . ')__auto_increment__/', $current_query, $matches)) { $table = $matches[1]; if (isset($ids[$table])) { $current_query = preg_replace('/__' . $table . '__auto_increment__/', $ids[$table], $current_query); } else { array_push($queue, $current_query); array_push($names, $current_table); $skips++; continue; } } //$res = mysql_query($current_query, $this->_table->db); $res = $this->dbObj->query($current_query, $this->_table->db, $this->lang); if (!$res || PEAR::isError($res)) { if (in_array(mysql_errno($this->_table->db), array(MYSQL_ER_DUP_KEY, MYSQL_ER_DUP_ENTRY))) { /* * This is a duplicate record (ie: it already exists) */ $duplicates[] = $current_table; } else { if ($queryAttempts[$current_query] < 3 and in_array(mysql_errno($this->_table->db), array(MYSQL_ER_NO_REFERENCED_ROW, MYSQL_ER_NO_REFERENCED_ROW_2, MYSQL_ER_ROW_IS_REFERENCED_2))) { /** * There is a foreign key constraint that is preventing us from inserting * this row. Perhaps we are just adding this row in the wrong order. * Let's re-add it to the queue. */ array_push($queue, $current_query); array_push($names, $current_table); } else { if (in_array(mysql_errno($this->_table->db), array(MYSQL_ER_NO_REFERENCED_ROW, MYSQL_ER_NO_REFERENCED_ROW_2))) { /* THis failed due to a foreign key constraint. */ $err = PEAR::raiseError(sprintf(df_translate('scripts.Dataface.IO.performSQL.ERROR_FOREIGN_KEY', 'Failed to save record because a foreign key constraint failed: %s'), mysql_error(df_db())), DATAFACE_E_NOTICE); error_log($err->toString()); return $err; } $err = PEAR::raiseError(DATAFACE_TABLE_SQL_ERROR, null, null, null, df_translate('scripts.Dataface.IO.performSQL.ERROR_PERFORMING_QUERY', "Error performing query '{$current_query}' on line " . __LINE__ . " of file " . __FILE__ . ": <br/>", array('line' => __LINE__, 'file' => __FILE__, 'current_query' => $current_query)) . mysql_errno($this->_table->db) . ': ' . mysql_error($this->_table->db)); trigger_error($err->toString() . Dataface_Error::printStackTrace(), E_USER_ERROR); } } } $ids[$current_table] = df_insert_id(); self::touchTable($current_table); $skips = 0; } $this->insertids = $ids; return true; }