diff mbox

[v2] Add page for seeing all of a user's comments

Message ID 20180717123126.18552-1-johannes@kyriasis.com
State Superseded, archived
Headers show

Commit Message

Johannes Löthberg July 17, 2018, 12:31 p.m. UTC
Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
---
v2: Actually add the new template, d'oh.

 web/html/account.php               |  69 +++++++++++++++-
 web/html/css/aurweb.css            |  17 ++++
 web/html/index.php                 |   2 +
 web/html/pkgbase.php               |   7 +-
 web/lib/acctfuncs.inc.php          |  41 ++++++++++
 web/lib/credentials.inc.php        |   2 +
 web/template/account_comments.php  | 125 +++++++++++++++++++++++++++++
 web/template/account_edit_form.php |   1 +
 8 files changed, 261 insertions(+), 3 deletions(-)
 create mode 100644 web/template/account_comments.php

Comments

Lukas Fleischer July 22, 2018, 8:15 a.m. UTC | #1
On Tue, 17 Jul 2018 at 14:31:26, Johannes Löthberg wrote:
> Signed-off-by: Johannes Löthberg <johannes@kyriasis.com>
> ---
> v2: Actually add the new template, d'oh.
> 
>  web/html/account.php               |  69 +++++++++++++++-
>  web/html/css/aurweb.css            |  17 ++++
>  web/html/index.php                 |   2 +
>  web/html/pkgbase.php               |   7 +-
>  web/lib/acctfuncs.inc.php          |  41 ++++++++++
>  web/lib/credentials.inc.php        |   2 +
>  web/template/account_comments.php  | 125 +++++++++++++++++++++++++++++
>  web/template/account_edit_form.php |   1 +
>  8 files changed, 261 insertions(+), 3 deletions(-)
>  create mode 100644 web/template/account_comments.php
> [...]

Thanks a lot for implementing this!

There is a lot of code duplication going on, though. Is there any reason
we cannot use a shared template for the package comments and the user
comments pages? It seems like one only needs to choose a different
result set?

Best regards,
Lukas
diff mbox

Patch

