<?php
require_once($INC . "/util.inc.php");
require_once($INC . "/log.inc.php");
require_once($INC . "/sql.inc.php");
require_once($INC . "/user.inc.php");
require_once($INC . "/prof.inc.php");
$rg_watch_error = "";
function rg_watch_set_error($str)
{
global $rg_watch_error;
$rg_watch_error = $str;
rg_log('Set error to ' . $str);
}
function rg_watch_error()
{
global $rg_watch_error;
return $rg_watch_error;
}
/*
* Returns a watched entry
*/
function rg_watch_load($db, $type, $uid, $obj_id1, $obj_id2)
{
rg_prof_start("watch_load");
rg_log_enter("watch_load: type=$type uid=$uid obj_id=$obj_id1/$obj_id2");
$ret = FALSE;
while (1) {
$key = 'watch' . '::' . $type . '::' . $uid
. '::' . $obj_id1 . '::' . $obj_id2;
$c = rg_cache_get($key);
if ($c !== FALSE) {
$ret = $c;
break;
}
$params = array(
'uid' => $uid,
'obj_id1' => $obj_id1,
'obj_id2' => $obj_id2);
if (strcmp($type, "bug") == 0) {
$sql = "SELECT 1 FROM watch_bug"
. " WHERE uid = @@uid@@"
. " AND repo_id = @@obj_id1@@"
. " AND bug_id = @@obj_id2@@";
} else if (strcmp($type, "repo") == 0) {
$sql = "SELECT 1 FROM watch_repo"
. " WHERE uid = @@uid@@"
. " AND repo_id = @@obj_id1@@";
} else if (strcmp($type, "user") == 0) {
$sql = "SELECT 1 FROM watch_user"
. " WHERE uid = @@uid@@"
. " AND watch_uid = @@obj_id1@@";
} else {
rg_internal_error("Invalid watch type!");
break;
}
$res = rg_sql_query_params($db, $sql, $params);
if ($res === FALSE) {
rg_watch_set_error('cannot get data from db');
break;
}
$rows = rg_sql_num_rows($res);
rg_sql_free_result($res);
$ret = $rows > 0 ? 1 : 0;
rg_cache_set($key, $ret, RG_SOCKET_NO_WAIT);
break;
}
rg_log_exit();
rg_prof_end("watch_load");
return $ret;
}
/*
* Add somebody to the watch list
*/
function rg_watch_add($db, $type, $login_uid, $obj_id1, $obj_id2)
{
global $rg_watch_add_state;
rg_prof_start("watch_add");
rg_log_enter("watch_add type=$type, login_uid=$login_uid"
. " obj_id=$obj_id1/$obj_id2");
$ret = FALSE;
while (1) {
$r = rg_watch_load($db, $type, $login_uid, $obj_id1, $obj_id2);
if ($r === FALSE)
break;
if ($r === 1) { // already in watch list
$ret = TRUE;
break;
}
$params = array("uid" => $login_uid,
"obj_id1" => $obj_id1,
"obj_id2" => $obj_id2);
if (strcmp($type, "bug") == 0) {
$sql = "INSERT INTO watch_bug (uid, repo_id, bug_id)"
. " VALUES (@@uid@@, @@obj_id1@@, @@obj_id2@@)";
} else if (strcmp($type, "repo") == 0) {
$sql = "INSERT INTO watch_repo (uid, repo_id)"
. " VALUES (@@uid@@, @@obj_id1@@)";
} else if (strcmp($type, "user") == 0) {
$sql = "INSERT INTO watch_user (uid, watch_uid)"
. " VALUES (@@uid@@, @@obj_id1@@)";
} else {
rg_internal_error("Invalid watch type!");
break;
}
$res = rg_sql_query_params($db, $sql, $params);
if ($res === FALSE) {
rg_watch_set_error('cannot insert data in db');
break;
}
rg_sql_free_result($res);
$key = 'watch' . '::' . $type . '::' . $login_uid
. '::' . $obj_id1 . '::' . $obj_id2;
rg_cache_set($key, 1, RG_SOCKET_NO_WAIT);
$ret = TRUE;
break;
}
rg_log_exit();
rg_prof_end("watch_add");
return $ret;
}
/*
* Delete somebody from the watch list
*/
function rg_watch_del($db, $type, $login_uid, $obj_id1, $obj_id2)
{
rg_prof_start("watch_del");
rg_log_enter("watch_del type=$type, login_uid=$login_uid"
. " obj_id=$obj_id1/$obj_id2");
$ret = FALSE;
while (1) {
$r = rg_watch_load($db, $type, $login_uid, $obj_id1, $obj_id2);
if ($r === FALSE)
break;
if ($r === 0) { // already deleted
rg_log('DEBUG: watch not active, nothing to do');
$ret = TRUE;
break;
}
$params = array("login_uid" => $login_uid,
"obj_id1" => $obj_id1,
"obj_id2" => $obj_id2);
if (strcmp($type, "bug") == 0) {
$sql = "DELETE FROM watch_bug"
. " WHERE uid = @@login_uid@@"
. " AND repo_id = @@obj_id1@@"
. " AND bug_id = @@obj_id2@@";
} else if (strcmp($type, "repo") == 0) {
$sql = "DELETE FROM watch_repo"
. " WHERE uid = @@login_uid@@"
. " AND repo_id = @@obj_id1@@";
} else if (strcmp($type, "user") == 0) {
$sql = "DELETE FROM watch_user"
. " WHERE uid = @@login_uid@@"
. " AND watch_uid = @@obj_id1@@";
} else {
rg_internal_error("Invalid watch type!");
break;
}
$res = rg_sql_query_params($db, $sql, $params);
if ($res === FALSE) {
rg_watch_set_error('cannot delete data from db');
break;
}
rg_sql_free_result($res);
$key = 'watch' . '::' . $type . '::' . $login_uid
. '::' . $obj_id1 . '::' . $obj_id2;
rg_cache_unset($key, RG_SOCKET_NO_WAIT);
$ret = TRUE;
break;
}
rg_log_exit();
rg_prof_end("watch_del");
return $ret;
}
/*
* Returns a list of uids by type and obj_id
*/
function rg_watch_load_by_obj_id($db, $type, $obj_id1, $obj_id2)
{
rg_prof_start("watch_load_by_obj_id");
rg_log_enter("watch_load_by_obj_id: type=$type obj_id=$obj_id1/$obj_id2");
$ret = FALSE;
while (1) {
$params = array("obj_id1" => $obj_id1,
"obj_id2" => $obj_id2);
if (strcmp($type, "bug") == 0) {
$sql = "SELECT uid FROM watch_bug"
. " WHERE repo_id = @@obj_id1@@"
. " AND bug_id = @@obj_id2@@";
} else if (strcmp($type, "repo") == 0) {
$sql = "SELECT uid FROM watch_repo"
. " WHERE repo_id = @@obj_id1@@";
} else if (strcmp($type, "user") == 0) {
$sql = "SELECT uid FROM watch_user"
. " WHERE watch_uid = @@obj_id1@@";
} else {
rg_internal_error("Invalid watch type!");
break;
}
$res = rg_sql_query_params($db, $sql, $params);
if ($res === FALSE) {
rg_watch_set_error('cannot get data from db');
break;
}
$ret = array();
while (($row = rg_sql_fetch_array($res)))
$ret[] = $row['uid'];
rg_sql_free_result($res);
break;
}
rg_log_exit();
rg_prof_end("watch_load_by_obj_id");
return $ret;
}
/*
* Helper to easy dealing witch watch buttons.
* It show and process the presses.
*/
function rg_watch_hl_process($db, &$rg, $type, $obj_id1, $obj_id2, $url)
{
rg_prof_start('watch_hl_process');
rg_log_enter('watch_hl_process type=' . $type);
$ret = FALSE;
$rg['HTML:watch_form'] = '';
$rg['HTML:watch_error'] = '';
while (1) {
// If user is not logged in, we cannot add a watch
if ($rg['login_ui']['uid'] == 0) {
$ret = TRUE;
break;
}
// The owner is already watching his repos
if ($rg['login_ui']['uid'] == $rg['page_ui']['uid']) {
$ret = TRUE;
break;
}
$watch = rg_watch_load($db, $type, $rg['login_ui']['uid'],
$obj_id1, $obj_id2);
if ($watch === FALSE)
break;
// It is our watch? Please note that we may have multiple
// watches on the same page: think bugs.
$passed_type = rg_var_str('watch_type');
$ours = strcmp($passed_type, $type) == 0;
if ((rg_var_uint('watch_doit') == 1) && $ours) {
if (!rg_valid_referer()) {
rg_watch_set_error('invalid referer; try again');
break;
}
if (!rg_token_valid($db, $rg, 'watch_' . $type, FALSE)) {
rg_watch_set_error('invalid token; try again');
break;
}
if (rg_var_uint('watch') == $watch)
$next_value = 1 - $watch;
else
$next_value = $watch;
} else {
$next_value = 1 - $watch;
}
rg_log('DEBUG: watch=' . $watch . ' next_value=' . $next_value);
$rg['watch'] = array(
'type' => $type,
'url' => $url,
'next_value' => $next_value);
$rg['rg_form_token_tag'] = 'watch_' . $type;
$rg['rg_form_token'] = rg_token_get($db, $rg, 'watch_' . $type);
$rg['HTML:watch_form'] = rg_template('watch.html',
$rg, TRUE /*xss*/);
if ((rg_var_uint('watch_doit') != 1) || !$ours) {
$ret = TRUE;
break;
}
if ($watch == 0)
$r = rg_watch_add($db, $type, $rg['login_ui']['uid'],
$obj_id1, $obj_id2);
else
$r = rg_watch_del($db, $type, $rg['login_ui']['uid'],
$obj_id1, $obj_id2);
if ($r === FALSE)
break;
$ret = TRUE;
break;
}
if ($ret === FALSE)
$rg['HTML:watch_error'] = rg_warning('Watch error: ' . rg_watch_error());
rg_log_exit();
rg_prof_end('watch_hl_process');
return $ret;
}
?>