[aur-dev] [PATCH 1/6] Add support for filing package requests
Add a new entry to the package actions box that allows for filing deletion and orphan requests. When choosing that action, the user is redirected to a new page that allows for selecting a request type and entering a comment. When submitting the request, a new entry in the request database is created and an email is sent to a configurable mailing list (defaults to aur-general). Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> --- UPGRADING | 31 ++++++++++++++ schema/aur-schema.sql | 28 +++++++++++++ web/html/index.php | 3 ++ web/html/pkgbase.php | 2 + web/html/pkgreq.php | 55 +++++++++++++++++++++++++ web/lib/config.inc.php.proto | 3 ++ web/lib/pkgbasefuncs.inc.php | 88 ++++++++++++++++++++++++++++++++++++++++ web/template/pkg_details.php | 1 + web/template/pkgbase_details.php | 1 + 9 files changed, 212 insertions(+) create mode 100644 web/html/pkgreq.php diff --git a/UPGRADING b/UPGRADING index 863fde3..455118e 100644 --- a/UPGRADING +++ b/UPGRADING @@ -1,6 +1,37 @@ Upgrading ========= +From 3.1.0 to 3.2.0 +------------------- + +1. Add support for package requests to the database: + +---- +CREATE TABLE RequestTypes ( + ID TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, + Name VARCHAR(32) NOT NULL DEFAULT '', + PRIMARY KEY (ID) +) ENGINE = InnoDB; +INSERT INTO RequestTypes VALUES (1, 'deletion'); +INSERT INTO RequestTypes VALUES (2, 'orphan'); + +CREATE TABLE PackageRequests ( + ID BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + ReqTypeID TINYINT UNSIGNED NOT NULL, + PackageBaseID INTEGER UNSIGNED NULL, + PackageBaseName VARCHAR(255) NOT NULL, + UsersID INTEGER UNSIGNED NULL DEFAULT NULL, + Comments TEXT NOT NULL DEFAULT '', + RequestTS BIGINT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (ID), + INDEX (UsersID), + INDEX (PackageBaseID), + FOREIGN KEY (ReqTypeID) REFERENCES RequestTypes(ID) ON DELETE NO ACTION, + FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE SET NULL, + FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE SET NULL +) ENGINE = InnoDB; +---- + From 3.0.0 to 3.1.0 ------------------- diff --git a/schema/aur-schema.sql b/schema/aur-schema.sql index 0efae93..88f9974 100644 --- a/schema/aur-schema.sql +++ b/schema/aur-schema.sql @@ -288,6 +288,34 @@ CREATE TABLE PackageBlacklist ( UNIQUE (Name) ) ENGINE = InnoDB; +-- Define package request types +-- +CREATE TABLE RequestTypes ( + ID TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, + Name VARCHAR(32) NOT NULL DEFAULT '', + PRIMARY KEY (ID) +) ENGINE = InnoDB; +INSERT INTO RequestTypes VALUES (1, 'deletion'); +INSERT INTO RequestTypes VALUES (2, 'orphan'); + +-- Package requests +-- +CREATE TABLE PackageRequests ( + ID BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + ReqTypeID TINYINT UNSIGNED NOT NULL, + PackageBaseID INTEGER UNSIGNED NULL, + PackageBaseName VARCHAR(255) NOT NULL, + UsersID INTEGER UNSIGNED NULL DEFAULT NULL, + Comments TEXT NOT NULL DEFAULT '', + RequestTS BIGINT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (ID), + INDEX (UsersID), + INDEX (PackageBaseID), + FOREIGN KEY (ReqTypeID) REFERENCES RequestTypes(ID) ON DELETE NO ACTION, + FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE SET NULL, + FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE SET NULL +) ENGINE = InnoDB; + -- Vote information -- CREATE TABLE IF NOT EXISTS TU_VoteInfo ( diff --git a/web/html/index.php b/web/html/index.php index 921839a..40063f0 100644 --- a/web/html/index.php +++ b/web/html/index.php @@ -75,6 +75,9 @@ if (!empty($tokens[1]) && '/' . $tokens[1] == get_pkg_route()) { $_GET['N'] = $tokens[2]; include('voters.php'); return; + case "request": + include('pkgreq.php'); + return; default: header("HTTP/1.0 404 Not Found"); include "./404.php"; diff --git a/web/html/pkgbase.php b/web/html/pkgbase.php index 0d1b74a..dd09977 100644 --- a/web/html/pkgbase.php +++ b/web/html/pkgbase.php @@ -94,6 +94,8 @@ if (check_token()) { list($ret, $output) = pkgbase_delete_comment($atype); } elseif (current_action("do_ChangeCategory")) { list($ret, $output) = pkgbase_change_category($base_id, $atype); + } elseif (current_action("do_FileRequest")) { + list($ret, $output) = pkgbase_file_request($ids, $_POST['type'], $_POST['comments']); } if (isset($_REQUEST['comment'])) { diff --git a/web/html/pkgreq.php b/web/html/pkgreq.php new file mode 100644 index 0000000..c8dd673 --- /dev/null +++ b/web/html/pkgreq.php @@ -0,0 +1,55 @@ +<?php + +set_include_path(get_include_path() . PATH_SEPARATOR . '../lib'); + +include_once("aur.inc.php"); +include_once("pkgfuncs.inc.php"); + +set_lang(); +check_sid(); + +html_header(__("File Request")); + +if (!check_user_privileges()) { + header('Location: /'); + exit(); +} +?> + +<div class="box"> + <h2><?= __('File Request: %s', htmlspecialchars($pkgbase_name)) ?></h2> + <p> + <?= __('Use this form to file a request against package base %s%s%s which includes the following packages:', + '<strong>', htmlspecialchars($pkgbase_name), '</strong>'); ?> + </p> + <ul> + <?php foreach(pkgbase_get_pkgnames($base_id) as $pkgname): ?> + <li><?= htmlspecialchars($pkgname) ?></li> + <?php endforeach; ?> + </ul> + <form action="<?= get_uri('/pkgbase/'); ?>" method="post"> + <fieldset> + <input type="hidden" name="IDs[<?= $base_id ?>]" value="1" /> + <input type="hidden" name="ID" value="<?= $base_id ?>" /> + <input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" /> + <p> + <label for="id_type"><?= __("Request type") ?>:</label> + <select name="type" id="id_type"> + <option value="deletion"><?= __('Deletion') ?></option> + <option value="orphan"><?= __('Orphan') ?></option> + </select> + </p> + <p> + <label for="id_comments"><?= __("Comments") ?>:</label> + <textarea name="comments" id="id_comments" rows="5" cols="50"></textarea> + </p> + <p> + <input type="submit" class="button" name="do_FileRequest" value="<?= __("File Request") ?>" /> + </p> + </fieldset> + </form> +</div> + +<?php +html_footer(AUR_VERSION); + diff --git a/web/lib/config.inc.php.proto b/web/lib/config.inc.php.proto index 1fe7dbc..10ed07e 100644 --- a/web/lib/config.inc.php.proto +++ b/web/lib/config.inc.php.proto @@ -59,3 +59,6 @@ $USE_VIRTUAL_URLS = true; # Maximum number of package results to return through an RPC connection. # Avoid setting this too high and having a PHP too much memory error. $MAX_RPC_RESULTS = 5000; + +# Mailing list to send package request notifications to. +$AUR_REQUEST_ML = "aur-general@archlinux.org"; diff --git a/web/lib/pkgbasefuncs.inc.php b/web/lib/pkgbasefuncs.inc.php index 9f80ef2..a9fe949 100644 --- a/web/lib/pkgbasefuncs.inc.php +++ b/web/lib/pkgbasefuncs.inc.php @@ -962,3 +962,91 @@ function pkgbase_update_category($base_id, $category_id) { $category_id, $base_id); $dbh->exec($q); } + +/** + * File a deletion/orphan request against a package base + * + * @global string $AUR_LOCATION The AUR's URL used for notification e-mails + * @global string $AUR_REQUEST_ML The request notification mailing list + * @param string $ids The package base IDs to file the request against + * @param string $type The type of the request + * @param string $comments The comments to be added to the request + * + * @return void + */ +function pkgbase_file_request($ids, $type, $comments) { + global $AUR_LOCATION; + global $AUR_REQUEST_ML; + + if (empty($comments)) { + return array(false, __("The comment field must not be empty.")); + } + + $dbh = DB::connect(); + $uid = uid_from_sid($_COOKIE["AURSID"]); + + /* TODO: Allow for filing multiple requests at once. */ + $base_id = $ids[0]; + $pkgbase_name = pkgbase_name_from_id($base_id); + + $q = "SELECT ID FROM RequestTypes WHERE Name = " . $dbh->quote($type); + $result = $dbh->query($q); + if ($row = $result->fetch(PDO::FETCH_ASSOC)) { + $type_id = $row['ID']; + } else { + return array(false, __("Invalid request type.")); + } + + $q = "INSERT INTO PackageRequests "; + $q.= "(ReqTypeID, PackageBaseID, PackageBaseName, UsersID, "; + $q.= "Comments, RequestTS) VALUES (" . $type_id . ", "; + $q.= intval($base_id) . ", " . $dbh->quote($pkgbase_name) . ", "; + $q.= $uid . ", " . $dbh->quote($comments) . ", UNIX_TIMESTAMP())"; + $dbh->exec($q); + + /* + * Send e-mail notifications. + * TODO: Move notification logic to separate function where it belongs. + */ + $q = "SELECT Users.Email "; + $q.= "FROM Users INNER JOIN PackageBases "; + $q.= "ON PackageBases.MaintainerUID = Users.ID "; + $q.= "WHERE PackageBases.ID = " . intval($base_id); + $result = $dbh->query($q); + if ($row = $result->fetch(PDO::FETCH_ASSOC)) { + $bcc = $row['Email']; + } else { + unset($bcc); + } + + $q = "SELECT Name FROM PackageBases WHERE ID = "; + $q.= intval($base_id); + $result = $dbh->query($q); + $row = $result->fetch(PDO::FETCH_ASSOC); + + /* + * TODO: Add native language emails for users, based on their + * preferences. Simply making these strings translatable won't + * work, users would be getting emails in the language that the + * user who posted the comment was in. + */ + $username = username_from_sid($_COOKIE['AURSID']); + $body = + $username . " [1] filed a " . $type . " request for " . + $row['Name'] . " [2]:\n\n" . $comments . "\n\n" . + "[1] " . $AUR_LOCATION . get_user_uri($username) . "\n" . + "[2] " . $AUR_LOCATION . get_pkgbase_uri($row['Name']) . "\n"; + $body = wordwrap($body, 70); + $headers = "MIME-Version: 1.0\r\n" . + "Content-type: text/plain; charset=UTF-8\r\n"; + if (!empty($bcc)) { + $headers .= "Bcc: $bcc\r\n"; + } + $headers .= "Reply-to: noreply@aur.archlinux.org\r\n" . + "From: notify@aur.archlinux.org\r\n" . + "X-Mailer: AUR"; + @mail($AUR_REQUEST_ML, "AUR " . ucfirst($type) . " Request for " . + $row['Name'], $body, $headers); + + return array(true, __("Added request successfully.")); +} diff --git a/web/template/pkg_details.php b/web/template/pkg_details.php index 6326d4e..065057a 100644 --- a/web/template/pkg_details.php +++ b/web/template/pkg_details.php @@ -106,6 +106,7 @@ $sources = pkg_sources($row["ID"]); </form> </li> <?php endif; ?> + <li><a href="<?= get_pkgbase_uri($row['BaseName']) . 'request/'; ?>"><?= __('File Request'); ?></a></li> <?php if ($atype == "Trusted User" || $atype == "Developer"): ?> <li><a href="<?= get_pkgbase_uri($row['BaseName']) . 'delete/'; ?>"><?= __('Delete Package'); ?></a></li> <li><a href="<?= get_pkgbase_uri($row['BaseName']) . 'merge/'; ?>"><?= __('Merge Package'); ?></a></li> diff --git a/web/template/pkgbase_details.php b/web/template/pkgbase_details.php index 6c617bf..1b40b84 100644 --- a/web/template/pkgbase_details.php +++ b/web/template/pkgbase_details.php @@ -81,6 +81,7 @@ $pkgs = pkgbase_get_pkgnames($base_id); </form> </li> <?php endif; ?> + <li><a href="<?= get_pkgbase_uri($row['BaseName']) . 'request/'; ?>"><?= __('File Request'); ?></a></li> <?php if ($atype == "Trusted User" || $atype == "Developer"): ?> <li><a href="<?= get_pkgbase_uri($row['Name']) . 'delete/'; ?>"><?= __('Delete Package'); ?></a></li> <li><a href="<?= get_pkgbase_uri($row['Name']) . 'merge/'; ?>"><?= __('Merge Package'); ?></a></li> -- 2.0.0
Introduce a new navigation point "Requests" that shows a list of pending package requests. This functionality is only available to Trusted Users. Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> --- web/html/pkgreq.php | 58 ++++++++++++++++++++++++++++++++++++ web/lib/pkgbasefuncs.inc.php | 20 +++++++++++++ web/lib/routing.inc.php | 1 + web/template/header.php | 3 ++ web/template/pkgreq_results.php | 66 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+) create mode 100644 web/template/pkgreq_results.php diff --git a/web/html/pkgreq.php b/web/html/pkgreq.php index c8dd673..05eeb51 100644 --- a/web/html/pkgreq.php +++ b/web/html/pkgreq.php @@ -14,6 +14,62 @@ if (!check_user_privileges()) { header('Location: /'); exit(); } + +if (!isset($base_id)) { + $results = pkgbase_request_list(); + $total = count($results); + + /* Sanitize paging variables. */ + if (isset($_GET['O'])) { + $_GET['O'] = intval($_GET['O']); + if ($_GET['O'] < 0) + $_GET['O'] = 0; + } else { + $_GET['O'] = 0; + } + + if (isset($_GET["PP"])) { + $_GET["PP"] = intval($_GET["PP"]); + if ($_GET["PP"] < 50) + $_GET["PP"] = 50; + else if ($_GET["PP"] > 250) + $_GET["PP"] = 250; + } else { + $_GET["PP"] = 50; + } + + /* Calculate the results to use. */ + $first = $_GET['O'] + 1; + + /* Calculation of pagination links. */ + $per_page = ($_GET['PP'] > 0) ? $_GET['PP'] : 50; + $current = ceil($first / $per_page); + $pages = ceil($total / $per_page); + $templ_pages = array(); + + if ($current > 1) { + $templ_pages['« ' . __('First')] = 0; + $templ_pages['‹ ' . __('Previous')] = ($current - 2) * $per_page; + } + + if ($current - 5 > 1) + $templ_pages["..."] = false; + + for ($i = max($current - 5, 1); $i <= min($pages, $current + 5); $i++) { + $templ_pages[$i] = ($i - 1) * $per_page; + } + + if ($current + 5 < $pages) + $templ_pages["... "] = false; + + if ($current < $pages) { + $templ_pages[__('Next') . ' ›'] = $current * $per_page; + $templ_pages[__('Last') . ' »'] = ($pages - 1) * $per_page; + } + + $SID = $_COOKIE['AURSID']; + include('pkgreq_results.php'); +} else { ?> <div class="box"> @@ -51,5 +107,7 @@ if (!check_user_privileges()) { </div> <?php +} + html_footer(AUR_VERSION); diff --git a/web/lib/pkgbasefuncs.inc.php b/web/lib/pkgbasefuncs.inc.php index a9fe949..505bb51 100644 --- a/web/lib/pkgbasefuncs.inc.php +++ b/web/lib/pkgbasefuncs.inc.php @@ -964,6 +964,26 @@ function pkgbase_update_category($base_id, $category_id) { } /** + * Get a list of all package requests + * + * @return array List of pacakge requests with details + */ +function pkgbase_request_list() { + $dbh = DB::connect(); + + $q = "SELECT PackageRequests.ID, "; + $q.= "PackageRequests.PackageBaseID AS BaseID, "; + $q.= "PackageRequests.PackageBaseName AS Name, "; + $q.= "RequestTypes.Name AS Type, PackageRequests.Comments, "; + $q.= "Users.Username AS User, PackageRequests.RequestTS "; + $q.= "FROM PackageRequests INNER JOIN RequestTypes ON "; + $q.= "RequestTypes.ID = PackageRequests.ReqTypeID "; + $q.= "INNER JOIN Users ON Users.ID = PackageRequests.UsersID"; + + return $dbh->query($q)->fetchAll(); +} + +/** * File a deletion/orphan request against a package base * * @global string $AUR_LOCATION The AUR's URL used for notification e-mails diff --git a/web/lib/routing.inc.php b/web/lib/routing.inc.php index 1b2aa52..5836a13 100644 --- a/web/lib/routing.inc.php +++ b/web/lib/routing.inc.php @@ -5,6 +5,7 @@ $ROUTES = array( '/index.php' => 'home.php', '/packages' => 'packages.php', '/pkgbase' => 'pkgbase.php', + '/requests' => 'pkgreq.php', '/register' => 'account.php', '/account' => 'account.php', '/accounts' => 'account.php', diff --git a/web/template/header.php b/web/template/header.php index df83995..03ce536 100644 --- a/web/template/header.php +++ b/web/template/header.php @@ -57,6 +57,9 @@ <li><a href="<?= get_uri('/packages/'); ?>"><?= __("Packages"); ?></a></li> <?php if (isset($_COOKIE['AURSID'])): ?> <li><a href="<?= get_uri('/packages/'); ?>?SeB=m&K=<?= username_from_sid($_COOKIE["AURSID"]); ?>"><?= __("My Packages"); ?></a></li> + <?php if (check_user_privileges()): ?> + <li><a href="<?= get_uri('/requests/') ; ?>"><?= __("Requests"); ?></a></li> + <?php endif; ?> <li><a href="<?= get_uri('/submit/'); ?>"><?= __("Submit"); ?></a></li> <?php if (check_user_privileges()): ?> <li><a href="<?= get_uri('/accounts/') ; ?>"><?= __("Accounts"); ?></a></li> diff --git a/web/template/pkgreq_results.php b/web/template/pkgreq_results.php new file mode 100644 index 0000000..7cbdcc4 --- /dev/null +++ b/web/template/pkgreq_results.php @@ -0,0 +1,66 @@ +<div id="pkglist-results" class="box"> + <div class="pkglist-stats"> + <p><?= __('%d package requests found. Page %d of %d.', $total, $current, $pages) ?></p> + <?php if (count($templ_pages) > 1): ?> + <p class="pkglist-nav"> + <?php foreach ($templ_pages as $pagenr => $pagestart): ?> + <?php if ($pagestart === false): ?> + <span class="page"><?= $pagenr ?></span> + <?php elseif ($pagestart + 1 == $first): ?> + <span class="page"><?= $pagenr ?></span> + <?php else: ?> + <a class="page" href="<?= get_uri('/requests/'); ?>?<?= mkurl('O=' . $pagestart) ?>"><?= $pagenr ?></a> + <?php endif; ?> + <?php endforeach; ?> + </p> + <?php endif; ?> + </div> + + <table class="results"> + <thead> + <tr> + <th><?= __("Package") ?></th> + <th><?= __("Type") ?></th> + <th><?= __("Comments") ?></th> + <th><?= __("Filed by") ?></th> + <th><?= __("Date") ?></th> + </tr> + </thead> + <tbody> + + <?php while (list($indx, $row) = each($results)): ?> + <tr class="<?= ($indx % 2 == 0) ? 'odd' : 'even' ?>"> + <?php if ($row['BaseID']): ?> + <td><a href="<?= htmlspecialchars(get_pkgbase_uri($row["Name"]), ENT_QUOTES); ?>"><?= htmlspecialchars($row["Name"]) ?></a></td> + <?php else: ?> + <td><?= htmlspecialchars($row["Name"]) ?></td> + <?php endif; ?> + <td><?= htmlspecialchars(ucfirst($row['Type']), ENT_QUOTES); ?></td> + <td class="wrap"><?= htmlspecialchars($row['Comments'], ENT_QUOTES); ?></td> + <td> + <a href="<?= get_uri('/account/') . htmlspecialchars($row['User'], ENT_QUOTES) ?>" title="<?= __('View account information for %s', htmlspecialchars($row['User'])) ?>"><?= htmlspecialchars($row['User']) ?></a> + </td> + <td><?= gmdate("Y-m-d H:i", intval($row['RequestTS'])) ?></td> + </tr> + <?php endwhile; ?> + + </tbody> + </table> + + <div class="pkglist-stats"> + <p><?= __('%d package requests found. Page %d of %d.', $total, $current, $pages) ?></p> + <?php if (count($templ_pages) > 1): ?> + <p class="pkglist-nav"> + <?php foreach ($templ_pages as $pagenr => $pagestart): ?> + <?php if ($pagestart === false): ?> + <span class="page"><?= $pagenr ?></span> + <?php elseif ($pagestart + 1 == $first): ?> + <span class="page"><?= $pagenr ?></span> + <?php else: ?> + <a class="page" href="<?= get_uri('/requests/'); ?>?<?= mkurl('O=' . $pagestart) ?>"><?= $pagenr ?></a> + <?php endif; ?> + <?php endforeach; ?> + </p> + <?php endif; ?> + </div> +</div> -- 2.0.0
On 25.06.2014 11:44, Lukas Fleischer wrote:
Introduce a new navigation point "Requests" that shows a list of pending package requests. This functionality is only available to Trusted Users.
Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> --- web/html/pkgreq.php | 58 ++++++++++++++++++++++++++++++++++++ web/lib/pkgbasefuncs.inc.php | 20 +++++++++++++ web/lib/routing.inc.php | 1 + web/template/header.php | 3 ++ web/template/pkgreq_results.php | 66 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+) create mode 100644 web/template/pkgreq_results.php
diff --git a/web/html/pkgreq.php b/web/html/pkgreq.php index c8dd673..05eeb51 100644 --- a/web/html/pkgreq.php +++ b/web/html/pkgreq.php @@ -14,6 +14,62 @@ if (!check_user_privileges()) { header('Location: /'); exit(); } + +if (!isset($base_id)) { + $results = pkgbase_request_list(); + $total = count($results); + + /* Sanitize paging variables. */ + if (isset($_GET['O'])) {
I understand this is copied from pkg_search_page() in web/lib/pkgfuncs.inc.php, but now would be a good time to clean it up (in both places). Especially the usage of $_GET rather than a local variable should go away. Introduce something like input_get($field_name, $default = false); which would check if the value is set and if it is return it, otherwise return the default.
+ $_GET['O'] = intval($_GET['O']); + if ($_GET['O'] < 0) + $_GET['O'] = 0;
$value = max(intval($value), 0);
+ } else { + $_GET['O'] = 0; + } + + + if (isset($_GET["PP"])) { + $_GET["PP"] = intval($_GET["PP"]); + if ($_GET["PP"] < 50) + $_GET["PP"] = 50; + else if ($_GET["PP"] > 250) + $_GET["PP"] = 250;
# Source: http://at2.php.net/manual/en/function.min.php#81302 function bound($x, $min, $max) { return min(max($x, $min), $max); }
+ } else { + $_GET["PP"] = 50; + } + + /* Calculate the results to use. */ + $first = $_GET['O'] + 1; + + /* Calculation of pagination links. */ + $per_page = ($_GET['PP'] > 0) ? $_GET['PP'] : 50; + $current = ceil($first / $per_page); + $pages = ceil($total / $per_page); + $templ_pages = array(); + + if ($current > 1) { + $templ_pages['« ' . __('First')] = 0; + $templ_pages['‹ ' . __('Previous')] = ($current - 2) * $per_page; + } + + if ($current - 5 > 1) + $templ_pages["..."] = false; + + for ($i = max($current - 5, 1); $i <= min($pages, $current + 5); $i++) { + $templ_pages[$i] = ($i - 1) * $per_page; + } + + if ($current + 5 < $pages) + $templ_pages["... "] = false; + + if ($current < $pages) { + $templ_pages[__('Next') . ' ›'] = $current * $per_page; + $templ_pages[__('Last') . ' »'] = ($pages - 1) * $per_page; + } + + $SID = $_COOKIE['AURSID']; + include('pkgreq_results.php'); +} else { ?>
<div class="box"> @@ -51,5 +107,7 @@ if (!check_user_privileges()) { </div>
<?php +} + html_footer(AUR_VERSION);
diff --git a/web/lib/pkgbasefuncs.inc.php b/web/lib/pkgbasefuncs.inc.php index a9fe949..505bb51 100644 --- a/web/lib/pkgbasefuncs.inc.php +++ b/web/lib/pkgbasefuncs.inc.php @@ -964,6 +964,26 @@ function pkgbase_update_category($base_id, $category_id) { }
/** + * Get a list of all package requests + * + * @return array List of pacakge requests with details + */ +function pkgbase_request_list() { + $dbh = DB::connect(); + + $q = "SELECT PackageRequests.ID, "; + $q.= "PackageRequests.PackageBaseID AS BaseID, "; + $q.= "PackageRequests.PackageBaseName AS Name, "; + $q.= "RequestTypes.Name AS Type, PackageRequests.Comments, "; + $q.= "Users.Username AS User, PackageRequests.RequestTS "; + $q.= "FROM PackageRequests INNER JOIN RequestTypes ON "; + $q.= "RequestTypes.ID = PackageRequests.ReqTypeID "; + $q.= "INNER JOIN Users ON Users.ID = PackageRequests.UsersID"; + + return $dbh->query($q)->fetchAll(); +} + +/** * File a deletion/orphan request against a package base * * @global string $AUR_LOCATION The AUR's URL used for notification e-mails diff --git a/web/lib/routing.inc.php b/web/lib/routing.inc.php index 1b2aa52..5836a13 100644 --- a/web/lib/routing.inc.php +++ b/web/lib/routing.inc.php @@ -5,6 +5,7 @@ $ROUTES = array( '/index.php' => 'home.php', '/packages' => 'packages.php', '/pkgbase' => 'pkgbase.php', + '/requests' => 'pkgreq.php', '/register' => 'account.php', '/account' => 'account.php', '/accounts' => 'account.php', diff --git a/web/template/header.php b/web/template/header.php index df83995..03ce536 100644 --- a/web/template/header.php +++ b/web/template/header.php @@ -57,6 +57,9 @@ <li><a href="<?= get_uri('/packages/'); ?>"><?= __("Packages"); ?></a></li> <?php if (isset($_COOKIE['AURSID'])): ?> <li><a href="<?= get_uri('/packages/'); ?>?SeB=m&K=<?= username_from_sid($_COOKIE["AURSID"]); ?>"><?= __("My Packages"); ?></a></li> + <?php if (check_user_privileges()): ?> + <li><a href="<?= get_uri('/requests/') ; ?>"><?= __("Requests"); ?></a></li> + <?php endif; ?> <li><a href="<?= get_uri('/submit/'); ?>"><?= __("Submit"); ?></a></li> <?php if (check_user_privileges()): ?> <li><a href="<?= get_uri('/accounts/') ; ?>"><?= __("Accounts"); ?></a></li> diff --git a/web/template/pkgreq_results.php b/web/template/pkgreq_results.php new file mode 100644 index 0000000..7cbdcc4 --- /dev/null +++ b/web/template/pkgreq_results.php @@ -0,0 +1,66 @@ +<div id="pkglist-results" class="box"> + <div class="pkglist-stats"> + <p><?= __('%d package requests found. Page %d of %d.', $total, $current, $pages) ?></p> + <?php if (count($templ_pages) > 1): ?> + <p class="pkglist-nav"> + <?php foreach ($templ_pages as $pagenr => $pagestart): ?> + <?php if ($pagestart === false): ?> + <span class="page"><?= $pagenr ?></span> + <?php elseif ($pagestart + 1 == $first): ?> + <span class="page"><?= $pagenr ?></span> + <?php else: ?> + <a class="page" href="<?= get_uri('/requests/'); ?>?<?= mkurl('O=' . $pagestart) ?>"><?= $pagenr ?></a> + <?php endif; ?> + <?php endforeach; ?> + </p> + <?php endif; ?> + </div> + + <table class="results"> + <thead> + <tr> + <th><?= __("Package") ?></th> + <th><?= __("Type") ?></th> + <th><?= __("Comments") ?></th> + <th><?= __("Filed by") ?></th> + <th><?= __("Date") ?></th> + </tr> + </thead> + <tbody> + + <?php while (list($indx, $row) = each($results)): ?> + <tr class="<?= ($indx % 2 == 0) ? 'odd' : 'even' ?>"> + <?php if ($row['BaseID']): ?> + <td><a href="<?= htmlspecialchars(get_pkgbase_uri($row["Name"]), ENT_QUOTES); ?>"><?= htmlspecialchars($row["Name"]) ?></a></td> + <?php else: ?> + <td><?= htmlspecialchars($row["Name"]) ?></td> + <?php endif; ?> + <td><?= htmlspecialchars(ucfirst($row['Type']), ENT_QUOTES); ?></td> + <td class="wrap"><?= htmlspecialchars($row['Comments'], ENT_QUOTES); ?></td> + <td> + <a href="<?= get_uri('/account/') . htmlspecialchars($row['User'], ENT_QUOTES) ?>" title="<?= __('View account information for %s', htmlspecialchars($row['User'])) ?>"><?= htmlspecialchars($row['User']) ?></a> + </td> + <td><?= gmdate("Y-m-d H:i", intval($row['RequestTS'])) ?></td> + </tr> + <?php endwhile; ?> + + </tbody> + </table> + + <div class="pkglist-stats"> + <p><?= __('%d package requests found. Page %d of %d.', $total, $current, $pages) ?></p> + <?php if (count($templ_pages) > 1): ?> + <p class="pkglist-nav"> + <?php foreach ($templ_pages as $pagenr => $pagestart): ?> + <?php if ($pagestart === false): ?> + <span class="page"><?= $pagenr ?></span> + <?php elseif ($pagestart + 1 == $first): ?> + <span class="page"><?= $pagenr ?></span> + <?php else: ?> + <a class="page" href="<?= get_uri('/requests/'); ?>?<?= mkurl('O=' . $pagestart) ?>"><?= $pagenr ?></a> + <?php endif; ?> + <?php endforeach; ?> + </p> + <?php endif; ?> + </div> +</div>
On Tue, 01 Jul 2014 at 18:37:46, Florian Pritz wrote:
[...] I understand this is copied from pkg_search_page() in web/lib/pkgfuncs.inc.php, but now would be a good time to clean it up (in both places). Especially the usage of $_GET rather than a local variable should go away.
Introduce something like input_get($field_name, $default = false); which would check if the value is set and if it is return it, otherwise return the default.
I prepared several patches to improve GET parameter handling and permission handling but I am not going to merge them before the 3.2.0 release.
+ $_GET['O'] = intval($_GET['O']); + if ($_GET['O'] < 0) + $_GET['O'] = 0;
$value = max(intval($value), 0);
+ } else { + $_GET['O'] = 0; + } + + + if (isset($_GET["PP"])) { + $_GET["PP"] = intval($_GET["PP"]); + if ($_GET["PP"] < 50) + $_GET["PP"] = 50; + else if ($_GET["PP"] > 250) + $_GET["PP"] = 250;
# Source: http://at2.php.net/manual/en/function.min.php#81302 function bound($x, $min, $max) { return min(max($x, $min), $max); } [...]
Thanks, I will send a patch to simplify these two checks (the patch series has already been merged into master, so it is too late to amend).
This allows Trusted Users to close package requests via the request list. Also, entries are now sorted such that open requests are shown before closed requests. Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> --- UPGRADING | 1 + schema/aur-schema.sql | 1 + web/html/css/aur.css | 30 ++++++++++++++++-------------- web/html/pkgbase.php | 8 +++++++- web/lib/pkgbasefuncs.inc.php | 26 ++++++++++++++++++++++++-- web/lib/routing.inc.php | 6 ++++++ web/template/pkgreq_results.php | 18 ++++++++++++++++++ 7 files changed, 73 insertions(+), 17 deletions(-) diff --git a/UPGRADING b/UPGRADING index 455118e..ceee6f5 100644 --- a/UPGRADING +++ b/UPGRADING @@ -23,6 +23,7 @@ CREATE TABLE PackageRequests ( UsersID INTEGER UNSIGNED NULL DEFAULT NULL, Comments TEXT NOT NULL DEFAULT '', RequestTS BIGINT UNSIGNED NOT NULL DEFAULT 0, + Status TINYINT UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (ID), INDEX (UsersID), INDEX (PackageBaseID), diff --git a/schema/aur-schema.sql b/schema/aur-schema.sql index 88f9974..486beef 100644 --- a/schema/aur-schema.sql +++ b/schema/aur-schema.sql @@ -308,6 +308,7 @@ CREATE TABLE PackageRequests ( UsersID INTEGER UNSIGNED NULL DEFAULT NULL, Comments TEXT NOT NULL DEFAULT '', RequestTS BIGINT UNSIGNED NOT NULL DEFAULT 0, + Status TINYINT UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (ID), INDEX (UsersID), INDEX (PackageBaseID), diff --git a/web/html/css/aur.css b/web/html/css/aur.css index 78fd4ce..cbebb30 100644 --- a/web/html/css/aur.css +++ b/web/html/css/aur.css @@ -24,20 +24,6 @@ padding: 0; } -#actionlist .text-button { - color: #07b; - background: none; - border: none; - padding: 0; - cursor: pointer; - font-size: 100%; -} - -#actionlist .text-button:hover { - text-decoration: underline; - color: #666; -} - .arch-bio-entry ul { list-style: none; padding: 0; @@ -61,3 +47,19 @@ #pkg-updates td.pkg-date { text-align:right; } + +.text-button { + background: transparent; + border: none !important; + margin: 0 !important; + padding: 0 !important; + font: normal 100% sans-serif; + text-decoration: none; + color: #07b; + cursor: pointer; +} + +.text-button:hover { + text-decoration: underline; + color: #666; +} diff --git a/web/html/pkgbase.php b/web/html/pkgbase.php index dd09977..9047f5b 100644 --- a/web/html/pkgbase.php +++ b/web/html/pkgbase.php @@ -96,6 +96,8 @@ if (check_token()) { list($ret, $output) = pkgbase_change_category($base_id, $atype); } elseif (current_action("do_FileRequest")) { list($ret, $output) = pkgbase_file_request($ids, $_POST['type'], $_POST['comments']); + } elseif (current_action("do_CloseRequest")) { + list($ret, $output) = pkgbase_close_request($_POST['reqid']); } if (isset($_REQUEST['comment'])) { @@ -105,7 +107,11 @@ if (check_token()) { } if ($ret) { - if (isset($base_id)) { + if (current_action("do_CloseRequest")) { + /* Redirect back to package request page on success. */ + header('Location: ' . get_pkgreq_route()); + exit(); + } if (isset($base_id)) { /* Redirect back to package base page on success. */ header('Location: ' . get_pkgbase_uri($pkgbase_name)); exit(); diff --git a/web/lib/pkgbasefuncs.inc.php b/web/lib/pkgbasefuncs.inc.php index 505bb51..a039f83 100644 --- a/web/lib/pkgbasefuncs.inc.php +++ b/web/lib/pkgbasefuncs.inc.php @@ -975,10 +975,12 @@ function pkgbase_request_list() { $q.= "PackageRequests.PackageBaseID AS BaseID, "; $q.= "PackageRequests.PackageBaseName AS Name, "; $q.= "RequestTypes.Name AS Type, PackageRequests.Comments, "; - $q.= "Users.Username AS User, PackageRequests.RequestTS "; + $q.= "Users.Username AS User, PackageRequests.RequestTS, "; + $q.= "PackageRequests.Status "; $q.= "FROM PackageRequests INNER JOIN RequestTypes ON "; $q.= "RequestTypes.ID = PackageRequests.ReqTypeID "; - $q.= "INNER JOIN Users ON Users.ID = PackageRequests.UsersID"; + $q.= "INNER JOIN Users ON Users.ID = PackageRequests.UsersID "; + $q.= "ORDER BY Status ASC, RequestTS DESC"; return $dbh->query($q)->fetchAll(); } @@ -1070,3 +1072,23 @@ function pkgbase_file_request($ids, $type, $comments) { return array(true, __("Added request successfully.")); } + +/** + * Close a deletion/orphan request + * + * @param int $id The package request to close + * + * @return void + */ +function pkgbase_close_request($id) { + $dbh = DB::connect(); + + if (!check_user_privileges()) { + return array(false, __("Only TUs and developers can close requests.")); + } + + $q = "UPDATE PackageRequests SET Status = 1 WHERE ID = " . intval($id); + $dbh->exec($q); + + return array(true, __("Request closed successfully.")); +} diff --git a/web/lib/routing.inc.php b/web/lib/routing.inc.php index 5836a13..2fa3e1f 100644 --- a/web/lib/routing.inc.php +++ b/web/lib/routing.inc.php @@ -21,6 +21,7 @@ $ROUTES = array( $PKG_PATH = '/packages'; $PKGBASE_PATH = '/pkgbase'; +$PKGREQ_PATH = '/requests'; $USER_PATH = '/account'; function get_route($path) { @@ -55,6 +56,11 @@ function get_pkgbase_route() { return $PKGBASE_PATH; } +function get_pkgreq_route() { + global $PKGREQ_PATH; + return $PKGREQ_PATH; +} + function get_pkg_uri($pkgname) { global $USE_VIRTUAL_URLS; global $PKG_PATH; diff --git a/web/template/pkgreq_results.php b/web/template/pkgreq_results.php index 7cbdcc4..33195c7 100644 --- a/web/template/pkgreq_results.php +++ b/web/template/pkgreq_results.php @@ -24,6 +24,7 @@ <th><?= __("Comments") ?></th> <th><?= __("Filed by") ?></th> <th><?= __("Date") ?></th> + <th><?= __("Status") ?></th> </tr> </thead> <tbody> @@ -41,6 +42,23 @@ <a href="<?= get_uri('/account/') . htmlspecialchars($row['User'], ENT_QUOTES) ?>" title="<?= __('View account information for %s', htmlspecialchars($row['User'])) ?>"><?= htmlspecialchars($row['User']) ?></a> </td> <td><?= gmdate("Y-m-d H:i", intval($row['RequestTS'])) ?></td> + <?php if ($row['Status'] == 0): ?> + <td> + <form action="<?= get_uri('/pkgbase/'); ?>" method="post"> + <fieldset> + <input type="hidden" name="IDs[<?= $row['BaseID'] ?>]" value="1" /> + <input type="hidden" name="ID" value="<?= $row['BaseID'] ?>" /> + <input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" /> + <input type="hidden" name="reqid" value="<?= $row['ID'] ?>" /> + <div> + <input type="submit" class="button text-button" name="do_CloseRequest" value="<?= __("Close") ?>" /> + </div> + </fieldset> + </form> + </td> + <?php else: ?> + <td><?= __("Closed") ?></td> + <?php endif; ?> </tr> <?php endwhile; ?> -- 2.0.0
On 25.06.2014 11:44, Lukas Fleischer wrote:
This allows Trusted Users to close package requests via the request list. Also, entries are now sorted such that open requests are shown before closed requests.
Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> --- UPGRADING | 1 + schema/aur-schema.sql | 1 + web/html/css/aur.css | 30 ++++++++++++++++-------------- web/html/pkgbase.php | 8 +++++++- web/lib/pkgbasefuncs.inc.php | 26 ++++++++++++++++++++++++-- web/lib/routing.inc.php | 6 ++++++ web/template/pkgreq_results.php | 18 ++++++++++++++++++ 7 files changed, 73 insertions(+), 17 deletions(-)
[...]
diff --git a/web/lib/pkgbasefuncs.inc.php b/web/lib/pkgbasefuncs.inc.php index 505bb51..a039f83 100644 --- a/web/lib/pkgbasefuncs.inc.php +++ b/web/lib/pkgbasefuncs.inc.php @@ -1070,3 +1072,23 @@ function pkgbase_file_request($ids, $type, $comments) {
return array(true, __("Added request successfully.")); } + +/** + * Close a deletion/orphan request + * + * @param int $id The package request to close + * + * @return void
You return an array, not void.
+ */ +function pkgbase_close_request($id) { + $dbh = DB::connect(); + + if (!check_user_privileges()) { + return array(false, __("Only TUs and developers can close requests.")); + } + + $q = "UPDATE PackageRequests SET Status = 1 WHERE ID = " . intval($id); + $dbh->exec($q); + + return array(true, __("Request closed successfully.")); +}
On Tue, 01 Jul 2014 at 18:42:09, Florian Pritz wrote:
[...]
+ +/** + * Close a deletion/orphan request + * + * @param int $id The package request to close + * + * @return void
You return an array, not void.
Will send a patch to fix the documentation, thanks.
+ */ +function pkgbase_close_request($id) { + $dbh = DB::connect(); + + if (!check_user_privileges()) { + return array(false, __("Only TUs and developers can close requests.")); + } + + $q = "UPDATE PackageRequests SET Status = 1 WHERE ID = " . intval($id); + $dbh->exec($q); + + return array(true, __("Request closed successfully.")); +}
Automatically highlight package requests after a configurable period of time. Defaults to 14 days. Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> --- web/lib/config.inc.php.proto | 3 +++ web/template/pkgreq_results.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/web/lib/config.inc.php.proto b/web/lib/config.inc.php.proto index 10ed07e..a9137f1 100644 --- a/web/lib/config.inc.php.proto +++ b/web/lib/config.inc.php.proto @@ -62,3 +62,6 @@ $MAX_RPC_RESULTS = 5000; # Mailing list to send package request notifications to. $AUR_REQUEST_ML = "aur-general@archlinux.org"; + +# Time to wait until a package request is due. +$REQUEST_IDLE_TIME = 60 * 60 * 24 * 14; diff --git a/web/template/pkgreq_results.php b/web/template/pkgreq_results.php index 33195c7..213f180 100644 --- a/web/template/pkgreq_results.php +++ b/web/template/pkgreq_results.php @@ -41,7 +41,7 @@ <td> <a href="<?= get_uri('/account/') . htmlspecialchars($row['User'], ENT_QUOTES) ?>" title="<?= __('View account information for %s', htmlspecialchars($row['User'])) ?>"><?= htmlspecialchars($row['User']) ?></a> </td> - <td><?= gmdate("Y-m-d H:i", intval($row['RequestTS'])) ?></td> + <td<?php if (time() - intval($row['RequestTS']) > $REQUEST_IDLE_TIME): ?> class="flagged"<?php endif; ?>><?= gmdate("Y-m-d H:i", intval($row['RequestTS'])) ?></td> <?php if ($row['Status'] == 0): ?> <td> <form action="<?= get_uri('/pkgbase/'); ?>" method="post"> -- 2.0.0
This button allows for accepting a request, disowning the affected package or redirecting to the package deletion page. The request is closed automatically when the action has been performed. Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> --- web/html/pkgbase.php | 10 ++++++---- web/html/pkgdel.php | 3 +++ web/lib/pkgbasefuncs.inc.php | 14 ++++++++++++-- web/template/pkgreq_results.php | 11 +++++++++++ 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/web/html/pkgbase.php b/web/html/pkgbase.php index 9047f5b..da88210 100644 --- a/web/html/pkgbase.php +++ b/web/html/pkgbase.php @@ -59,23 +59,25 @@ if (check_token()) { } elseif (current_action("do_UnFlag")) { list($ret, $output) = pkgbase_unflag($atype, $ids); } elseif (current_action("do_Adopt")) { - list($ret, $output) = pkgbase_adopt($atype, $ids, true); + list($ret, $output) = pkgbase_adopt($atype, $ids, true, NULL); } elseif (current_action("do_Disown")) { - list($ret, $output) = pkgbase_adopt($atype, $ids, false); + $via = isset($_POST['via']) ? $_POST['via'] : NULL; + list($ret, $output) = pkgbase_adopt($atype, $ids, false, $via); } elseif (current_action("do_Vote")) { list($ret, $output) = pkgbase_vote($atype, $ids, true); } elseif (current_action("do_UnVote")) { list($ret, $output) = pkgbase_vote($atype, $ids, false); } elseif (current_action("do_Delete")) { if (isset($_POST['confirm_Delete'])) { + $via = isset($_POST['via']) ? $_POST['via'] : NULL; if (!isset($_POST['merge_Into']) || empty($_POST['merge_Into'])) { - list($ret, $output) = pkgbase_delete($atype, $ids, NULL); + list($ret, $output) = pkgbase_delete($atype, $ids, NULL, $via); unset($_GET['ID']); } else { $merge_base_id = pkgbase_from_name($_POST['merge_Into']); if ($merge_base_id) { - list($ret, $output) = pkgbase_delete($atype, $ids, $merge_base_id); + list($ret, $output) = pkgbase_delete($atype, $ids, $merge_base_id, $via); unset($_GET['ID']); } else { diff --git a/web/html/pkgdel.php b/web/html/pkgdel.php index 39fe81a..621c3c9 100644 --- a/web/html/pkgdel.php +++ b/web/html/pkgdel.php @@ -37,6 +37,9 @@ if ($atype == "Trusted User" || $atype == "Developer"): ?> <input type="hidden" name="IDs[<?= $base_id ?>]" value="1" /> <input type="hidden" name="ID" value="<?= $base_id ?>" /> <input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" /> + <?php if (isset($_GET['via'])): ?> + <input type="hidden" name="via" value="<?= intval($_GET['via']) ?>" /> + <?php endif; ?> <p><input type="checkbox" name="confirm_Delete" value="1" /> <?= __("Confirm package deletion") ?></p> <p><input type="submit" class="button" name="do_Delete" value="<?= __("Delete") ?>" /></p> diff --git a/web/lib/pkgbasefuncs.inc.php b/web/lib/pkgbasefuncs.inc.php index a039f83..2444674 100644 --- a/web/lib/pkgbasefuncs.inc.php +++ b/web/lib/pkgbasefuncs.inc.php @@ -438,10 +438,11 @@ function pkgbase_unflag($atype, $base_ids) { * @param string $atype Account type, output of account_from_sid * @param array $base_ids Array of package base IDs to delete * @param int $merge_base_id Package base to merge the deleted ones into + * @param int $via Package request to close upon deletion * * @return array Tuple of success/failure indicator and error message */ -function pkgbase_delete ($atype, $base_ids, $merge_base_id) { +function pkgbase_delete ($atype, $base_ids, $merge_base_id, $via) { if (!$atype) { return array(false, __("You must be logged in before you can delete packages.")); } @@ -537,6 +538,10 @@ function pkgbase_delete ($atype, $base_ids, $merge_base_id) { $q = "DELETE FROM PackageBases WHERE ID IN (" . implode(",", $base_ids) . ")"; $dbh->exec($q); + if ($via) { + pkgbase_close_request(intval($via)); + } + return array(true, __("The selected packages have been deleted.")); } @@ -546,10 +551,11 @@ function pkgbase_delete ($atype, $base_ids, $merge_base_id) { * @param string $atype Account type, output of account_from_sid * @param array $base_ids Array of package base IDs to adopt/disown * @param bool $action Adopts if true, disowns if false. Adopts by default + * @param int $via Package request to close upon adoption * * @return array Tuple of success/failure indicator and error message */ -function pkgbase_adopt ($atype, $base_ids, $action=true) { +function pkgbase_adopt ($atype, $base_ids, $action=true, $via) { if (!$atype) { if ($action) { return array(false, __("You must be logged in before you can adopt packages.")); @@ -590,6 +596,10 @@ function pkgbase_adopt ($atype, $base_ids, $action=true) { $dbh->exec($q); + if ($via) { + pkgbase_close_request(intval($via)); + } + if ($action) { pkgbase_notify(account_from_sid($_COOKIE["AURSID"]), $base_ids); return array(true, __("The selected packages have been adopted.")); diff --git a/web/template/pkgreq_results.php b/web/template/pkgreq_results.php index 213f180..8ab8351 100644 --- a/web/template/pkgreq_results.php +++ b/web/template/pkgreq_results.php @@ -44,6 +44,17 @@ <td<?php if (time() - intval($row['RequestTS']) > $REQUEST_IDLE_TIME): ?> class="flagged"<?php endif; ?>><?= gmdate("Y-m-d H:i", intval($row['RequestTS'])) ?></td> <?php if ($row['Status'] == 0): ?> <td> + <?php if ($row['BaseID']): ?> + <?php if ($row['Type'] == 'deletion'): ?> + <a href="<?= get_pkgbase_uri($row['Name']) ?>delete/?via=<?= intval($row['ID']) ?>"><?= __('Accept') ?></a> + <?php elseif ($row['Type'] == 'orphan'): ?> + <form action="<?= get_pkgbase_uri($row['Name']) . 'disown/'; ?>" method="post"> + <input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" /> + <input type="hidden" name="via" value="<?= intval($row['ID']) ?>" /> + <input type="submit" class="button text-button" name="do_Disown" value="<?= __('Accept') ?>" /> + </form> + <?php endif; ?> + <?php endif; ?> <form action="<?= get_uri('/pkgbase/'); ?>" method="post"> <fieldset> <input type="hidden" name="IDs[<?= $row['BaseID'] ?>]" value="1" /> -- 2.0.0
This adds a new "Merge" category to the list of available request types and also adds a new "Merge into" field that is hidden via JavaScript when "Deletion" or "Orphan" is selected. Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> --- UPGRADING | 2 ++ schema/aur-schema.sql | 2 ++ web/html/pkgbase.php | 2 +- web/html/pkgmerge.php | 5 ++++- web/html/pkgreq.php | 21 ++++++++++++++++++++- web/lib/pkgbasefuncs.inc.php | 11 +++++++---- web/template/pkgreq_results.php | 6 ++++++ 7 files changed, 42 insertions(+), 7 deletions(-) diff --git a/UPGRADING b/UPGRADING index ceee6f5..0e8edf0 100644 --- a/UPGRADING +++ b/UPGRADING @@ -14,12 +14,14 @@ CREATE TABLE RequestTypes ( ) ENGINE = InnoDB; INSERT INTO RequestTypes VALUES (1, 'deletion'); INSERT INTO RequestTypes VALUES (2, 'orphan'); +INSERT INTO RequestTypes VALUES (3, 'merge'); CREATE TABLE PackageRequests ( ID BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, ReqTypeID TINYINT UNSIGNED NOT NULL, PackageBaseID INTEGER UNSIGNED NULL, PackageBaseName VARCHAR(255) NOT NULL, + MergeBaseName VARCHAR(255) NULL, UsersID INTEGER UNSIGNED NULL DEFAULT NULL, Comments TEXT NOT NULL DEFAULT '', RequestTS BIGINT UNSIGNED NOT NULL DEFAULT 0, diff --git a/schema/aur-schema.sql b/schema/aur-schema.sql index 486beef..1ec7385 100644 --- a/schema/aur-schema.sql +++ b/schema/aur-schema.sql @@ -297,6 +297,7 @@ CREATE TABLE RequestTypes ( ) ENGINE = InnoDB; INSERT INTO RequestTypes VALUES (1, 'deletion'); INSERT INTO RequestTypes VALUES (2, 'orphan'); +INSERT INTO RequestTypes VALUES (3, 'merge'); -- Package requests -- @@ -305,6 +306,7 @@ CREATE TABLE PackageRequests ( ReqTypeID TINYINT UNSIGNED NOT NULL, PackageBaseID INTEGER UNSIGNED NULL, PackageBaseName VARCHAR(255) NOT NULL, + MergeBaseName VARCHAR(255) NULL, UsersID INTEGER UNSIGNED NULL DEFAULT NULL, Comments TEXT NOT NULL DEFAULT '', RequestTS BIGINT UNSIGNED NOT NULL DEFAULT 0, diff --git a/web/html/pkgbase.php b/web/html/pkgbase.php index da88210..0b0f6ef 100644 --- a/web/html/pkgbase.php +++ b/web/html/pkgbase.php @@ -97,7 +97,7 @@ if (check_token()) { } elseif (current_action("do_ChangeCategory")) { list($ret, $output) = pkgbase_change_category($base_id, $atype); } elseif (current_action("do_FileRequest")) { - list($ret, $output) = pkgbase_file_request($ids, $_POST['type'], $_POST['comments']); + list($ret, $output) = pkgbase_file_request($ids, $_POST['type'], $_POST['merge_into'], $_POST['comments']); } elseif (current_action("do_CloseRequest")) { list($ret, $output) = pkgbase_close_request($_POST['reqid']); } diff --git a/web/html/pkgmerge.php b/web/html/pkgmerge.php index dbc5eac..ba3f742 100644 --- a/web/html/pkgmerge.php +++ b/web/html/pkgmerge.php @@ -39,8 +39,11 @@ if ($atype == "Trusted User" || $atype == "Developer"): ?> <input type="hidden" name="IDs[<?= $base_id ?>]" value="1" /> <input type="hidden" name="ID" value="<?= $base_id ?>" /> <input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" /> + <?php if (isset($_GET['via'])): ?> + <input type="hidden" name="via" value="<?= intval($_GET['via']) ?>" /> + <?php endif; ?> <p><label for="merge_Into" ><?= __("Merge into:") ?></label> - <input type="text" id="merge_Into" name="merge_Into" /></p> + <input type="text" id="merge_Into" name="merge_Into" value="<?= isset($_GET['into']) ? $_GET['into'] : '' ?>" /></p> <p><input type="checkbox" name="confirm_Delete" value="1" /> <?= __("Confirm package merge") ?></p> <p><input type="submit" class="button" name="do_Delete" value="<?= __("Merge") ?>" /></p> diff --git a/web/html/pkgreq.php b/web/html/pkgreq.php index 05eeb51..2b46b02 100644 --- a/web/html/pkgreq.php +++ b/web/html/pkgreq.php @@ -90,11 +90,30 @@ if (!isset($base_id)) { <input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" /> <p> <label for="id_type"><?= __("Request type") ?>:</label> - <select name="type" id="id_type"> + <select name="type" id="id_type" onchange="showHideMergeSection()"> <option value="deletion"><?= __('Deletion') ?></option> + <option value="merge"><?= __('Merge') ?></option> <option value="orphan"><?= __('Orphan') ?></option> </select> </p> + <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> + <script type="text/javascript"> + function showHideMergeSection() { + if ($('#id_type').val() == 'merge') { + $('#merge_section').show(); + } else { + $('#merge_section').hide(); + } + } + + $(document).ready(function() { + showHideMergeSection(); + }); + </script> + <p id="merge_section"> + <label for="id_merge_into"><?= __("Merge into") ?>:</label> + <input type="text" name="merge_into" id="id_merge_into" /> + </p> <p> <label for="id_comments"><?= __("Comments") ?>:</label> <textarea name="comments" id="id_comments" rows="5" cols="50"></textarea> diff --git a/web/lib/pkgbasefuncs.inc.php b/web/lib/pkgbasefuncs.inc.php index 2444674..68dd656 100644 --- a/web/lib/pkgbasefuncs.inc.php +++ b/web/lib/pkgbasefuncs.inc.php @@ -984,6 +984,7 @@ function pkgbase_request_list() { $q = "SELECT PackageRequests.ID, "; $q.= "PackageRequests.PackageBaseID AS BaseID, "; $q.= "PackageRequests.PackageBaseName AS Name, "; + $q.= "PackageRequests.MergeBaseName AS MergeInto, "; $q.= "RequestTypes.Name AS Type, PackageRequests.Comments, "; $q.= "Users.Username AS User, PackageRequests.RequestTS, "; $q.= "PackageRequests.Status "; @@ -1002,11 +1003,12 @@ function pkgbase_request_list() { * @global string $AUR_REQUEST_ML The request notification mailing list * @param string $ids The package base IDs to file the request against * @param string $type The type of the request + * @param string $merge_into The target of a merge operation * @param string $comments The comments to be added to the request * * @return void */ -function pkgbase_file_request($ids, $type, $comments) { +function pkgbase_file_request($ids, $type, $merge_into, $comments) { global $AUR_LOCATION; global $AUR_REQUEST_ML; @@ -1030,10 +1032,11 @@ function pkgbase_file_request($ids, $type, $comments) { } $q = "INSERT INTO PackageRequests "; - $q.= "(ReqTypeID, PackageBaseID, PackageBaseName, UsersID, "; - $q.= "Comments, RequestTS) VALUES (" . $type_id . ", "; + $q.= "(ReqTypeID, PackageBaseID, PackageBaseName, MergeBaseName, "; + $q.= "UsersID, Comments, RequestTS) VALUES (" . $type_id . ", "; $q.= intval($base_id) . ", " . $dbh->quote($pkgbase_name) . ", "; - $q.= $uid . ", " . $dbh->quote($comments) . ", UNIX_TIMESTAMP())"; + $q.= $dbh->quote($merge_into) . ", " . $uid . ", "; + $q.= $dbh->quote($comments) . ", UNIX_TIMESTAMP())"; $dbh->exec($q); /* diff --git a/web/template/pkgreq_results.php b/web/template/pkgreq_results.php index 8ab8351..042cc3a 100644 --- a/web/template/pkgreq_results.php +++ b/web/template/pkgreq_results.php @@ -36,7 +36,11 @@ <?php else: ?> <td><?= htmlspecialchars($row["Name"]) ?></td> <?php endif; ?> + <?php if ($row['Type'] == 'merge'): ?> + <td><?= htmlspecialchars(ucfirst($row['Type']), ENT_QUOTES); ?> (<?= htmlspecialchars(ucfirst($row['MergeInto']), ENT_QUOTES); ?>)</td> + <?php else: ?> <td><?= htmlspecialchars(ucfirst($row['Type']), ENT_QUOTES); ?></td> + <?php endif; ?> <td class="wrap"><?= htmlspecialchars($row['Comments'], ENT_QUOTES); ?></td> <td> <a href="<?= get_uri('/account/') . htmlspecialchars($row['User'], ENT_QUOTES) ?>" title="<?= __('View account information for %s', htmlspecialchars($row['User'])) ?>"><?= htmlspecialchars($row['User']) ?></a> @@ -47,6 +51,8 @@ <?php if ($row['BaseID']): ?> <?php if ($row['Type'] == 'deletion'): ?> <a href="<?= get_pkgbase_uri($row['Name']) ?>delete/?via=<?= intval($row['ID']) ?>"><?= __('Accept') ?></a> + <?php elseif ($row['Type'] == 'merge'): ?> + <a href="<?= get_pkgbase_uri($row['Name']) ?>merge/?into=<?= urlencode($row['MergeInto']) ?>&via=<?= intval($row['ID']) ?>"><?= __('Accept') ?></a> <?php elseif ($row['Type'] == 'orphan'): ?> <form action="<?= get_pkgbase_uri($row['Name']) . 'disown/'; ?>" method="post"> <input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" /> -- 2.0.0
On 25.06.2014 11:44, Lukas Fleischer wrote:
Add a new entry to the package actions box that allows for filing deletion and orphan requests. When choosing that action, the user is redirected to a new page that allows for selecting a request type and entering a comment. When submitting the request, a new entry in the request database is created and an email is sent to a configurable mailing list (defaults to aur-general).
Signed-off-by: Lukas Fleischer <archlinux@cryptocrack.de> --- UPGRADING | 31 ++++++++++++++ schema/aur-schema.sql | 28 +++++++++++++ web/html/index.php | 3 ++ web/html/pkgbase.php | 2 + web/html/pkgreq.php | 55 +++++++++++++++++++++++++ web/lib/config.inc.php.proto | 3 ++ web/lib/pkgbasefuncs.inc.php | 88 ++++++++++++++++++++++++++++++++++++++++ web/template/pkg_details.php | 1 + web/template/pkgbase_details.php | 1 + 9 files changed, 212 insertions(+) create mode 100644 web/html/pkgreq.php
[..]
diff --git a/web/lib/pkgbasefuncs.inc.php b/web/lib/pkgbasefuncs.inc.php index 9f80ef2..a9fe949 100644 --- a/web/lib/pkgbasefuncs.inc.php +++ b/web/lib/pkgbasefuncs.inc.php @@ -962,3 +962,91 @@ function pkgbase_update_category($base_id, $category_id) { $category_id, $base_id); $dbh->exec($q); } + +/** + * File a deletion/orphan request against a package base + * + * @global string $AUR_LOCATION The AUR's URL used for notification e-mails + * @global string $AUR_REQUEST_ML The request notification mailing list + * @param string $ids The package base IDs to file the request against + * @param string $type The type of the request + * @param string $comments The comments to be added to the request + * + * @return void + */ +function pkgbase_file_request($ids, $type, $comments) { + global $AUR_LOCATION; + global $AUR_REQUEST_ML; + + if (empty($comments)) { + return array(false, __("The comment field must not be empty.")); + } + + $dbh = DB::connect(); + $uid = uid_from_sid($_COOKIE["AURSID"]); + + /* TODO: Allow for filing multiple requests at once. */ + $base_id = $ids[0]; + $pkgbase_name = pkgbase_name_from_id($base_id); + + $q = "SELECT ID FROM RequestTypes WHERE Name = " . $dbh->quote($type); + $result = $dbh->query($q); + if ($row = $result->fetch(PDO::FETCH_ASSOC)) { + $type_id = $row['ID']; + } else { + return array(false, __("Invalid request type.")); + } + + $q = "INSERT INTO PackageRequests "; + $q.= "(ReqTypeID, PackageBaseID, PackageBaseName, UsersID, "; + $q.= "Comments, RequestTS) VALUES (" . $type_id . ", "; + $q.= intval($base_id) . ", " . $dbh->quote($pkgbase_name) . ", "; + $q.= $uid . ", " . $dbh->quote($comments) . ", UNIX_TIMESTAMP())"; + $dbh->exec($q); + + /* + * Send e-mail notifications. + * TODO: Move notification logic to separate function where it belongs. + */ + $q = "SELECT Users.Email "; + $q.= "FROM Users INNER JOIN PackageBases "; + $q.= "ON PackageBases.MaintainerUID = Users.ID "; + $q.= "WHERE PackageBases.ID = " . intval($base_id); + $result = $dbh->query($q); + if ($row = $result->fetch(PDO::FETCH_ASSOC)) { + $bcc = $row['Email']; + } else { + unset($bcc); + } + + $q = "SELECT Name FROM PackageBases WHERE ID = "; + $q.= intval($base_id); + $result = $dbh->query($q); + $row = $result->fetch(PDO::FETCH_ASSOC); + + /* + * TODO: Add native language emails for users, based on their + * preferences. Simply making these strings translatable won't + * work, users would be getting emails in the language that the + * user who posted the comment was in. + */ + $username = username_from_sid($_COOKIE['AURSID']); + $body = + $username . " [1] filed a " . $type . " request for " . + $row['Name'] . " [2]:\n\n" . $comments . "\n\n" . + "[1] " . $AUR_LOCATION . get_user_uri($username) . "\n" . + "[2] " . $AUR_LOCATION . get_pkgbase_uri($row['Name']) . "\n"; + $body = wordwrap($body, 70); + $headers = "MIME-Version: 1.0\r\n" . + "Content-type: text/plain; charset=UTF-8\r\n"; + if (!empty($bcc)) { + $headers .= "Bcc: $bcc\r\n"; + } + $headers .= "Reply-to: noreply@aur.archlinux.org\r\n" . + "From: notify@aur.archlinux.org\r\n" . + "X-Mailer: AUR";
Can you set a References header here so accept requests generated via the webui will be able to thread properly? Something like "References: <request-$request_id@aur.archlinux.org>".
+ @mail($AUR_REQUEST_ML, "AUR " . ucfirst($type) . " Request for " . + $row['Name'], $body, $headers); + + return array(true, __("Added request successfully.")); +}
On Tue, 01 Jul 2014 at 18:50:33, Florian Pritz wrote:
[...]
+ /* + * TODO: Add native language emails for users, based on their + * preferences. Simply making these strings translatable won't + * work, users would be getting emails in the language that the + * user who posted the comment was in. + */ + $username = username_from_sid($_COOKIE['AURSID']); + $body = + $username . " [1] filed a " . $type . " request for " . + $row['Name'] . " [2]:\n\n" . $comments . "\n\n" . + "[1] " . $AUR_LOCATION . get_user_uri($username) . "\n" . + "[2] " . $AUR_LOCATION . get_pkgbase_uri($row['Name']) . "\n"; + $body = wordwrap($body, 70); + $headers = "MIME-Version: 1.0\r\n" . + "Content-type: text/plain; charset=UTF-8\r\n"; + if (!empty($bcc)) { + $headers .= "Bcc: $bcc\r\n"; + } + $headers .= "Reply-to: noreply@aur.archlinux.org\r\n" . + "From: notify@aur.archlinux.org\r\n" . + "X-Mailer: AUR";
Can you set a References header here so accept requests generated via the webui will be able to thread properly? Something like "References: <request-$request_id@aur.archlinux.org>".
See commit 0e84667 (Add threading headers to request notification mails, 2014-06-25) in master.
+ @mail($AUR_REQUEST_ML, "AUR " . ucfirst($type) . " Request for " . + $row['Name'], $body, $headers); + + return array(true, __("Added request successfully.")); +}
participants (2)
-
Florian Pritz
-
Lukas Fleischer