WT_DB::exec("ROLLBACK"); echo '<span class="error">', WT_I18N::translate('Error: converting GEDCOM files from %s encoding to UTF-8 encoding not currently supported.', $charset), '</span>'; $controller->addInlineJavascript('jQuery("#actions' . $gedcom_id . '").toggle();'); exit; } $first_time = false; // Re-fetch the data, now that we have performed character set conversion. $data = WT_DB::prepare("SELECT gedcom_chunk_id, REPLACE(chunk_data, '\r', '\n') AS chunk_data" . " FROM `##gedcom_chunk`" . " WHERE gedcom_chunk_id=?")->execute(array($data->gedcom_chunk_id))->fetchOneRow(); } if (!$data) { break; } try { // Import all the records in this chunk of data foreach (preg_split('/\\n+(?=0)/', $data->chunk_data) as $rec) { import_record($rec, $gedcom_id, false); } // Mark the chunk as imported WT_DB::prepare("UPDATE `##gedcom_chunk` SET imported=TRUE WHERE gedcom_chunk_id=?")->execute(array($data->gedcom_chunk_id)); } catch (PDOException $ex) { WT_DB::exec("ROLLBACK"); if ($ex->getCode() == '40001') { // "SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction" // The documentation says that if you get this error, wait and try again..... sleep(1); $controller->addInlineJavascript('jQuery("#import' . $gedcom_id . '").load("import.php?gedcom_id=' . $gedcom_id . '&u=' . uniqid() . '");'); } else { // A fatal error. Nothing we can do? echo '<span class="error">', $ex->getMessage(), '</span>'; $controller->addInlineJavascript('jQuery("#actions' . $gedcom_id . '").toggle();'); }
/** * Convert an ANSI encoded file to UTF8 * * converts an ANSI or ANSEL encoded file to UTF-8 * @see is_ansi() */ function importGedcom() { // -- array of names if (!isset($indilist)) { $indilist = array(); } if (!isset($famlist)) { $famlist = array(); } $sourcelist = array(); $otherlist = array(); //-- as we are importing the file, a new file is being written to store any //-- changes that might have occurred to the gedcom file (eg. conversion of //-- media objects). After the import is complete the new file is //-- copied over the old file. //-- The records are written during the import_record() method and the //-- update_media() method //-- open handle to read file $fpged = fopen($this->mInfo['g_path'], "rb"); //-- open handle to write changed file $fpnewged = fopen(STORAGE_PKG_PATH . PHPGEDVIEW_PKG_NAME . "/" . basename($this->mInfo['g_path']) . ".new", "ab"); $BLOCK_SIZE = 1024 * 4; //-- 4k bytes per read (4kb is usually the page size of a virtual memory system) $fcontents = ""; $TOTAL_BYTES = 0; $place_count = 0; $date_count = 0; $media_count = 0; $MAX_IDS = array(); $listtype = array(); $_SESSION["resumed"] = 1; while (!feof($fpged)) { $temp = fread($fpged, $BLOCK_SIZE); $fcontents .= $temp; $TOTAL_BYTES += strlen($temp); $pos1 = 0; while ($pos1 !== false) { //-- find the start of the next record $pos2 = strpos($fcontents, "\n0", $pos1 + 1); while (!$pos2 && !feof($fpged)) { $temp = fread($fpged, $BLOCK_SIZE); $fcontents .= $temp; $TOTAL_BYTES += strlen($temp); $pos2 = strpos($fcontents, "\n0", $pos1 + 1); } //-- pull the next record out of the file if ($pos2) { $indirec = substr($fcontents, $pos1, $pos2 - $pos1); } else { $indirec = substr($fcontents, $pos1); } //-- remove any extra slashes $indirec = preg_replace("/\\\\/", "/", $indirec); //-- import anything that is not a blob if (preg_match("/\n1 BLOB/", $indirec) == 0) { import_record(trim($indirec), false); // $place_count += update_places( $gid, $this->mGEDCOMId, $indirec ); // $date_count += update_dates( $gid, $this->mGEDCOMId, $indirec ); } //-- move the cursor to the start of the next record $pos1 = $pos2; } $fcontents = substr($fcontents, $pos2); } fclose($fpged); fclose($fpnewged); //-- as we are importing the file, a new file is being written to store any //-- changes that might have occurred to the gedcom file (eg. conversion of //-- media objects). After the import is complete the new file is //-- copied over the old file. //-- The records are written during the import_record() method and the //-- update_media() method $res = @copy($this->mInfo['g_path'], PHPGEDVIEW_PKG_NAME . basename($GEDCOM_FILE) . ".bak"); if (!$res) { $this->mError = "Unable to create backup of the GEDCOM file at " . STORAGE_PKG_PATH . PHPGEDVIEW_PKG_NAME . "/" . basename($this->mInfo['g_path']) . ".bak"; } //unlink($GEDCOM_FILE); $res = @copy(STORAGE_PKG_PATH . PHPGEDVIEW_PKG_NAME . "/" . basename($this->mInfo['g_path']) . ".new", $this->mInfo['g_path']); if (!$res) { $this->mError = "Unable to copy updated GEDCOM file " . STORAGE_PKG_PATH . PHPGEDVIEW_PKG_NAME . "/" . basename($this->mInfo['g_path']) . ".new to " . $this->mInfo['g_path']; } else { global $gBitUser; @unlink(STORAGE_PKG_PATH . PHPGEDVIEW_PKG_NAME . "/" . basename($this->mInfo['g_path']) . ".new"); $logline = $this->addToLog($this->mInfo['g_path'] . " updated by >" . $gBitUser->getDisplayName() . "<"); // if (!empty ($COMMIT_COMMAND)) // check_in($logline, $GEDCOM_FILE, $INDEX_DIRECTORY); } }
/** * update a record in the database * @param string $gedrec */ function update_record($gedrec, $delete = false) { global $TBLPREFIX, $GEDCOM, $FILE, $gBitDb; if (empty($FILE)) { $FILE = $GEDCOM; } if (preg_match('/^0 @(' . PGV_REGEX_XREF . ')@ (' . PGV_REGEX_TAG . ')/', $gedrec, $match)) { list(, $gid, $type) = $match; } else { print "ERROR: Invalid gedcom record."; return false; } $ged_id = get_id_from_gedcom($FILE); // TODO deleting unlinked places can be done more efficiently in a single query $placeids = $gBitDb->getOne("SELECT pl_p_id FROM {$TBLPREFIX}placelinks WHERE pl_gid=? AND pl_file=?", array($gid, $ged_id)); $gBitDb->query("DELETE FROM {$TBLPREFIX}placelinks WHERE pl_gid=? AND pl_file=?", array($gid, $ged_id)); $gBitDb->query("DELETE FROM {$TBLPREFIX}dates WHERE d_gid =? AND d_file =?", array($gid, $ged_id)); //-- delete any unlinked places foreach ($placeids as $p_id) { $num = $gBitDb->getOne("SELECT count(pl_p_id) FROM {$TBLPREFIX}placelinks WHERE pl_p_id=? AND pl_file=?", array($p_id, $ged_id)); if ($num == 0) { $gBitDb->query("DELETE FROM {$TBLPREFIX}places WHERE p_id=? AND p_file=?", array($p_id, $ged_id)); } } $gBitDb->query("DELETE FROM {$TBLPREFIX}media_mapping WHERE mm_gid=? AND mm_gedfile=?", array($gid, $ged_id)); $gBitDb->query("DELETE FROM {$TBLPREFIX}remotelinks WHERE r_gid=? AND r_file=?", array($gid, $ged_id)); $gBitDb->query("DELETE FROM {$TBLPREFIX}name WHERE n_id=? AND n_file=?", array($gid, $ged_id)); $gBitDb->query("DELETE FROM {$TBLPREFIX}link WHERE l_from=? AND l_file=?", array($gid, $ged_id)); switch ($type) { case 'INDI': $gBitDb->query("DELETE FROM {$TBLPREFIX}individuals WHERE i_id=? AND i_file=?", array($gid, $ged_id)); break; case 'FAM': $gBitDb->query("DELETE FROM {$TBLPREFIX}families WHERE f_id=? AND f_file=?", array($gid, $ged_id)); break; case 'SOUR': $gBitDb->query("DELETE FROM {$TBLPREFIX}sources WHERE s_id=? AND s_file=?", array($gid, $ged_id)); break; case 'OBJE': $gBitDb->query("DELETE FROM {$TBLPREFIX}media WHERE m_media=? AND m_gedfile=?", array($gid, $ged_id)); break; default: $gBitDb->query("DELETE FROM {$TBLPREFIX}other WHERE o_id=? AND o_file=?", array($gid, $ged_id)); break; } if (!$delete) { import_record($gedrec, true); } }
/** * update a record in the database * * @param string $gedrec * @param int $ged_id * @param bool $delete */ function update_record($gedrec, $ged_id, $delete) { if (preg_match('/^0 @(' . WT_REGEX_XREF . ')@ (' . WT_REGEX_TAG . ')/', $gedrec, $match)) { list(, $gid, $type) = $match; } else { echo "ERROR: Invalid gedcom record."; return; } // TODO deleting unlinked places can be done more efficiently in a single query $placeids = WT_DB::prepare("SELECT pl_p_id FROM `##placelinks` WHERE pl_gid=? AND pl_file=?")->execute(array($gid, $ged_id))->fetchOneColumn(); WT_DB::prepare("DELETE FROM `##placelinks` WHERE pl_gid=? AND pl_file=?")->execute(array($gid, $ged_id)); WT_DB::prepare("DELETE FROM `##dates` WHERE d_gid =? AND d_file =?")->execute(array($gid, $ged_id)); //-- delete any unlinked places foreach ($placeids as $p_id) { $num = WT_DB::prepare("SELECT count(pl_p_id) FROM `##placelinks` WHERE pl_p_id=? AND pl_file=?")->execute(array($p_id, $ged_id))->fetchOne(); if ($num == 0) { WT_DB::prepare("DELETE FROM `##places` WHERE p_id=? AND p_file=?")->execute(array($p_id, $ged_id)); } } WT_DB::prepare("DELETE FROM `##name` WHERE n_id=? AND n_file=?")->execute(array($gid, $ged_id)); WT_DB::prepare("DELETE FROM `##link` WHERE l_from=? AND l_file=?")->execute(array($gid, $ged_id)); switch ($type) { case 'INDI': WT_DB::prepare("DELETE FROM `##individuals` WHERE i_id=? AND i_file=?")->execute(array($gid, $ged_id)); break; case 'FAM': WT_DB::prepare("DELETE FROM `##families` WHERE f_id=? AND f_file=?")->execute(array($gid, $ged_id)); break; case 'SOUR': WT_DB::prepare("DELETE FROM `##sources` WHERE s_id=? AND s_file=?")->execute(array($gid, $ged_id)); break; case 'OBJE': WT_DB::prepare("DELETE FROM `##media` WHERE m_id=? AND m_file=?")->execute(array($gid, $ged_id)); break; default: WT_DB::prepare("DELETE FROM `##other` WHERE o_id=? AND o_file=?")->execute(array($gid, $ged_id)); break; } if (!$delete) { import_record($gedrec, $ged_id, true); } }
$filename = $_POST['filename']; $import_type = $_POST['import_type']; $added_row_count = isset($_POST['added_row_count']) ? $_POST['added_row_count'] : 0; $last_time = isset($_POST['last_time']) ? $_POST['last_time'] : 0; $duplicated_time_count = isset($_POST['duplicated_time_count']) ? $_POST['duplicated_time_count'] : 0; if (isset($filename) && isset($import_type)) { if ($import_type == "override" && $added_row_count == 0) { if (!CRecordManager::ClearAllRecords()) { break; } echo "Cleared all records.<br/>"; } } else { header('Location: xls_importer.php'); } $result = import_record($filename, $added_row_count, $last_time, $duplicated_time_count); echo "Added row from {$added_row_count} to " . $result[0] . "<br/>"; $extra_data = array(); $extra_data[0] = $filename; // name of uploaded file $extra_data[1] = $import_type; // type of importing $extra_data[2] = $result[0]; // number of added rows $extra_data[3] = $result[1]; // time of recent added row $extra_data[4] = $result[2]; // number of duplicated go_to_step(5, $extra_data); break; default: