PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/CaGov/index.php

http://zero-k.googlecode.com/
PHP | 351 lines | 301 code | 43 blank | 7 comment | 60 complexity | 3c3de8882321b1a285093aca69511a10 MD5 | raw file
Possible License(s): GPL-2.0, MIT, BSD-3-Clause, GPL-3.0, LGPL-2.1
  1. <?php
  2. require 'tabulky.php';
  3. require 'functions.php';
  4. require 'login.php'; // fills id_user, power, db, login, anon variables
  5. $limitone = $_GET[limitone];
  6. ?>
  7. <html>
  8. <head>
  9. <title>CaGov</title>
  10. <style>
  11. <!--
  12. A:link {text-decoration: underline; color:Blue;}
  13. A:visited {text-decoration: underline;color:Blue;}
  14. A:active {text-decoration: underline;color:Blue;}
  15. A:hover {text-decoration: none;color:Blue;}
  16. -->
  17. </style>
  18. </head>
  19. <body>
  20. <div style="width: <?= $limitone?"625":"800"?>px">
  21. <?
  22. if (!$limitone) {
  23. // login form
  24. echo "<a href='index.php'>Refresh</a><br>";
  25. echo "<div style='border: 1px dotted blue'><b><i>Login: </i></b><br>";
  26. if ($id_user > 0) {
  27. echo $login." - votes:".$power;
  28. ?>
  29. <form method="post" action="index.php?act=changepassword">Change password: <input type="password" name="password"><input type="submit"></form>
  30. <?
  31. echo "<b>";
  32. if ($id_user > 0) echo "<a href='index.php?act=addpoll'>Add new poll</a>";
  33. if ($power > 1) echo "&nbsp;|&nbsp<a href='index.php?act=adduser'>Add developer</a>";
  34. echo "&nbsp;|&nbsp;<a href='index.php?act=logout'>Logout</a></b>";
  35. } else {
  36. ?>
  37. <form method="post" action="index.php?act=login">
  38. Login: <input type="text" name="login" value="<?= $_COOKIE["login"]?>">
  39. Password: <input type="password" name="password">
  40. <input type="submit"> </form>
  41. <?
  42. }
  43. echo "</div><br>";
  44. ?>
  45. You dont have to ask before implementing something, polls are for conflict resolving. <br/>
  46. For decision making use polls with only yes/no options.<br/>
  47. Do not add polls about things you wont implement yourself!<br/>
  48. Adding a vote like "make all units OTA free" is pointless unless you plan to do it yourself.<br/>
  49. <br/>
  50. <?
  51. }
  52. switch ($_GET["act"]) {
  53. case "changepassword":
  54. if ($id_user > 0) {
  55. $pas = trim($_POST["password"]);
  56. $pas = md5($pas);
  57. if (strlen($pas)>0) {
  58. $db->query("UPDATE Users SET password='$pas' WHERE id=$id_user");
  59. echo "Password changed, <a href='index.php'>login</a>";
  60. exit();
  61. }
  62. }
  63. break;
  64. case "editpoll"; // editing poll
  65. if ($power <= 0) return;
  66. $pinfo = $db->query("SELECT * FROM Polls WHERE id = $_GET[id_poll]")->fetch();
  67. ?>
  68. <div style="border:1px black solid;">
  69. <b><i>Edit poll:</i></b>
  70. <form method="post" action="index.php?act=editpollsubmit&id_poll=<?= $_GET["id_poll"]?>&limitone=<?= $limitone?>">
  71. <table>
  72. <tr><td>Question: </td><td><textarea name="question" cols="40"><?= $pinfo["question"] ?></textarea></td></tr>
  73. <?php
  74. $res = $db->query("SELECT * FROM Options WHERE id_poll = $_GET[id_poll] AND abstain = 0 ORDER BY id");
  75. while (($arr = $res->fetch())) {
  76. ?>
  77. <tr><td></td><td><input type='text' name='id_<?=$arr["id"]?>' value="<?= $arr["text"]?>"></td></tr>
  78. <?
  79. }
  80. ?>
  81. <tr><td>Add options (one per line): </td><td><textarea name="options" rows="4" cols="40"></textarea>
  82. </td></tr>
  83. <tr><td colspan="2" align="center">
  84. <input type="submit" value="Modify">
  85. </td></tr>
  86. </table>
  87. </form>
  88. </div>
  89. <?
  90. break;
  91. case "editpollsubmit": // submit editing poll
  92. if ($power > 0) {
  93. $question = sqlite_escape_string($_POST["question"]);
  94. $db->queryExec("UPDATE Polls SET question='$question' WHERE id = $_GET[id_poll]");
  95. $res = $db->query("SELECT * FROM Options WHERE id_poll = $_GET[id_poll] AND abstain = 0 ORDER BY id");
  96. while (($arr = $res->fetch())) {
  97. $val = $_POST["id_".$arr[id]];
  98. $text = sqlite_escape_string($val);
  99. if (strlen(trim($val))> 0) {
  100. $db->queryExec("UPDATE Options SET text = '$text' WHERE id = $arr[id]");
  101. } else {
  102. $db->queryExec("DELETE FROM Options WHERE id = $arr[id]");
  103. }
  104. }
  105. $qlist = split("\n",$_POST["options"]);
  106. for ($i = 0; $i < count($qlist); $i++) {
  107. $trimmed = trim($qlist[$i]);
  108. if (strlen($trimmed) == 0) continue;
  109. $db->query("insert into Options (id_poll, text) values ($_GET[id_poll], '".sqlite_escape_string($trimmed)."')");
  110. }
  111. }
  112. break;
  113. case "vote": // voting
  114. if ($id_user > 0) {
  115. $db->queryExec("INSERT OR REPLACE INTO Votes (id_poll, id_user,id_option) VALUES ($_GET[id_poll], $id_user, $_GET[id_option])");
  116. }
  117. $db->queryExec("INSERT OR REPLACE INTO AnonymousVotes (id_poll, cookie,id_option) VALUES ($_GET[id_poll], $anon, $_GET[id_option])");
  118. break;
  119. case "addpollsubmit": // creating new poll
  120. if ($id_user > 0) {
  121. $question = sqlite_escape_string($_POST["question"]);
  122. $db->queryExec("insert into Polls (question, creator, creation_time,secret) values ('$question', '$login', ".time().", ".($_POST["secret"] == "on" ? 1:0).")", $err);
  123. $pid = $db->lastInsertRowid();
  124. $qlist = split("\n",$_POST["options"]);
  125. for ($i = 0; $i < count($qlist); $i++) {
  126. $trimmed = trim($qlist[$i]);
  127. if (strlen($trimmed) == 0) continue;
  128. $db->query("insert into Options (id_poll, text) values ($pid, '".sqlite_escape_string($trimmed)."')");
  129. }
  130. $db->query("insert into Options (id_poll, text, abstain) values ($pid, 'Abstain',1)");
  131. if ($_POST["addtrac"] == "on") {
  132. $qline = split("[\\.\\?\\!]+", $question);
  133. $summary = $trac_db->quote("Poll: ".$qline[0]);
  134. $text=$trac_db->quote("{{{\n#!html\n<iframe src='http://gov.caspring.org/index.php?limitone=$pid' width='650' height='250' style='border:0; margin:0; padding:0;' frameborder='0'></iframe>\n}}}");
  135. $trac_db->exec("insert into ticket (type, time, changetime, component, priority, reporter, status, summary, description) values ('poll',".time().",".time().", 'CA','major','$login','new',$summary, $text)");
  136. $tracid = $trac_db->lastInsertId();
  137. $db->queryExec("update Polls set id_trac = $tracid WHERE id=$pid");
  138. }
  139. }
  140. break;
  141. case "addpoll":
  142. ?>
  143. <div style="border:1px black solid;">
  144. <b><i>Add new poll:</i></b>
  145. <form method="post" action="index.php?act=addpollsubmit">
  146. <table>
  147. <tr><td>Question: </td><td><textarea name="question" cols="40"></textarea></td></tr>
  148. <tr><td>Options (one per line): </td><td><textarea name="options" rows="4" cols="40"></textarea></td></tr>
  149. <tr><td>Is secret vote: </td><td><input type="checkbox" name="secret"></td></tr>
  150. <tr><td>Add trac ticket: </td><td><input type="checkbox" name="addtrac" checked="checked"></td></tr>
  151. <tr><td colspan="2" align="center">
  152. <input type="submit" value="Add">
  153. </td></tr>
  154. </table>
  155. (Note that abstain option is added automtically)
  156. </form>
  157. </div>
  158. <?php
  159. break;
  160. case "addusersubmit":
  161. if ($power > 1) {
  162. $uid = $_GET["uid"];
  163. if ($uid > 0) {
  164. $db->queryExec("UPDATE Users SET login='$_POST[login]', power='$_POST[power]' WHERE id = $uid");
  165. } else {
  166. $db->queryExec("INSERT INTO Users (login, power) VALUES ('$_POST[login]', $_POST[power])");
  167. }
  168. }
  169. break;
  170. case "adduser":
  171. if ($power <= 1) exit();
  172. unset($arr);
  173. if ($_GET["uid"] > 0) {
  174. $arr = $db->query("SELECT login, power FROM Users WHERE id = $_GET[uid]")->fetch();
  175. }
  176. ?>
  177. <div style="border:1px black solid;">
  178. <b><i>Add/modify user:</i></b>
  179. <form method="post" action="index.php?act=addusersubmit&uid=<?=$_GET["uid"]?>">
  180. <table>
  181. <tr><td>Login: </td><td><input type="text" name="login" value="<?= $arr[login]?>"></td></tr>
  182. <tr><td>Votes: </td><td><input type="text" name="power" value="<?= $arr[power]?>"></td></tr>
  183. </td></tr>
  184. <tr><td colspan="2" align="center">
  185. <input type="submit" value="Add/modify">
  186. </td></tr>
  187. </table>
  188. Note default new password is 'default'
  189. </form>
  190. </div>
  191. <?php
  192. break;
  193. break;
  194. case "closepoll": // close existing poll
  195. if ($power > 0) {
  196. $total_power = $db->singleQuery("SELECT sum(power) FROM Users");
  197. $bestp = 0;
  198. $bestt = "";
  199. $tot_abstain = $db->singleQuery("select sum(power) from v_VotePowers JOIN Options o ON id_option = o.id AND o.abstain=1 AND v_VotePowers.id_poll=$_GET[id_poll]");
  200. $res = $db->query("SELECT text, sum(power) as cadev, sum(abstain) as abst, o.id as ido FROM Options o LEFT OUTER JOIN v_VotePowers p ON o.id_poll = p.id_poll AND o.id = p.id_option WHERE o.id_poll = $_GET[id_poll] GROUP BY id ORDER BY id");
  201. while (($arr = $res->fetch())) {
  202. if ($arr[abst]) continue;
  203. if ($total_power - $tot_abstain > 0) $percentage = (int)(100 *$arr["cadev"] / ($total_power - $tot_abstain)); else $percentage = 0;
  204. if ($percentage > $bestp) {
  205. $bestp = $percentage;
  206. $bestt = $arr["text"];
  207. }
  208. }
  209. if ($bestp > 0) {
  210. $bestt = sqlite_escape_string($bestt);
  211. } else {
  212. $bestt = "";
  213. }
  214. $db->queryExec("UPDATE Polls SET resolution = '$bestt', resolution_percentage = $bestp, active = 0 WHERE id = $_GET[id_poll]");
  215. $id_trac = $db->singleQuery("SELECT id_trac FROM Polls WHERE id = $_GET[id_poll]");
  216. if ($id_trac) {
  217. $time = time();
  218. $trac_db->exec("UPDATE ticket SET changetime=$time, status='closed' WHERE id=$id_trac");
  219. $trac_db->exec("INSERT INTO ticket_change (ticket, time, author, field, oldvalue, newvalue) values ($id_trac, $time, '$login', 'status','new','closed')");
  220. $trac_db->exec("INSERT INTO ticket_change (ticket, time, author, field, oldvalue, newvalue) values ($id_trac, $time,'$login', 'comment','','Winner: $bestt ($bestp%)')");
  221. }
  222. }
  223. break;
  224. case "reopenpoll":
  225. if ($power > 0) {
  226. $db->queryExec("UPDATE Polls SET active=1 WHERE id=$_GET[id_poll]");
  227. $id_trac = $db->singleQuery("SELECT id_trac FROM Polls WHERE id = $_GET[id_poll]");
  228. if ($id_trac) {
  229. $time = time();
  230. $trac_db->exec("UPDATE ticket SET changetime=$time, status='reopened' WHERE id=$id_trac");
  231. $trac_db->exec("INSERT INTO ticket_change (ticket, time, author, field, oldvalue, newvalue) values ($id_trac, $time, '$login', 'status','closed','reopened')");
  232. }
  233. }
  234. break;
  235. case "deletepoll":
  236. if ($power > 1) $db->queryExec("DELETE FROM Polls WHERE id=$_GET[id_poll]");
  237. break;
  238. case "deleteuser":
  239. if ($power > 1) $db->queryExec("DELETE FROM Users WHERE id=$_GET[uid]");
  240. break;
  241. }
  242. // set old polls to abstain
  243. $res = $db->query("SELECT id FROM Polls WHERE active=1 AND creation_time < ".(time()- 7*24*3600));
  244. while (($arr = $res->fetch())) {
  245. $idp = $arr[id];
  246. $db->queryExec("INSERT INTO Votes (id_user, id_poll, id_option) SELECT id, $idp, (SELECT id FROM Options WHERE id_poll=$idp AND abstain=1) FROM Users WHERE id NOT IN (SELECT id_user FROM Votes WHERE id_poll=$idp)");
  247. }
  248. // limit display to just one poll
  249. if ($limitone) {
  250. display_poll($limitone, $id_user, $power);
  251. } else {
  252. // active not voted
  253. $res = poll_query(1,0,$id_user);
  254. while (($arr = $res->fetch())) {
  255. display_poll($arr["pid"], $id_user, $power);
  256. }
  257. // active voted
  258. $res = poll_query(1,1,$id_user);
  259. while (($arr = $res->fetch())) {
  260. display_poll($arr["pid"], $id_user, $power);
  261. }
  262. // closed poll list
  263. tabletop(7, "Closed polls", "Details^Question^Resolution^Votes^Created by^Secret^Admin");
  264. $res = $db->query("SELECT * FROM Polls WHERE active=0 ORDER BY creation_time DESC");
  265. while (($arr = $res->fetch())) {
  266. if ($power > 0) $admin = "<a href='index.php?act=reopenpoll&id_poll=$arr[id]'>Reopen</a>";
  267. if ($power > 1) $admin.= " | <a href='index.php?act=deletepoll&id_poll=$arr[id]'>Delete</a>";
  268. tablerow(7, "<a href='index.php?limitone=$arr[id]&traclink=1'>Details</a>^".linkify($arr[question])."^".linkify($arr[resolution])."^".display_weight($arr[resolution_percentage])."^$arr[creator]^".($arr[secret]?"yes":"no")."^$admin");
  269. }
  270. tablebottom();
  271. echo "<br>&nbsp;<br>";
  272. // developers
  273. tabletop(3, "Developers", "Name^Votes^Admin");
  274. $res = $db->query("SELECT login,power,id FROM Users ORDER BY power DESC, login");
  275. while (($arr = $res->fetch())) {
  276. if ($power > 1) $admin = "<a href='index.php?act=adduser&uid=$arr[id]'>Edit</a>&nbsp;|&nbsp;<a href='index.php?act=deleteuser&uid=$arr[id]'>Delete</a>";
  277. else $admin = "";
  278. tablerow(3, "$arr[login]^$arr[power]^$admin");
  279. }
  280. tablebottom();
  281. ?>
  282. <p>
  283. <b>Explanation:</b><br>
  284. Each developer has different number of votes (default 1 for developers, 2 for core developers).<br>
  285. <br>
  286. Each poll can be either <b>secret</b> or not - secret polls don't show who voted for what option.<br>
  287. <br>
  288. In each poll both public (anonymous) and logged users (developers) can vote. Developer votes show as blue bars and public votes as thin red line below.<br>
  289. <b>Vote percentage</b> is the amount of developer's votes for this option out of <b>all</b> developers. (except those abstaining)<br>
  290. <br>
  291. You can put links to both question and options to link to trac.
  292. </p>
  293. <p>
  294. <b>Guidelines:</b><br/>
  295. For general poll (sampling, no decision making yet) use any number of options.<br/>
  296. <br/>
  297. For decision making use only yes/no (abstain added automatically).<br/>
  298. This ensures that at least one option has 50+% votes if all devs vote.<br/>
  299. <br/>
  300. Note that you cannot force anyone to do anything using poll - its just for decision making and solving conflicts in dev team<br/>
  301. Adding a vote like "make all units OTA free" is pointless unless you plan to do it yourself.<br/>
  302. </p>
  303. <?
  304. }
  305. ?>
  306. </div>
  307. </body>
  308. </html>