Remember user ID when flagging package bases
[aur.git] / web / lib / pkgbasefuncs.inc.php
blobdf1ae18660cfcb37ad13ba1a663cc12b297c3eba
1 <?php
3 include_once("pkgreqfuncs.inc.php");
5 /**
6 * Get the number of non-deleted comments for a specific package base
8 * @param string $base_id The package base ID to get comment count for
9 * @param bool $include_deleted True if deleted comments should be included
11 * @return string The number of comments left for a specific package
13 function pkgbase_comments_count($base_id, $include_deleted) {
14 $base_id = intval($base_id);
15 if (!$base_id) {
16 return null;
19 $dbh = DB::connect();
20 $q = "SELECT COUNT(*) FROM PackageComments ";
21 $q.= "WHERE PackageBaseID = " . $base_id . " ";
22 if (!$include_deleted) {
23 $q.= "AND DelUsersID IS NULL";
25 $result = $dbh->query($q);
26 if (!$result) {
27 return null;
30 return $result->fetchColumn(0);
33 /**
34 * Get all package comment information for a specific package base
36 * @param int $base_id The package base ID to get comments for
37 * @param int $limit Maximum number of comments to return (0 means unlimited)
38 * @param bool $include_deleted True if deleted comments should be included
40 * @return array All package comment information for a specific package base
42 function pkgbase_comments($base_id, $limit, $include_deleted) {
43 $base_id = intval($base_id);
44 $limit = intval($limit);
45 if (!$base_id) {
46 return null;
49 $dbh = DB::connect();
50 $q = "SELECT PackageComments.ID, A.UserName AS UserName, UsersID, Comments, ";
51 $q.= "CommentTS, EditedTS, B.UserName AS EditUserName, ";
52 $q.= "DelUsersID, C.UserName AS DelUserName FROM PackageComments ";
53 $q.= "LEFT JOIN Users A ON PackageComments.UsersID = A.ID ";
54 $q.= "LEFT JOIN Users B ON PackageComments.EditedUsersID = B.ID ";
55 $q.= "LEFT JOIN Users C ON PackageComments.DelUsersID = C.ID ";
56 $q.= "WHERE PackageBaseID = " . $base_id . " ";
57 if (!$include_deleted) {
58 $q.= "AND DelUsersID IS NULL ";
60 $q.= "ORDER BY CommentTS DESC";
61 if ($limit > 0) {
62 $q.=" LIMIT " . $limit;
64 $result = $dbh->query($q);
65 if (!$result) {
66 return null;
69 return $result->fetchAll();
72 /**
73 * Add a comment to a package page and send out appropriate notifications
75 * @param string $base_id The package base ID to add the comment on
76 * @param string $uid The user ID of the individual who left the comment
77 * @param string $comment The comment left on a package page
79 * @return void
81 function pkgbase_add_comment($base_id, $uid, $comment) {
82 $dbh = DB::connect();
84 if (trim($comment) == '') {
85 return array(false, __('Comment cannot be empty.'));
88 $q = "INSERT INTO PackageComments ";
89 $q.= "(PackageBaseID, UsersID, Comments, CommentTS) VALUES (";
90 $q.= intval($base_id) . ", " . $uid . ", ";
91 $q.= $dbh->quote($comment) . ", UNIX_TIMESTAMP())";
92 $dbh->exec($q);
95 * Send e-mail notifications.
96 * TODO: Move notification logic to separate function where it belongs.
98 $q = "SELECT CommentNotify.*, Users.Email ";
99 $q.= "FROM CommentNotify, Users ";
100 $q.= "WHERE Users.ID = CommentNotify.UserID ";
101 $q.= "AND CommentNotify.UserID != " . $uid . " ";
102 $q.= "AND CommentNotify.PackageBaseID = " . intval($base_id);
103 $result = $dbh->query($q);
104 $bcc = array();
106 if ($result) {
107 notify(array('comment', $uid, $base_id), $comment);
110 return array(true, __('Comment has been added.'));
114 * Get a list of all packages a logged-in user has voted for
116 * @param string $sid The session ID of the visitor
118 * @return array All packages the visitor has voted for
120 function pkgbase_votes_from_sid($sid="") {
121 $pkgs = array();
122 if (!$sid) {return $pkgs;}
123 $dbh = DB::connect();
124 $q = "SELECT PackageBaseID ";
125 $q.= "FROM PackageVotes, Users, Sessions ";
126 $q.= "WHERE Users.ID = Sessions.UsersID ";
127 $q.= "AND Users.ID = PackageVotes.UsersID ";
128 $q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
129 $result = $dbh->query($q);
130 if ($result) {
131 while ($row = $result->fetch(PDO::FETCH_NUM)) {
132 $pkgs[$row[0]] = 1;
135 return $pkgs;
139 * Get the package base details
141 * @param string $id The package base ID to get description for
143 * @return array The package base's details OR error message
145 function pkgbase_get_details($base_id) {
146 $dbh = DB::connect();
148 $q = "SELECT PackageBases.ID, PackageBases.Name, ";
149 $q.= "PackageBases.NumVotes, PackageBases.Popularity, ";
150 $q.= "PackageBases.OutOfDateTS, PackageBases.SubmittedTS, ";
151 $q.= "PackageBases.ModifiedTS, PackageBases.SubmitterUID, ";
152 $q.= "PackageBases.MaintainerUID, PackageBases.PackagerUID, ";
153 $q.= "(SELECT COUNT(*) FROM PackageRequests ";
154 $q.= " WHERE PackageRequests.PackageBaseID = PackageBases.ID ";
155 $q.= " AND PackageRequests.Status = 0) AS RequestCount ";
156 $q.= "FROM PackageBases ";
157 $q.= "WHERE PackageBases.ID = " . intval($base_id);
158 $result = $dbh->query($q);
160 $row = array();
162 if (!$result) {
163 $row['error'] = __("Error retrieving package details.");
165 else {
166 $row = $result->fetch(PDO::FETCH_ASSOC);
167 if (empty($row)) {
168 $row['error'] = __("Package details could not be found.");
172 return $row;
176 * Display the package base details page
178 * @param string $id The package base ID to get details page for
179 * @param array $row Package base details retrieved by pkgbase_get_details()
180 * @param string $SID The session ID of the visitor
182 * @return void
184 function pkgbase_display_details($base_id, $row, $SID="") {
185 $dbh = DB::connect();
187 if (isset($row['error'])) {
188 print "<p>" . $row['error'] . "</p>\n";
190 else {
191 $pkgbase_name = pkgbase_name_from_id($base_id);
193 include('pkgbase_details.php');
195 if ($SID) {
196 include('pkg_comment_box.php');
199 $limit = isset($_GET['comments']) ? 0 : 10;
200 $include_deleted = has_credential(CRED_COMMENT_VIEW_DELETED);
201 $comments = pkgbase_comments($base_id, $limit, $include_deleted);
202 if (!empty($comments)) {
203 include('pkg_comments.php');
209 * Convert a list of package IDs into a list of corresponding package bases.
211 * @param array|int $ids Array of package IDs to convert
213 * @return array|int List of package base IDs
215 function pkgbase_from_pkgid($ids) {
216 $dbh = DB::connect();
218 if (is_array($ids)) {
219 $q = "SELECT PackageBaseID FROM Packages ";
220 $q.= "WHERE ID IN (" . implode(",", $ids) . ")";
221 $result = $dbh->query($q);
222 return $result->fetchAll(PDO::FETCH_COLUMN, 0);
223 } else {
224 $q = "SELECT PackageBaseID FROM Packages ";
225 $q.= "WHERE ID = " . $ids;
226 $result = $dbh->query($q);
227 return $result->fetch(PDO::FETCH_COLUMN, 0);
232 * Retrieve ID of a package base by name
234 * @param string $name The package base name to retrieve the ID for
236 * @return int The ID of the package base
238 function pkgbase_from_name($name) {
239 $dbh = DB::connect();
240 $q = "SELECT ID FROM PackageBases WHERE Name = " . $dbh->quote($name);
241 $result = $dbh->query($q);
242 return $result->fetch(PDO::FETCH_COLUMN, 0);
246 * Retrieve the name of a package base given its ID
248 * @param int $base_id The ID of the package base to query
250 * @return string The name of the package base
252 function pkgbase_name_from_id($base_id) {
253 $dbh = DB::connect();
254 $q = "SELECT Name FROM PackageBases WHERE ID = " . intval($base_id);
255 $result = $dbh->query($q);
256 return $result->fetch(PDO::FETCH_COLUMN, 0);
260 * Get the names of all packages belonging to a package base
262 * @param int $base_id The ID of the package base
264 * @return array The names of all packages belonging to the package base
266 function pkgbase_get_pkgnames($base_id) {
267 $dbh = DB::connect();
268 $q = "SELECT Name FROM Packages WHERE PackageBaseID = " . intval($base_id);
269 $result = $dbh->query($q);
270 return $result->fetchAll(PDO::FETCH_COLUMN, 0);
274 * Delete all packages belonging to a package base
276 * @param int $base_id The ID of the package base
278 * @return void
280 function pkgbase_delete_packages($base_id) {
281 $dbh = DB::connect();
282 $q = "DELETE FROM Packages WHERE PackageBaseID = " . intval($base_id);
283 $dbh->exec($q);
287 * Retrieve the maintainer of a package base given its ID
289 * @param int $base_id The ID of the package base to query
291 * @return int The user ID of the current package maintainer
293 function pkgbase_maintainer_uid($base_id) {
294 $dbh = DB::connect();
295 $q = "SELECT MaintainerUID FROM PackageBases WHERE ID = " . intval($base_id);
296 $result = $dbh->query($q);
297 return $result->fetch(PDO::FETCH_COLUMN, 0);
301 * Retrieve the maintainers of an array of package bases given by their ID
303 * @param int $base_ids The array of IDs of the package bases to query
305 * @return int The user ID of the current package maintainer
307 function pkgbase_maintainer_uids($base_ids) {
308 $dbh = DB::connect();
309 $q = "SELECT MaintainerUID FROM PackageBases WHERE ID IN (" . implode(",", $base_ids) . ")";
310 $result = $dbh->query($q);
311 return $result->fetchAll(PDO::FETCH_COLUMN, 0);
315 * Flag package(s) as out-of-date
317 * @param array $base_ids Array of package base IDs to flag/unflag
319 * @return array Tuple of success/failure indicator and error message
321 function pkgbase_flag($base_ids) {
322 if (!has_credential(CRED_PKGBASE_FLAG)) {
323 return array(false, __("You must be logged in before you can flag packages."));
326 $base_ids = sanitize_ids($base_ids);
327 if (empty($base_ids)) {
328 return array(false, __("You did not select any packages to flag."));
331 $uid = uid_from_sid($_COOKIE['AURSID']);
332 $dbh = DB::connect();
334 $q = "UPDATE PackageBases SET";
335 $q.= " OutOfDateTS = UNIX_TIMESTAMP(), FlaggerUID = " . $uid;
336 $q.= " WHERE ID IN (" . implode(",", $base_ids) . ")";
337 $q.= " AND OutOfDateTS IS NULL";
338 $dbh->exec($q);
340 foreach ($base_ids as $base_id) {
341 notify(array('flag', $uid, $base_id));
344 return array(true, __("The selected packages have been flagged out-of-date."));
348 * Unflag package(s) as out-of-date
350 * @param array $base_ids Array of package base IDs to flag/unflag
352 * @return array Tuple of success/failure indicator and error message
354 function pkgbase_unflag($base_ids) {
355 $uid = uid_from_sid($_COOKIE["AURSID"]);
356 if (!$uid) {
357 return array(false, __("You must be logged in before you can unflag packages."));
360 $base_ids = sanitize_ids($base_ids);
361 if (empty($base_ids)) {
362 return array(false, __("You did not select any packages to unflag."));
365 $dbh = DB::connect();
367 $q = "UPDATE PackageBases SET ";
368 $q.= "OutOfDateTS = NULL ";
369 $q.= "WHERE ID IN (" . implode(",", $base_ids) . ") ";
371 $maintainers = array_merge(pkgbase_maintainer_uids($base_ids), pkgbase_get_comaintainer_uids($base_ids));
372 if (!has_credential(CRED_PKGBASE_UNFLAG, $maintainers)) {
373 $q.= "AND MaintainerUID = " . $uid;
376 $result = $dbh->exec($q);
378 if ($result) {
379 return array(true, __("The selected packages have been unflagged."));
384 * Delete package bases
386 * @param array $base_ids Array of package base IDs to delete
387 * @param int $merge_base_id Package base to merge the deleted ones into
388 * @param int $via Package request to close upon deletion
389 * @param bool $grant Allow anyone to delete the package base
391 * @return array Tuple of success/failure indicator and error message
393 function pkgbase_delete ($base_ids, $merge_base_id, $via, $grant=false) {
394 if (!$grant && !has_credential(CRED_PKGBASE_DELETE)) {
395 return array(false, __("You do not have permission to delete packages."));
398 $base_ids = sanitize_ids($base_ids);
399 if (empty($base_ids)) {
400 return array(false, __("You did not select any packages to delete."));
403 $dbh = DB::connect();
405 if ($merge_base_id) {
406 $merge_base_name = pkgbase_name_from_id($merge_base_id);
409 $uid = uid_from_sid($_COOKIE['AURSID']);
410 foreach ($base_ids as $base_id) {
411 if ($merge_base_id) {
412 notify(array('delete', $uid, $base_id, $merge_base_id));
413 } else {
414 notify(array('delete', $uid, $base_id));
419 * Close package request if the deletion was initiated through the
420 * request interface. NOTE: This needs to happen *before* the actual
421 * deletion. Otherwise, the former maintainer will not be included in
422 * the Cc list of the request notification email.
424 if ($via) {
425 pkgreq_close(intval($via), 'accepted', '');
428 /* Scan through pending deletion requests and close them. */
429 if (!$action) {
430 $username = username_from_sid($_COOKIE['AURSID']);
431 foreach ($base_ids as $base_id) {
432 $pkgreq_ids = array_merge(pkgreq_by_pkgbase($base_id));
433 foreach ($pkgreq_ids as $pkgreq_id) {
434 pkgreq_close(intval($pkgreq_id), 'accepted',
435 'The user ' . $username .
436 ' deleted the package.', true);
441 if ($merge_base_id) {
442 /* Merge comments */
443 $q = "UPDATE PackageComments ";
444 $q.= "SET PackageBaseID = " . intval($merge_base_id) . " ";
445 $q.= "WHERE PackageBaseID IN (" . implode(",", $base_ids) . ")";
446 $dbh->exec($q);
448 /* Merge votes */
449 foreach ($base_ids as $base_id) {
450 $q = "UPDATE PackageVotes ";
451 $q.= "SET PackageBaseID = " . intval($merge_base_id) . " ";
452 $q.= "WHERE PackageBaseID = " . $base_id . " ";
453 $q.= "AND UsersID NOT IN (";
454 $q.= "SELECT * FROM (SELECT UsersID ";
455 $q.= "FROM PackageVotes ";
456 $q.= "WHERE PackageBaseID = " . intval($merge_base_id);
457 $q.= ") temp)";
458 $dbh->exec($q);
461 $q = "UPDATE PackageBases ";
462 $q.= "SET NumVotes = (SELECT COUNT(*) FROM PackageVotes ";
463 $q.= "WHERE PackageBaseID = " . intval($merge_base_id) . ") ";
464 $q.= "WHERE ID = " . intval($merge_base_id);
465 $dbh->exec($q);
468 $q = "DELETE FROM Packages WHERE PackageBaseID IN (" . implode(",", $base_ids) . ")";
469 $dbh->exec($q);
471 $q = "DELETE FROM PackageBases WHERE ID IN (" . implode(",", $base_ids) . ")";
472 $dbh->exec($q);
474 return array(true, __("The selected packages have been deleted."));
478 * Adopt or disown packages
480 * @param array $base_ids Array of package base IDs to adopt/disown
481 * @param bool $action Adopts if true, disowns if false. Adopts by default
482 * @param int $via Package request to close upon adoption
484 * @return array Tuple of success/failure indicator and error message
486 function pkgbase_adopt ($base_ids, $action=true, $via) {
487 $dbh = DB::connect();
489 $uid = uid_from_sid($_COOKIE["AURSID"]);
490 if (!$uid) {
491 if ($action) {
492 return array(false, __("You must be logged in before you can adopt packages."));
493 } else {
494 return array(false, __("You must be logged in before you can disown packages."));
498 /* Verify package ownership. */
499 $base_ids = sanitize_ids($base_ids);
501 $q = "SELECT ID FROM PackageBases ";
502 $q.= "WHERE ID IN (" . implode(",", $base_ids) . ") ";
504 if ($action && !has_credential(CRED_PKGBASE_ADOPT)) {
505 /* Regular users may only adopt orphan packages. */
506 $q.= "AND MaintainerUID IS NULL";
508 if (!$action && !has_credential(CRED_PKGBASE_DISOWN)) {
509 /* Regular users may only disown their own packages. */
510 $q.= "AND MaintainerUID = " . $uid;
513 $result = $dbh->query($q);
514 $base_ids = $result->fetchAll(PDO::FETCH_COLUMN, 0);
516 /* Error out if the list of remaining packages is empty. */
517 if (empty($base_ids)) {
518 if ($action) {
519 return array(false, __("You did not select any packages to adopt."));
520 } else {
521 return array(false, __("You did not select any packages to disown."));
526 * Close package request if the disownment was initiated through the
527 * request interface. NOTE: This needs to happen *before* the actual
528 * disown operation. Otherwise, the former maintainer will not be
529 * included in the Cc list of the request notification email.
531 if ($via) {
532 pkgreq_close(intval($via), 'accepted', '');
535 /* Scan through pending orphan requests and close them. */
536 if (!$action) {
537 $username = username_from_sid($_COOKIE['AURSID']);
538 foreach ($base_ids as $base_id) {
539 $pkgreq_ids = pkgreq_by_pkgbase($base_id, 'orphan');
540 foreach ($pkgreq_ids as $pkgreq_id) {
541 pkgreq_close(intval($pkgreq_id), 'accepted',
542 'The user ' . $username .
543 ' disowned the package.', true);
548 /* Adopt or disown the package. */
549 if ($action) {
550 $q = "UPDATE PackageBases ";
551 $q.= "SET MaintainerUID = $uid ";
552 $q.= "WHERE ID IN (" . implode(",", $base_ids) . ") ";
553 $dbh->exec($q);
554 } else {
555 /* Update the co-maintainer list when disowning a package. */
556 if (has_credential(CRED_PKGBASE_DISOWN)) {
557 foreach ($base_ids as $base_id) {
558 pkgbase_set_comaintainers($base_id, array());
561 $q = "UPDATE PackageBases ";
562 $q.= "SET MaintainerUID = NULL ";
563 $q.= "WHERE ID IN (" . implode(",", $base_ids) . ") ";
564 $dbh->exec($q);
565 } else {
566 foreach ($base_ids as $base_id) {
567 $comaintainers = pkgbase_get_comaintainers($base_id);
569 if (count($comaintainers) > 0) {
570 $uid = uid_from_username($comaintainers[0]);
571 $comaintainers = array_diff($comaintainers, array($comaintainers[0]));
572 pkgbase_set_comaintainers($base_id, $comaintainers);
573 } else {
574 $uid = "NULL";
577 $q = "UPDATE PackageBases ";
578 $q.= "SET MaintainerUID = " . $uid . " ";
579 $q.= "WHERE ID = " . $base_id;
580 $dbh->exec($q);
585 if ($action) {
586 pkgbase_notify($base_ids);
587 return array(true, __("The selected packages have been adopted."));
588 } else {
589 return array(true, __("The selected packages have been disowned."));
594 * Vote and un-vote for packages
596 * @param array $base_ids Array of package base IDs to vote/un-vote
597 * @param bool $action Votes if true, un-votes if false. Votes by default
599 * @return array Tuple of success/failure indicator and error message
601 function pkgbase_vote ($base_ids, $action=true) {
602 if (!has_credential(CRED_PKGBASE_VOTE)) {
603 if ($action) {
604 return array(false, __("You must be logged in before you can vote for packages."));
605 } else {
606 return array(false, __("You must be logged in before you can un-vote for packages."));
610 $base_ids = sanitize_ids($base_ids);
611 if (empty($base_ids)) {
612 if ($action) {
613 return array(false, __("You did not select any packages to vote for."));
614 } else {
615 return array(false, __("Your votes have been removed from the selected packages."));
619 $dbh = DB::connect();
620 $my_votes = pkgbase_votes_from_sid($_COOKIE["AURSID"]);
621 $uid = uid_from_sid($_COOKIE["AURSID"]);
623 $first = 1;
624 foreach ($base_ids as $pid) {
625 if ($action) {
626 $check = !isset($my_votes[$pid]);
627 } else {
628 $check = isset($my_votes[$pid]);
631 if ($check) {
632 if ($first) {
633 $first = 0;
634 $vote_ids = $pid;
635 if ($action) {
636 $vote_clauses = "($uid, $pid, UNIX_TIMESTAMP())";
638 } else {
639 $vote_ids .= ", $pid";
640 if ($action) {
641 $vote_clauses .= ", ($uid, $pid, UNIX_TIMESTAMP())";
647 /* Only add votes for packages the user hasn't already voted for. */
648 $op = $action ? "+" : "-";
649 $q = "UPDATE PackageBases SET NumVotes = NumVotes $op 1 ";
650 $q.= "WHERE ID IN ($vote_ids)";
652 $dbh->exec($q);
654 if ($action) {
655 $q = "INSERT INTO PackageVotes (UsersID, PackageBaseID, VoteTS) VALUES ";
656 $q.= $vote_clauses;
657 } else {
658 $q = "DELETE FROM PackageVotes WHERE UsersID = $uid ";
659 $q.= "AND PackageBaseID IN ($vote_ids)";
662 $dbh->exec($q);
664 if ($action) {
665 return array(true, __("Your votes have been cast for the selected packages."));
666 } else {
667 return array(true, __("Your votes have been removed from the selected packages."));
672 * Get all usernames and IDs that voted for a specific package base
674 * @param string $pkgbase_name The package base to retrieve votes for
676 * @return array User IDs and usernames that voted for a specific package base
678 function pkgbase_votes_from_name($pkgbase_name) {
679 $dbh = DB::connect();
681 $q = "SELECT UsersID, Username, Name, VoteTS FROM PackageVotes ";
682 $q.= "LEFT JOIN Users ON UsersID = Users.ID ";
683 $q.= "LEFT JOIN PackageBases ";
684 $q.= "ON PackageVotes.PackageBaseID = PackageBases.ID ";
685 $q.= "WHERE PackageBases.Name = ". $dbh->quote($pkgbase_name) . " ";
686 $q.= "ORDER BY Username";
687 $result = $dbh->query($q);
689 if (!$result) {
690 return;
693 $votes = array();
694 while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
695 $votes[] = $row;
698 return $votes;
702 * Determine if a user has already voted for a specific package base
704 * @param string $uid The user ID to check for an existing vote
705 * @param string $base_id The package base ID to check for an existing vote
707 * @return bool True if the user has already voted, otherwise false
709 function pkgbase_user_voted($uid, $base_id) {
710 $dbh = DB::connect();
711 $q = "SELECT COUNT(*) FROM PackageVotes WHERE ";
712 $q.= "UsersID = ". $dbh->quote($uid) . " AND ";
713 $q.= "PackageBaseID = " . $dbh->quote($base_id);
714 $result = $dbh->query($q);
715 if (!$result) {
716 return null;
719 return ($result->fetch(PDO::FETCH_COLUMN, 0) > 0);
723 * Determine if a user wants notifications for a specific package base
725 * @param string $uid User ID to check in the database
726 * @param string $base_id Package base ID to check notifications for
728 * @return bool True if the user wants notifications, otherwise false
730 function pkgbase_user_notify($uid, $base_id) {
731 $dbh = DB::connect();
733 $q = "SELECT * FROM CommentNotify WHERE UserID = " . $dbh->quote($uid);
734 $q.= " AND PackageBaseID = " . $dbh->quote($base_id);
735 $result = $dbh->query($q);
737 if ($result->fetch(PDO::FETCH_NUM)) {
738 return true;
740 else {
741 return false;
746 * Toggle notification of packages
748 * @param array $base_ids Array of package base IDs to toggle
750 * @return array Tuple of success/failure indicator and error message
752 function pkgbase_notify ($base_ids, $action=true) {
753 if (!has_credential(CRED_PKGBASE_NOTIFY)) {
754 return;
757 $base_ids = sanitize_ids($base_ids);
758 if (empty($base_ids)) {
759 return array(false, __("Couldn't add to notification list."));
762 $dbh = DB::connect();
763 $uid = uid_from_sid($_COOKIE["AURSID"]);
765 $output = "";
767 $first = true;
770 * There currently shouldn't be multiple requests here, but the format
771 * in which it's sent requires this.
773 foreach ($base_ids as $bid) {
774 $q = "SELECT Name FROM PackageBases WHERE ID = $bid";
775 $result = $dbh->query($q);
776 if ($result) {
777 $row = $result->fetch(PDO::FETCH_NUM);
778 $basename = $row[0];
780 else {
781 $basename = '';
784 if ($first)
785 $first = false;
786 else
787 $output .= ", ";
790 if ($action) {
791 $q = "SELECT COUNT(*) FROM CommentNotify WHERE ";
792 $q .= "UserID = $uid AND PackageBaseID = $bid";
794 /* Notification already added. Don't add again. */
795 $result = $dbh->query($q);
796 if ($result->fetchColumn() == 0) {
797 $q = "INSERT INTO CommentNotify (PackageBaseID, UserID) VALUES ($bid, $uid)";
798 $dbh->exec($q);
801 $output .= $basename;
803 else {
804 $q = "DELETE FROM CommentNotify WHERE PackageBaseID = $bid ";
805 $q .= "AND UserID = $uid";
806 $dbh->exec($q);
808 $output .= $basename;
812 if ($action) {
813 $output = __("You have been added to the comment notification list for %s.", $output);
815 else {
816 $output = __("You have been removed from the comment notification list for %s.", $output);
819 return array(true, $output);
823 * Delete a package comment
825 * @return array Tuple of success/failure indicator and error message
827 function pkgbase_delete_comment() {
828 $uid = uid_from_sid($_COOKIE["AURSID"]);
829 if (!$uid) {
830 return array(false, __("You must be logged in before you can edit package information."));
833 if (isset($_POST["comment_id"])) {
834 $comment_id = $_POST["comment_id"];
835 } else {
836 return array(false, __("Missing comment ID."));
839 $dbh = DB::connect();
840 if (can_delete_comment($comment_id)) {
841 $q = "UPDATE PackageComments ";
842 $q.= "SET DelUsersID = ".$uid.", ";
843 $q.= "EditedTS = UNIX_TIMESTAMP() ";
844 $q.= "WHERE ID = ".intval($comment_id);
845 $dbh->exec($q);
846 return array(true, __("Comment has been deleted."));
847 } else {
848 return array(false, __("You are not allowed to delete this comment."));
853 * Edit a package comment
855 * @return array Tuple of success/failure indicator and error message
857 function pkgbase_edit_comment($comment) {
858 $uid = uid_from_sid($_COOKIE["AURSID"]);
859 if (!$uid) {
860 return array(false, __("You must be logged in before you can edit package information."));
863 if (isset($_POST["comment_id"])) {
864 $comment_id = $_POST["comment_id"];
865 } else {
866 return array(false, __("Missing comment ID."));
869 if (trim($comment) == '') {
870 return array(false, __('Comment cannot be empty.'));
873 $dbh = DB::connect();
874 if (can_edit_comment($comment_id)) {
875 $q = "UPDATE PackageComments ";
876 $q.= "SET EditedUsersID = ".$uid.", ";
877 $q.= "Comments = ".$dbh->quote($comment).", ";
878 $q.= "EditedTS = UNIX_TIMESTAMP() ";
879 $q.= "WHERE ID = ".intval($comment_id);
880 $dbh->exec($q);
881 return array(true, __("Comment has been edited."));
882 } else {
883 return array(false, __("You are not allowed to edit this comment."));
888 * Get a list of package base keywords
890 * @param int $base_id The package base ID to retrieve the keywords for
892 * @return array An array of keywords
894 function pkgbase_get_keywords($base_id) {
895 $dbh = DB::connect();
896 $q = "SELECT Keyword FROM PackageKeywords ";
897 $q .= "WHERE PackageBaseID = " . intval($base_id) . " ";
898 $q .= "ORDER BY Keyword ASC";
899 $result = $dbh->query($q);
901 if ($result) {
902 return $result->fetchAll(PDO::FETCH_COLUMN, 0);
903 } else {
904 return array();
909 * Update the list of keywords of a package base
911 * @param int $base_id The package base ID to update the keywords of
912 * @param array $users Array of keywords
914 * @return array Tuple of success/failure indicator and error message
916 function pkgbase_set_keywords($base_id, $keywords) {
917 $base_id = intval($base_id);
919 $maintainers = array_merge(array(pkgbase_maintainer_uid($base_id)), pkgbase_get_comaintainer_uids(array($base_id)));
920 if (!has_credential(CRED_PKGBASE_SET_KEYWORDS, $maintainers)) {
921 return array(false, __("You are not allowed to edit the keywords of this package base."));
924 /* Remove empty and duplicate user names. */
925 $keywords = array_unique(array_filter(array_map('trim', $keywords)));
927 $dbh = DB::connect();
929 $q = sprintf("DELETE FROM PackageKeywords WHERE PackageBaseID = %d", $base_id);
930 $dbh->exec($q);
932 $i = 0;
933 foreach ($keywords as $keyword) {
934 $q = sprintf("INSERT INTO PackageKeywords (PackageBaseID, Keyword) VALUES (%d, %s)", $base_id, $dbh->quote($keyword));
935 var_dump($q);
936 $dbh->exec($q);
938 $i++;
939 if ($i >= 20) {
940 break;
944 return array(true, __("The package base keywords have been updated."));
948 * Get a list of package base co-maintainers
950 * @param int $base_id The package base ID to retrieve the co-maintainers for
952 * @return array An array of co-maintainer user names
954 function pkgbase_get_comaintainers($base_id) {
955 $dbh = DB::connect();
956 $q = "SELECT UserName FROM PackageComaintainers ";
957 $q .= "INNER JOIN Users ON Users.ID = PackageComaintainers.UsersID ";
958 $q .= "WHERE PackageComaintainers.PackageBaseID = " . intval($base_id) . " ";
959 $q .= "ORDER BY Priority ASC";
960 $result = $dbh->query($q);
962 if ($result) {
963 return $result->fetchAll(PDO::FETCH_COLUMN, 0);
964 } else {
965 return array();
970 * Get a list of package base co-maintainer IDs
972 * @param int $base_id The package base ID to retrieve the co-maintainers for
974 * @return array An array of co-maintainer user UDs
976 function pkgbase_get_comaintainer_uids($base_ids) {
977 $dbh = DB::connect();
978 $q = "SELECT UsersID FROM PackageComaintainers ";
979 $q .= "INNER JOIN Users ON Users.ID = PackageComaintainers.UsersID ";
980 $q .= "WHERE PackageComaintainers.PackageBaseID IN (" . implode(",", $base_ids) . ") ";
981 $q .= "ORDER BY Priority ASC";
982 $result = $dbh->query($q);
984 if ($result) {
985 return $result->fetchAll(PDO::FETCH_COLUMN, 0);
986 } else {
987 return array();
992 * Update the list of co-maintainers of a package base
994 * @param int $base_id The package base ID to update the co-maintainers of
995 * @param array $users Array of co-maintainer user names
997 * @return array Tuple of success/failure indicator and error message
999 function pkgbase_set_comaintainers($base_id, $users) {
1000 if (!has_credential(CRED_PKGBASE_EDIT_COMAINTAINERS, array(pkgbase_maintainer_uid($base_id)))) {
1001 return array(false, __("You are not allowed to manage co-maintainers of this package base."));
1004 /* Remove empty and duplicate user names. */
1005 $users = array_unique(array_filter(array_map('trim', $users)));
1007 $dbh = DB::connect();
1009 $uids = array();
1010 foreach($users as $user) {
1011 $q = "SELECT ID FROM Users ";
1012 $q .= "WHERE UserName = " . $dbh->quote($user);
1013 $result = $dbh->query($q);
1014 $uid = $result->fetchColumn(0);
1016 if (!$uid) {
1017 return array(false, __("Invalid user name: %s", $user));
1020 $uids[] = $uid;
1023 $q = sprintf("DELETE FROM PackageComaintainers WHERE PackageBaseID = %d", $base_id);
1024 $dbh->exec($q);
1026 $i = 1;
1027 foreach ($uids as $uid) {
1028 $q = sprintf("INSERT INTO PackageComaintainers (PackageBaseID, UsersID, Priority) VALUES (%d, %d, %d)", $base_id, $uid, $i);
1029 $dbh->exec($q);
1030 $i++;
1033 return array(true, __("The package base co-maintainers have been updated."));