diff --git a/web/html/account.php b/web/html/account.php
index c30a89a..955aa4d 100644
--- a/web/html/account.php
+++ b/web/html/account.php
@@ -8,7 +8,7 @@  include_once('acctfuncs.inc.php');   # access Account specific functions
 $action = in_request("Action");
 
 $need_userinfo = array(
-	"DisplayAccount", "DeleteAccount", "AccountInfo", "UpdateAccount"
+	"DisplayAccount", "DeleteAccount", "AccountInfo", "UpdateAccount", "ListComments"
 );
 
 if (in_array($action, $need_userinfo)) {
@@ -54,6 +54,8 @@  if ($action == "UpdateAccount") {
 
 if ($action == "AccountInfo") {
 	html_header(__('Account') . ' ' . $row['Username']);
+} elseif ($action == "ListComments") {
+	html_header(__('Comments for') . ' ' . $row['Username']);
 } else {
 	html_header(__('Accounts'));
 }
@@ -61,7 +63,11 @@  if ($action == "AccountInfo") {
 # Main page processing here
 #
 echo "<div class=\"box\">\n";
-echo "  <h2>".__("Accounts")."</h2>\n";
+if ($action == "ListComments") {
+	echo "  <h2>".__("Comments for").' '.$row['Username']."</h2>\n";
+} else {
+	echo "  <h2>".__("Accounts")."</h2>\n";
+}
 
 if (isset($_COOKIE["AURSID"])) {
 	if ($action == "SearchAccounts") {
@@ -166,6 +172,65 @@  if (isset($_COOKIE["AURSID"])) {
 				$row["Username"]);
 		}
 
+	} elseif ($action == "ListComments") {
+		if (has_credential(CRED_ACCOUNT_LIST_COMMENTS)) {
+			# display the comment list if they're a TU/dev
+			#
+
+			/* Sanitize paging variables. */
+			if (isset($_GET["O"])) {
+				$_GET["O"] = max(intval($_GET["O"]), 0);
+			} else {
+				$_GET["O"] = 0;
+			}
+
+			if (isset($_GET["PP"])) {
+				$_GET["PP"] = bound(intval($_GET["PP"]), 5, 250);
+			} else {
+				$_GET["PP"] = 10;
+			}
+
+			$total = account_comments_count($row["ID"]);
+
+			/* 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['&laquo; ' . __('First')] = 0;
+				$templ_pages['&lsaquo; ' . __('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') . ' &rsaquo;'] = $current * $per_page;
+				$templ_pages[__('Last') . ' &raquo;'] = ($pages - 1) * $per_page;
+			}
+
+			$username = $row["Username"];
+			$userid = $row["ID"];
+			$comments = account_comments($row["ID"], $_GET["PP"], $_GET["O"]);
+
+			include('account_comments.php');
+
+		} else {
+			print __("You are not allowed to access this area.");
+		}
+
 	} else {
 		if (has_credential(CRED_ACCOUNT_SEARCH)) {
 			# display the search page if they're a TU/dev
diff --git a/web/html/css/aurweb.css b/web/html/css/aurweb.css
index f5e1037..ce54a28 100644
--- a/web/html/css/aurweb.css
+++ b/web/html/css/aurweb.css
@@ -148,3 +148,20 @@  label.confirmation,
 	color: red;
 	font-weight: bold;
 }
+
+.commentlist-nav .page {
+	margin: 0 .25em;
+}
+
+#commentlist-results .commentlist-nav {
+	float: right;
+	margin-top: -2.2em;
+}
+
+.commentlist-nav .prev {
+	margin-right: 1em;
+}
+
+.commentlist-nav .next {
+	margin-right: 1em;
+}
diff --git a/web/html/index.php b/web/html/index.php
index 2c53cdd..b2cd840 100644
--- a/web/html/index.php
+++ b/web/html/index.php
@@ -142,6 +142,8 @@  if (!empty($tokens[1]) && '/' . $tokens[1] == get_pkg_route()) {
 				$_REQUEST['Action'] = "UpdateAccount";
 			} elseif ($tokens[3] == 'delete') {
 				$_REQUEST['Action'] = "DeleteAccount";
+			} elseif ($tokens[3] == 'comments') {
+				$_REQUEST['Action'] = "ListComments";
 			} else {
 				header("HTTP/1.0 404 Not Found");
 				include "./404.php";
diff --git a/web/html/pkgbase.php b/web/html/pkgbase.php
index cf9a6c6..8a0c363 100644
--- a/web/html/pkgbase.php
+++ b/web/html/pkgbase.php
@@ -43,6 +43,7 @@  if (isset($_POST['IDs'])) {
 
 /* Perform package base actions. */
 $via = isset($_POST['via']) ? $_POST['via'] : NULL;
+$return_to = isset($_POST['return_to']) ? $_POST['return_to'] : NULL;
 $ret = false;
 $output = "";
 $fragment = "";
@@ -133,7 +134,11 @@  if (check_token()) {
 			/* Redirect back to package request page on success. */
 			header('Location: ' . get_pkgreq_route());
 			exit();
-		} if (isset($base_id)) {
+		} elseif ((current_action("do_DeleteComment") ||
+		           current_action("do_UndeleteComment")) && $return_to) {
+			header('Location: ' . $return_to);
+			exit();
+		} elseif (isset($base_id)) {
 			/* Redirect back to package base page on success. */
 			header('Location: ' . get_pkgbase_uri($pkgbase_name) . $fragment);
 			exit();
diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php
index df57375..9536139 100644
--- a/web/lib/acctfuncs.inc.php
+++ b/web/lib/acctfuncs.inc.php
@@ -1403,3 +1403,44 @@  function accept_terms($uid, $termrev) {
 		$dbh->exec($q);
 	}
 }
+
+function account_comments($uid, $limit, $offset=0) {
+	$dbh = DB::connect();
+	$q = "SELECT PackageComments.ID, Comments, ";
+	$q.= "PackageBaseId, CommentTS, DelTS, EditedTS, B.UserName AS EditUserName, ";
+	$q.= "C.UserName as DelUserName, RenderedComment, ";
+	$q.= "PB.ID as PackageBaseID, PB.Name as PackageBaseName ";
+	$q.= "FROM PackageComments ";
+	$q.= "LEFT JOIN PackageBases PB ON PackageComments.PackageBaseID = PB.ID ";
+	$q.= "LEFT JOIN Users A ON PackageComments.UsersID = A.ID ";
+	$q.= "LEFT JOIN Users B ON PackageComments.EditedUsersID = B.ID ";
+	$q.= "LEFT JOIN Users C ON PackageComments.DelUsersID = C.ID ";
+	$q.= "WHERE A.ID = " . $dbh->quote($uid) . " ";
+	$q.= "ORDER BY CommentTS DESC";
+
+	if ($limit > 0) {
+		$q.=" LIMIT " . $limit;
+	}
+
+	if ($offset > 0) {
+		$q.=" OFFSET " . $offset;
+	}
+
+	$result = $dbh->query($q);
+	if (!$result) {
+		return null;
+	}
+
+	return $result->fetchAll();
+}
+
+function account_comments_count($uid) {
+	$dbh = DB::connect();
+	$q = "SELECT COUNT(*) ";
+	$q.= "FROM PackageComments ";
+	$q.= "LEFT JOIN Users A ON PackageComments.UsersID = A.ID ";
+	$q.= "WHERE A.ID = " . $dbh->quote($uid);
+
+	$result = $dbh->query($q);
+	return $result->fetch(PDO::FETCH_NUM)[0];
+}
diff --git a/web/lib/credentials.inc.php b/web/lib/credentials.inc.php
index d8698a8..5d90cfc 100644
--- a/web/lib/credentials.inc.php
+++ b/web/lib/credentials.inc.php
@@ -5,6 +5,7 @@  define("CRED_ACCOUNT_EDIT", 2);
 define("CRED_ACCOUNT_EDIT_DEV", 3);
 define("CRED_ACCOUNT_LAST_LOGIN", 4);
 define("CRED_ACCOUNT_SEARCH", 5);
+define("CRED_ACCOUNT_LIST_COMMENTS", 28);
 define("CRED_COMMENT_DELETE", 6);
 define("CRED_COMMENT_UNDELETE", 27);
 define("CRED_COMMENT_VIEW_DELETED", 22);
@@ -59,6 +60,7 @@  function has_credential($credential, $approved_users=array()) {
 	case CRED_ACCOUNT_EDIT:
 	case CRED_ACCOUNT_LAST_LOGIN:
 	case CRED_ACCOUNT_SEARCH:
+	case CRED_ACCOUNT_LIST_COMMENTS:
 	case CRED_COMMENT_DELETE:
 	case CRED_COMMENT_UNDELETE:
 	case CRED_COMMENT_VIEW_DELETED:
diff --git a/web/template/account_comments.php b/web/template/account_comments.php
new file mode 100644
index 0000000..aedcc55
--- /dev/null
+++ b/web/template/account_comments.php
@@ -0,0 +1,125 @@ 
+<div id="commentlist-results">
+<?php if (count($templ_pages) > 1): ?>
+<p class="commentlist-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('/account/' . $username . '/comments/'); ?>?<?= mkurl('O=' . $pagestart) ?>"><?= $pagenr ?></a>
+		<?php endif; ?>
+	<?php endforeach; ?>
+</p>
+<?php endif; ?>
+</div>
+
+<?php while (list($indx, $row) = each($comments)): ?>
+	<?php
+	$date_fmtd = date('Y-m-d H:i', $row['CommentTS']);
+	$pkg_uri = '<a href=' . htmlspecialchars(get_pkg_uri($row['PackageBaseName']), ENT_QUOTES) . '>' . htmlspecialchars($row['PackageBaseName']) . '</a></td>';
+	$heading = __('Commented on package %s on %s', $pkg_uri, $date_fmtd);
+
+	$is_deleted = $row['DelTS'];
+	$is_edited = $row['EditedTS'];
+
+	if ($userid && $is_deleted) {
+		$date_fmtd = date('Y-m-d H:i', $row['DelTS']);
+		$heading .= ' <span class="edited">(';
+		if ($row['DelUserName']) {
+			$user_fmtd = html_format_username($row['DelUserName']);
+			$heading .= __('deleted on %s by %s', $date_fmtd, $user_fmtd);
+		} else {
+			$heading .= __('deleted on %s', $date_fmtd);
+		}
+		$heading .= ')</span>';
+	} elseif ($userid && $is_edited) {
+		$date_fmtd = date('Y-m-d H:i', $row['EditedTS']);
+		$heading .= ' <span class="edited">(';
+		if ($row['EditUserName']) {
+			$user_fmtd = html_format_username($row['EditUserName']);
+			$heading .= __('edited on %s by %s', $date_fmtd, $user_fmtd);
+		} else {
+			$heading .= __('edited on %s', $date_fmtd);
+		}
+		$heading .= ')</span>';
+	}
+	?>
+	<h4 id="<?= isset($pinned) ? "pinned-" : "comment-" ?><?= $row['ID'] ?>"<?php if ($is_deleted): ?> class="comment-deleted"<?php endif; ?>>
+		<?= $heading ?>
+		<?php if ($is_deleted && has_credential(CRED_COMMENT_UNDELETE)): ?>
+			<form class="undelete-comment-form" method="post" action="<?= htmlspecialchars(get_pkgbase_uri($row['PackageBaseName']), ENT_QUOTES); ?>">
+				<fieldset style="display:inline;">
+					<input type="hidden" name="action" value="do_UndeleteComment" />
+					<input type="hidden" name="comment_id" value="<?= $row['ID'] ?>" />
+					<input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" />
+					<input type="hidden" name="return_to" value="<?= htmlspecialchars($_SERVER["REQUEST_URI"], ENT_QUOTES) ?>" />
+					<input type="image" class="undelete-comment" src="/images/action-undo.min.svg" width="11" height="11" alt="<?= __('Undelete comment') ?>" title="<?= __('Undelete comment') ?>" name="submit" value="1" />
+				</fieldset>
+			</form>
+		<?php endif;?>
+
+		<?php if (!$is_deleted && can_delete_comment_array(array('UsersID' => $userid))): ?>
+			<form class="delete-comment-form" method="post" action="<?= htmlspecialchars(get_pkgbase_uri($row['PackageBaseName']), ENT_QUOTES); ?>">
+				<fieldset style="display:inline;">
+					<input type="hidden" name="action" value="do_DeleteComment" />
+					<input type="hidden" name="comment_id" value="<?= $row['ID'] ?>" />
+					<input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" />
+					<input type="hidden" name="return_to" value="<?= htmlspecialchars($_SERVER["REQUEST_URI"], ENT_QUOTES) ?>" />
+					<input type="image" class="delete-comment" src="/images/x.min.svg" width="11" height="11" alt="<?= __('Delete comment') ?>" title="<?= __('Delete comment') ?>" name="submit" value="1" />
+				</fieldset>
+			</form>
+		<?php endif; ?>
+
+		<?php if (!$is_deleted && can_edit_comment_array(array('UsersID' => $userid))): ?>
+		<a href="<?= htmlspecialchars(get_pkgbase_uri($row['PackageBaseName']) . 'edit-comment/?comment_id=' . $row['ID'], ENT_QUOTES) ?>" class="edit-comment" title="<?= __('Edit comment') ?>"><img src="/images/pencil.min.svg" alt="<?= __('Edit comment') ?>" width="11" height="11"></a>
+		<?php endif; ?>
+	</h4>
+
+	<div id="<?= isset($pinned) ? "pinned-" : "comment-" ?><?= $row['ID'] ?>-content" class="article-content<?php if ($is_deleted): ?> comment-deleted<?php endif; ?>">
+		<div>
+			<?php if (!empty($row['RenderedComment'])): ?>
+			<?= $row['RenderedComment'] ?>
+			<?php else: ?>
+			<p>
+				<?= parse_comment($row['Comments']) ?>
+			</p>
+			<?php endif; ?>
+		</div>
+	</div>
+<?php endwhile; ?>
+<script>
+$(document).ready(function() {
+	$('.edit-comment').click(function () {
+		var parent_element = this.parentElement,
+			parent_id = parent_element.id,
+			comment_id = parent_id.substr(parent_id.indexOf('-') + 1),
+			edit_form = $(parent_element).next(),
+			_this = $(this);
+		add_busy_indicator(_this);
+		$.getJSON('<?= get_uri('/rpc') ?>', {
+			type: 'get-comment-form',
+			arg: comment_id,
+			base_id: <?= intval($row["PackageBaseID"]) ?>,
+			base_name: <?= json_encode($row['PackageBaseName']) ?>
+		}, function (data) {
+			remove_busy_indicator(_this);
+			if (data.success) {
+				edit_form.html(data.form);
+				edit_form.find('textarea').focus();
+			} else {
+				alert(data.error);
+			}
+		});
+		return false;
+	});
+
+	function add_busy_indicator(sibling) {
+		sibling.after('<img src="/images/ajax-loader.gif" class="ajax-loader" width="16" height="11" alt="Busy…" />');
+	}
+
+	function remove_busy_indicator(sibling) {
+		sibling.next().remove();
+	}
+});
+</script>
diff --git a/web/template/account_edit_form.php b/web/template/account_edit_form.php
index 6eff81b..38d5274 100644
--- a/web/template/account_edit_form.php
+++ b/web/template/account_edit_form.php
@@ -2,6 +2,7 @@ 
 <p>
 	<?= __('Click %shere%s if you want to permanently delete this account.', '<a href="' . get_user_uri($N) . 'delete/' . '">', '</a>') ?>
 	<?= __('Click %shere%s for user details.', '<a href="' . get_user_uri($N) . '">', '</a>') ?>
+	<?= __('Click %shere%s to list the comments made by this account.', '<a href="' . get_user_uri($N) . 'comments/' . '">', '</a>') ?>
 </p>
 
 <form id="edit-profile-form" action="<?= get_user_uri($N) . 'update/'; ?>" method="post">