Beispiel #1
0
                if (preg_match("/^insert/i", $x)) {
                    print mysql_affected_rows() . " INSERTED\n \n";
                }
            }
        }
    }
    return $res;
}
require_once dirname(__FILE__) . "/../../common/connect/applyCredentials.php";
require_once dirname(__FILE__) . "/../../common/php/dbMySqlWrappers.php";
require_once dirname(__FILE__) . "/../../common/php/saveRecord.php";
require_once dirname(__FILE__) . "/../../common/php/utilsTitleMask.php";
// 26/3/14 Functions to index record being saved using Elastic Search (Lucene)
require_once dirname(__FILE__) . "/../../records/index/elasticSearchFunctions.php";
if (!is_logged_in()) {
    jsonError("no logged-in user");
}
$_REQUEST = json_decode(@$_POST["data"] ? $_POST["data"] : base64_decode(@$_GET["data"]), true);
mysql_connection_overwrite(DATABASE);
mysql_query("start transaction");
$out = saveRecord(@$_REQUEST["id"], @$_REQUEST["type"], @$_REQUEST["url"], @$_REQUEST["notes"], @$_REQUEST["group"], @$_REQUEST["vis"], @$_REQUEST["bookmark"], @$_REQUEST["pnotes"], @$_REQUEST["rating"], @$_REQUEST["tags"], @$_REQUEST["wgTags"], @$_REQUEST["detail"], @$_REQUEST["-notify"], @$_REQUEST["+notify"], @$_REQUEST["-comment"], @$_REQUEST["comment"], @$_REQUEST["+comment"]);
mysql_query("commit");
// 26/3/14 Add record to index in Elastic Search (Lucene)
updateRecordIndexEntry(HEURIST_DBNAME, @$_REQUEST["type"], @$_REQUEST["id"]);
print json_format($out);
function jsonError($message)
{
    mysql_query("rollback");
    print "{\"error\":\"" . addslashes($message) . "\"}";
    exit(0);
}
/**
* Main method that parses POST and update details for given record ID
*
* @param int $recID
*/
function updateRecord($recID, $rtyID = null)
{
    // Update the given record.
    // This is non-trivial: so that the versioning stuff (achive_*) works properly
    // we need to separate this into updates, inserts and deletes.
    // We get the currect record details and compare them against the post
    // if the details id is in the post[dtyID][dtlID] then compare the values
    $recID = intval($recID);
    // Check that the user has permissions to edit it.
    $res = mysql_query("select * from Records" . " left join sysUsrGrpLinks on ugl_GroupID=rec_OwnerUGrpID" . " left join defRecTypes on rty_ID=rec_RecTypeID" . " where rec_ID={$recID} and (! rec_OwnerUGrpID or rec_OwnerUGrpID=" . get_user_id() . " or ugl_UserID=" . get_user_id() . ")");
    if (mysql_num_rows($res) == 0) {
        $res = mysql_query("select grp.ugr_Name from Records, " . USERS_DATABASE . ".sysUGrps grp where rec_ID={$recID} and grp.ugr_ID=rec_OwnerUGrpID");
        $grpName = mysql_fetch_row($res);
        $grpName = $grpName[0];
        print '({ error: "\\nSorry - you can\'t edit this record.\\nYou aren\'t in the ' . slash($grpName) . ' workgroup" })';
        return;
    }
    $record = mysql_fetch_assoc($res);
    // Upload any files submitted ... (doesn't have to take place right now, but may as well)
    uploadFiles();
    //Artem: it does not work here - since we uploaded files at once
    // Get the existing records details and compare them to the incoming data
    $recDetails = getRecordDetails($recID);
    // find UPDATES - everything that is in current record and has a post value is treated as an update
    $recDetailUpdates = array();
    foreach ($recDetails as $dtyID => $dtlIDs) {
        $eltName = "type:" . $dtyID;
        $skipEltName = "_type:" . $dtyID;
        if (@$_REQUEST[$skipEltName] && is_array($_REQUEST[$skipEltName])) {
            // handle any _type post meant for ignore, need to remove from recDetails
            foreach (@$_REQUEST[$skipEltName] as $codedDtlID => $ingnoreVal) {
                if (!preg_match("/^bd:\\d+\$/", $codedDtlID)) {
                    continue;
                }
                $dtlID = substr($codedDtlID, 3);
                // everything after "bd:"
                unset($_REQUEST[$skipEltName][$codedDtlID]);
                // remove data from post submission
                if (count($_REQUEST[$skipEltName]) == 0) {
                    // if nothing left in post dtyID then remove it also
                    unset($_REQUEST[$skipEltName]);
                }
                unset($recDetails[$dtyID][$dtlID]);
                // remove data from local reflection of the database
            }
        }
        if (!(@$_REQUEST[$eltName] && is_array($_REQUEST[$eltName]))) {
            // element wasn't in POST: ignore it -this could be a non-rectype detail
            unset($recDetails[$dtyID]);
            // remove from details so it's not deleted
            continue;
        }
        if (count($_REQUEST[$eltName]) == 0) {
            // element was in POST but without content: values have been deleted client-side (need to be deleted in DB so leave POST)
            continue;
        }
        $bdInputHandler = getInputHandlerForType($dtyID);
        //returns the particular handler (processor) for given field type
        foreach ($dtlIDs as $dtlID => $val) {
            $eltID = "bd:" . $dtlID;
            $val = @$_REQUEST[$eltName][$eltID];
            if (!$bdInputHandler->inputOK($val, $dtyID, $rtyID)) {
                continue;
                // faulty input ... ignore
            }
            $toadd = $bdInputHandler->convertPostToMysql($val);
            if ($toadd == null) {
                continue;
            }
            $recDetailUpdates[$dtlID] = $toadd;
            $recDetailUpdates[$dtlID]["dtl_DetailTypeID"] = $dtyID;
            /*
            @TODO Since this function is utilized in (email)import we need to add verification of values according to detail type
            at the first for terms (enumeration field type)
            */
            unset($_REQUEST[$eltName][$eltID]);
            // remove data from post submission
            if (count($_REQUEST[$eltName]) == 0) {
                // if nothing left in post dtyID then remove it also
                unset($_REQUEST[$eltName]);
            }
            unset($recDetails[$dtyID][$dtlID]);
            // remove data from local reflection of the database
        }
    }
    // find DELETES
    // Anything left in recDetails now represents recDetails rows that need to be deleted
    $bibDetailDeletes = array();
    foreach ($recDetails as $dtyID => $dtlIDs) {
        foreach ($dtlIDs as $dtlID => $val) {
            array_push($bibDetailDeletes, $dtlID);
        }
    }
    // find INSERTS
    // Try to insert anything left in POST as new recDetails rows
    $bibDetailInserts = array();
    foreach ($_REQUEST as $eltName => $bds) {
        // if not properly formatted or empty or an empty array then skip it
        if (!preg_match("/^type:\\d+\$/", $eltName) || !$_REQUEST[$eltName] || count($_REQUEST[$eltName]) == 0) {
            continue;
        }
        $dtyID = substr($eltName, 5);
        $bdInputHandler = getInputHandlerForType($dtyID);
        foreach ($bds as $eltID => $val) {
            if (!$bdInputHandler->inputOK($val, $dtyID, $rtyID)) {
                continue;
                // faulty input ... ignore
            }
            $newBibDetail = $bdInputHandler->convertPostToMysql($val);
            $newBibDetail["dtl_DetailTypeID"] = $dtyID;
            $newBibDetail["dtl_RecID"] = $recID;
            array_push($bibDetailInserts, $newBibDetail);
            unset($_REQUEST[$eltName][$eltID]);
            // remove data from post submission
        }
    }
    // Anything left in POST now is stuff that we have no intention of inserting ... ignore it
    // We now have:
    //  - $recDetailUpdates: an assoc. array of dtl_ID => column values to be updated in recDetails
    //  - $bibDetailInserts: an array of column values to be inserted into recDetails
    //  - $bibDetailDeletes: an array of dtl_ID values corresponding to rows to be deleted from recDetails
    // Commence versioning ...
    mysql_query("start transaction");
    $recUpdates = array("rec_Modified" => array("now()"), "rec_FlagTemporary" => 0);
    $recUpdates["rec_ScratchPad"] = $_REQUEST["notes"];
    if (intval(@$_REQUEST["rectype"])) {
        $recUpdates["rec_RecTypeID"] = intval($_REQUEST["rectype"]);
    }
    if (array_key_exists("rec_url", $_REQUEST)) {
        $recUpdates["rec_URL"] = $_REQUEST["rec_url"];
    }
    $owner = $record['rec_OwnerUGrpID'];
    if (is_admin() || is_admin('group', $owner) || $owner == get_user_id()) {
        // must be grpAdmin or record owner to changes ownership or visibility
        if (array_key_exists("rec_owner", $_REQUEST)) {
            $recUpdates["rec_OwnerUGrpID"] = $_REQUEST["rec_owner"];
        }
        if (array_key_exists("rec_visibility", $_REQUEST)) {
            $recUpdates["rec_NonOwnerVisibility"] = $_REQUEST["rec_visibility"];
        } else {
            if ($record['rec_NonOwnerVisibility'] == 'public' && HEURIST_PUBLIC_TO_PENDING) {
                $recUpdates["rec_NonOwnerVisibility"] = 'pending';
            }
        }
    }
    mysql__update("Records", "rec_ID={$recID}", $recUpdates);
    $biblioUpdated = mysql_affected_rows() > 0 ? true : false;
    $updatedRowCount = 0;
    foreach ($recDetailUpdates as $bdID => $vals) {
        mysql__update("recDetails", "dtl_ID={$bdID} and dtl_RecID={$recID}", $vals);
        if (mysql_affected_rows() > 0) {
            ++$updatedRowCount;
        }
    }
    $insertedRowCount = 0;
    foreach ($bibDetailInserts as $vals) {
        mysql__insert("recDetails", $vals);
        if (mysql_affected_rows() > 0) {
            ++$insertedRowCount;
        }
    }
    $deletedRowCount = 0;
    if ($bibDetailDeletes) {
        mysql_query("delete from recDetails where dtl_ID in (" . join($bibDetailDeletes, ",") . ") and dtl_RecID={$recID}");
        if (mysql_affected_rows() > 0) {
            $deletedRowCount = mysql_affected_rows();
        }
    }
    // eliminate any duplicated lines
    $notesIn = explode("\n", str_replace("\r", "", $_REQUEST["notes"]));
    $notesOut = "";
    $notesMap = array();
    for ($i = 0; $i < count($notesIn); ++$i) {
        if (!@$notesMap[$notesIn[$i]] || !$notesIn[$i]) {
            // preserve blank lines
            $notesOut .= $notesIn[$i] . "\n";
            $notesMap[$notesIn[$i]] = true;
        }
    }
    $_REQUEST["notes"] = preg_replace("/\n\n+/", "\n", $notesOut);
    if ($updatedRowCount > 0 || $insertedRowCount > 0 || $deletedRowCount > 0 || $biblioUpdated) {
        /* something changed: update the records title and commit all changes */
        $new_title = fill_title_mask($record["rty_TitleMask"], $record["rec_ID"], $record["rec_RecTypeID"]);
        mysql_query("update Records\n            set rec_Title = '" . mysql_real_escape_string($new_title) . "'\n            where rec_ID = {$recID}");
        mysql_query("commit");
        // Update memcached's copy of record (if it is cached)
        updateCachedRecord($recID);
        updateRecordIndexEntry(DATABASE, $record["rec_RecTypeID"], $recID);
        // TODO: Doesn't properly update Elasticsearch
        return true;
    } else {
        /* nothing changed: rollback the transaction so we don't get false versioning */
        mysql_query("rollback");
        return false;
    }
}
/**
 * Rebuild the index for a specified record type
 * @param $dbName       The name of the Heurist databasem, excluding prefix
 * @param
 * @returns 0 = OK, any other = error
 */
function buildIndexForRectype($dbName, $recTypeID)
{
    global $elasticSearch;
    if ($elasticSearch) {
        //print "buildIndexForRectype: indexing record type $recTypeID for $dbName<br />";
        deleteIndexForRectype($dbName, $recTypeID);
        // clear the existing index
        $query = "Select rec_ID from Records where rec_RecTypeID = {$recTypeID}";
        $res = mysql_query($query);
        if ($res) {
            while ($row = mysql_fetch_array($res)) {
                // fetch records
                $code = updateRecordIndexEntry($dbName, $recTypeID, $row[0]);
                if ($code != 0) {
                    //print "<br />ERROR while updating record index; code = $code, dbName = $dbname, rectypeID = $recTypeID, row = " + $row[0] + "<br />";
                    return $code;
                    // curl error code
                }
            }
            return 0;
        }
    }
    return -1;
}
Beispiel #4
0
function saveRecord($recordID, $rectype, $url, $notes, $wg, $vis, $personalised, $pnotes, $rating, $tags, $wgTags, $details, $notifyREMOVE, $notifyADD, $commentREMOVE, $commentMOD, $commentADD, &$nonces = null, &$retitleRecs = null, $modeImport = 0)
{
    global $msgInfoSaveRec;
    $msgInfoSaveRec = array();
    // reset the message array
    mysql_query("start transaction");
    //	$log = " saving record ($recordID) ";
    $recordID = intval($recordID);
    $wg = intval($wg);
    if (!is_logged_in()) {
        errSaveRec("It is not possible to save record if not logged in, record save aborted");
        return $msgInfoSaveRec;
    } else {
        if ($wg != null && intval($wg) > 0 && intval($wg) != get_user_id()) {
            // non-member saves are not allowed
            $uquery = "select * from " . USERS_DATABASE . ".sysUsrGrpLinks where ugl_UserID=" . get_user_id() . " and ugl_GroupID=" . $wg;
            $res = mysql_query($uquery);
            if (mysql_num_rows($res) < 1) {
                errSaveRec("Current user " . get_user_id() . " is not a member of required workgroup " . $wg . ", record save aborted ");
                return $msgInfoSaveRec;
            }
        }
    }
    $rectype = intval($rectype);
    if ($recordID && !$rectype) {
        errSaveRec("cannot change existing record to private note, record save aborted");
        return $msgInfoSaveRec;
    }
    $rectypeName = null;
    $res = mysql_query("select rty_Name from defRecTypes where rty_ID=" . $rectype);
    if ($res) {
        $row = mysql_fetch_row($res);
        if ($row) {
            $rectypeName = $row[0];
        }
    }
    if (!$rectypeName) {
        errSaveRec("record type #{$rectype} is not valid");
        return $msgInfoSaveRec;
    }
    if ($vis) {
        $vis = strtolower(str_replace('"', "", $vis));
        $isvalid = in_array(strtolower($vis), array('hidden', 'viewable', 'pending', 'public'));
        if ($isvalid == false) {
            $vis = null;
        }
    }
    $now = date('Y-m-d H:i:s');
    $wg = $wg >= 0 ? $wg : get_user_id();
    // public records data
    if (!$recordID || $recordID < 0) {
        //new record
        //		$log .= "- inserting record ";
        $recheader = array("rec_RecTypeID" => $rectype, "rec_URL" => $url, "rec_ScratchPad" => $notes, "rec_OwnerUGrpID" => $wg, "rec_NonOwnerVisibility" => $vis ? $vis : "viewable", "rec_AddedByUGrpID" => get_user_id(), "rec_Added" => $now, "rec_Modified" => $now, "rec_AddedByImport" => $modeImport > 0 ? 1 : 0);
        if ($recordID < 0) {
            $recordID = abs($recordID);
            $recheader["rec_ID"] = $recordID;
        }
        mysql__insert("Records", $recheader);
        if (mysql_error()) {
            errSaveRec("Database record insert error - " . mysql_error() . "  " . print_r($recheader, true));
            return $msgInfoSaveRec;
        }
        $recordID = mysql_insert_id();
    } else {
        $res = checkPermission($recordID, $wg);
        if ($res !== true) {
            errSaveRec($res);
            return $msgInfoSaveRec;
        }
        //		$log .= "- updating record ";
        mysql__update("Records", "rec_ID={$recordID}", array("rec_RecTypeID" => $rectype, "rec_URL" => $url, "rec_ScratchPad" => $notes, "rec_OwnerUGrpID" => $wg, "rec_NonOwnerVisibility" => $vis ? $vis : "viewable", "rec_FlagTemporary" => 0, "rec_Modified" => $now));
        updateRecordIndexEntry(DATABASE, $rectype, $recordID);
        // TODO: Doesn't properly update Elasticsearch
        if (mysql_error()) {
            errSaveRec("Database record update error - " . mysql_error());
            return $msgInfoSaveRec;
        }
    }
    // public recDetails data
    if ($details) {
        //		$log .= "- inserting details ";
        $dtlIDsByAction = doDetailInsertion($recordID, $details, $rectype, $wg, $nonces, $retitleRecs, $modeImport);
        if (@$dtlIDsByAction['error']) {
            array_push($msgInfoSaveRec['error'], $dtlIDsByAction['error']);
            return $msgInfoSaveRec;
        }
    }
    // check that all the required fields are present
    $res = mysql_query("select rst_ID, rst_DetailTypeID, rst_DisplayName" . " from defRecStructure" . " left join recDetails on dtl_RecID={$recordID} and rst_DetailTypeID=dtl_DetailTypeID" . " where rst_RecTypeID={$rectype} and rst_RequirementType='required' and dtl_ID is null");
    if (mysql_num_rows($res) > 0) {
        //		$log .= "- testing missing detatils ";
        $missed = "";
        while ($row = mysql_fetch_row($res)) {
            //ij asked to remove$conceptCode = getDetailTypeConceptID($row[1]);
            $missed = $missed . $row[2];
            //ij asked to remove ." (Code:".$conceptCode.") ";
        }
        // at least one missing field
        if ($missed) {
            $msg = "Missing data for Required field(s) in '{$rectypeName}'. You may need to make fields optional. Missing data: " . $missed;
            if ($modeImport == 2) {
                warnSaveRec($msg);
            } else {
                errSaveRec($msg);
                return $msgInfoSaveRec;
            }
        }
    }
    mysql_query("commit");
    // if we get to here we have a valid save of the core record.
    // calculate title, do an update
    //	$log .= "- filling titlemask ";
    $mask = mysql__select_array("defRecTypes", "rty_TitleMask", "rty_ID={$rectype}");
    $mask = $mask[0];
    $title = fill_title_mask($mask, $recordID, $rectype);
    if ($title) {
        mysql_query("update Records set rec_Title = '" . mysql_real_escape_string($title) . "' where rec_ID = {$recordID}");
    }
    // Update memcache: we can do this here since it's only the public data that we cache.
    updateCachedRecord($recordID);
    updateRecordIndexEntry(USERS_DATABASE, $rectype, $recordID);
    // private data
    $bkmk = @mysql_fetch_row(mysql_query("select bkm_ID from usrBookmarks where bkm_UGrpID=" . get_user_id() . " and bkm_recID=" . $recordID));
    $bkm_ID = @$bkmk[0];
    if ($personalised) {
        if (!$bkm_ID) {
            // Record is not yet bookmarked, but we want it to be
            mysql_query("insert into usrBookmarks (bkm_Added,bkm_Modified,bkm_UGrpID,bkm_recID) values (now(),now()," . get_user_id() . ",{$recordID})");
            if (mysql_error()) {
                warnSaveRec("trying to create a bookmark - database error - " . mysql_error());
            } else {
                $bkm_ID = mysql_insert_id();
            }
        }
        //		$log .= "- updating bookmark ";
        mysql__update("usrBookmarks", "bkm_ID={$bkm_ID}", array("bkm_Rating" => $rating, "bkm_Modified" => date('Y-m-d H:i:s')));
        //WARNING  tags is assumed to be a complete replacement list for personal tags on this record.
        doTagInsertion($recordID, $bkm_ID, $tags);
    } else {
        if ($bkm_ID) {
            // Record is bookmarked, but the user doesn't want it to be
            //		$log .= "- deleting bookmark ";
            $query = "delete usrBookmarks, usrRecTagLinks " . "from usrBookmarks left join usrRecTagLinks on rtl_RecID = bkm_recID " . "left join usrTags on tag_ID = rtl_TagID " . "where bkm_ID={$bkm_ID} and bkm_recID={$recordID} and bkm_UGrpID = tag_UGrpID and bkm_UGrpID=" . get_user_id();
            mysql_query($query);
            if (mysql_error()) {
                warnSaveRec("database error while removing bookmark- " . mysql_error());
            }
            //saw TODO: add code to remove other personal data reminders, personal notes (woots), etc.
        }
    }
    doWgTagInsertion($recordID, $wgTags);
    if ($notifyREMOVE || $notifyADD) {
        $notifyIDs = handleNotifications($recordID, $notifyREMOVE, $notifyADD);
    }
    if ($commentREMOVE || $commentMOD || $commentADD) {
        $commentIDs = handleComments($recordID, $commentREMOVE, $commentMOD, $commentADD);
    }
    $rval = array("bibID" => $recordID, "bkmkID" => $bkm_ID, "modified" => $now);
    if ($title) {
        $rval["title"] = $title;
    }
    if (@$dtlIDsByAction) {
        $rval["detail"] = $dtlIDsByAction;
    }
    if (@$notifyIDs) {
        $rval["notify"] = $notifyIDs;
    }
    if (@$commentIDs) {
        $rval["comment"] = $commentIDs;
    }
    if (@$msgInfoSaveRec['warning']) {
        $rval["warning"] = $msgInfoSaveRec['warning'];
    }
    if (@$msgInfoSaveRec['error']) {
        //should never get here with error set
        $rval["error"] = $msgInfoSaveRec['error'];
    } else {
        //$rval["usageCount"] =
        updateRecTypeUsageCount();
    }
    return $rval;
}