Commit 887196f2 authored by Aaron Wells's avatar Aaron Wells Committed by Gerrit Code Review
Browse files

Merge "Fix sorting threaded comments. Bug 1499122"

parents 199f94d3 289b680f
......@@ -25,6 +25,7 @@
<FIELD NAME="requestpublic" TYPE="char" LENGTH="50" NOTNULL="false" />
<FIELD NAME="rating" TYPE="int" LENGTH="10" NOTNULL="false" />
<FIELD NAME="lastcontentupdate" TYPE="datetime" NOTNULL="false" />
<FIELD NAME="threadedposition" TYPE="int" LENGTH="4" NOTNULL="false" />
</FIELDS>
<KEYS>
<KEY NAME="artefactpk" TYPE="primary" FIELDS="artefact" />
......@@ -34,6 +35,9 @@
<KEY NAME="deletedbyfk" TYPE="foreign" FIELDS="deletedby" REFTABLE="artefact_comment_deletedby" REFFIELDS="name" />
<KEY NAME="requestpublicfk" TYPE="foreign" FIELDS="requestpublic" REFTABLE="artefact_comment_deletedby" REFFIELDS="name" />
</KEYS>
<INDEXES>
<INDEX NAME="threadedpositionix" UNIQUE="false" FIELDS="threadedposition"/>
</INDEXES>
</TABLE>
</TABLES>
</XMLDB>
......@@ -44,5 +44,94 @@ function xmldb_artefact_comment_upgrade($oldversion=0) {
set_config_plugin('artefact', 'comment', 'maxindent', 5);
}
if ($oldversion < 2015100100) {
// Add new column '' to table artefact_comment_comment used for diplaying comments by threads
$table = new XMLDBTable('artefact_comment_comment');
$field = new XMLDBField('threadedposition');
$field->setAttributes(XMLDB_TYPE_INTEGER, 4, null, null);
add_field($table, $field);
$index = new XMLDBIndex('threadedpositionix');
$index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('threadedposition'));
add_index($table, $index);
// Update the threaded position for all exising comments
// We assume there is no child comment in the database before this release
// Comments on views
$commented_views = get_column_sql('
SELECT DISTINCT onview
FROM {artefact_comment_comment}
WHERE onview IS NOT NULL
ORDER BY onview
');
if ($commented_views) {
$total = count($commented_views);
$limit = 5000;
$done = 0;
foreach ($commented_views as $v) {
$comments = get_record_sql('
SELECT artefact
FROM {artefact_comment_comment}
WHERE onview = ?
ORDER BY artefact
', $v->onview);
$p = 1;
foreach ($comments as $c) {
update_record('artefact_comment_comment',
(object) array (
'threadedposition' => $p
),
array (
'artefact' => $c->artefact
)
);
$p++;
}
$done++;
if (($done % $limit) == 0 || $done >= $total) {
log_debug("Updating comments on views: $done/$total");
set_time_limit(30);
}
}
}
// Comments on artefact
$commented_views = get_column_sql('
SELECT DISTINCT onartefact
FROM {artefact_comment_comment}
WHERE onartefact IS NOT NULL
ORDER BY onartefact
');
if ($commented_views) {
$total = count($commented_views);
$limit = 5000;
$done = 0;
foreach ($commented_views as $v) {
$comments = get_record_sql('
SELECT artefact
FROM {artefact_comment_comment}
WHERE onartefact = ?
ORDER BY artefact
', $v->onartefact);
$p = 1;
foreach ($comments as $c) {
update_record('artefact_comment_comment',
(object) array (
'threadedposition' => $p
),
array (
'artefact' => $c->artefact
)
);
$p++;
}
$done++;
if (($done % $limit) == 0 || $done >= $total) {
log_debug("Updating comments on artefacts: $done/$total");
set_time_limit(30);
}
}
}
}
return $success;
}
......@@ -180,6 +180,7 @@ class ArtefactTypeComment extends ArtefactType {
protected $requestpublic;
protected $rating;
protected $lastcontentupdate;
protected $threadedposition;
public function __construct($id = 0, $data = null) {
parent::__construct($id, $data);
......@@ -233,6 +234,7 @@ class ArtefactTypeComment extends ArtefactType {
'deletedby' => $this->get('deletedby'),
'requestpublic' => $this->get('requestpublic'),
'rating' => $this->get('rating'),
'threadedposition' => $this->get('threadedposition'),
);
if ($this->get('lastcontentupdate')) {
$data->lastcontentupdate = db_format_timestamp($this->get('lastcontentupdate'));
......@@ -433,21 +435,7 @@ class ArtefactTypeComment extends ArtefactType {
$orderby = 'a.ctime ' . ($sort == 'latest' ? 'DESC' : 'ASC');
}
else {
if ($sort != 'latest') {
// Threaded ascending
$orderby = 'a.path ASC, a.ctime ASC, a.id';
}
else {
// Threaded & descending. Sort "root comments" by descending order, and the
// comments below them in ascending order. (This is the only sane way to do it.)
if (is_mysql()) {
$splitfunc = 'SUBSTRING_INDEX';
}
else {
$splitfunc = 'SPLIT_PART';
}
$orderby = "{$splitfunc}(a.path, '/', 2) DESC, a.path ASC, a.ctime ASC, a.id";
}
$orderby = 'c.threadedposition ' . ($sort == 'latest' ? 'DESC' : 'ASC');
}
// If pagination is in use, see if we want to get a page with particular comment
......@@ -1438,12 +1426,14 @@ function add_feedback_form_submit(Pieform $form, $values) {
$data->owner = $artefact->get('owner');
$data->group = $artefact->get('group');
$data->institution = $artefact->get('institution');
$onvieworartefactstr = "onartefact = $data->onartefact";
}
else {
$data->onview = $view->get('id');
$data->owner = $view->get('owner');
$data->group = $view->get('group');
$data->institution = $view->get('institution');
$onvieworartefactstr = "onview = $data->onview";
}
$owner = $data->owner;
......@@ -1478,8 +1468,48 @@ function add_feedback_form_submit(Pieform $form, $values) {
$data->rating = valid_rating($values['rating']);
}
if ($values['replyto']) {
$data->parent = $values['replyto'];
if ($values['replyto']
&& ($pcomment = artefact_instance_from_id($values['replyto']))) {
$data->parent = $pcomment->get('id');
$grandparentid = $pcomment->get('parent');
// Find the position for the new comment
// Find the last offspring of the parent
$parentid = $data->parent;
$data->threadedposition = $pcomment->get('threadedposition');
while ($lastchild = get_records_sql_array('
SELECT c.artefact, c.threadedposition
FROM {artefact_comment_comment} c
INNER JOIN {artefact} a ON a.id = c.artefact
WHERE
' . $onvieworartefactstr . '
AND a.parent = ?
ORDER BY c.threadedposition DESC
LIMIT 1'
, array($parentid)
)) {
$parentid = $lastchild[0]->artefact;
$data->threadedposition = $lastchild[0]->threadedposition;
}
$data->threadedposition++;
// Increase the threaded position of following comments by 1
execute_sql('
UPDATE {artefact_comment_comment}
SET threadedposition = threadedposition + 1
WHERE
' . $onvieworartefactstr . '
AND threadedposition >= ?'
, array($data->threadedposition)
);
}
if (!isset($data->threadedposition)) {
$lastcomment = get_record_sql('
SELECT max(threadedposition) AS lastposition
FROM {artefact_comment_comment} c
WHERE
' . $onvieworartefactstr
);
$data->threadedposition = $lastcomment->lastposition ? $lastcomment->lastposition + 1 : 1;
}
$comment = new ArtefactTypeComment(0, $data);
......
......@@ -12,5 +12,5 @@
defined('INTERNAL') || die();
$config = new StdClass;
$config->version = 2015081000;
$config->version = 2015100100;
$config->release = '1.0.0';
......@@ -4227,5 +4227,12 @@ function xmldb_core_upgrade($oldversion=0) {
}
}
if ($oldversion < 2015100200) {
log_debug('Upgrade comment plugin for threaded comments');
if ($data = check_upgrades('artefact.comment')) {
upgrade_plugin($data);
}
}
return $status;
}
......@@ -16,7 +16,7 @@ $config = new stdClass();
// See https://wiki.mahara.org/index.php/Developer_Area/Version_Numbering_Policy
// For upgrades on stable branches, increment the version by one. On master, use the date.
$config->version = 2015093000;
$config->version = 2015100200;
$config->series = '16.04';
$config->release = '16.04dev';
$config->minupgradefrom = 2009022600;
......
@javascript @core @core_artefact @core_content @artefact_comment
Feature: Threaded comments
In order to see earliest/latest threaded comments to a page
As a mahara user I should see threaded comments in the right order
So I can easily follow these comments/feedbacks
Background:
Given the following "institutions" exist:
| name | displayname | commentthreaded | allowinstitutionpublicviews |
| instone | inst1 | 1 | 1 |
Given the following "users" exist:
| username | password | email | firstname | lastname | institution | authname | role |
| pageowner | password | test01@example.com | Paige | Owner | instone | internal | admin |
Given the following "pages" exist:
| title | description | ownertype | ownername |
| page1 | page1 | user | pageowner |
Scenario: Threaded comments should be displayed in correct order
Given I log in as "pageowner" with password "password"
And I go to portfolio page "page1"
# Add 11 comments
And I fill in "Comment #1" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I fill in "Comment #2" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I fill in "Comment #3" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I fill in "Comment #4" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I fill in "Comment #5" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I fill in "Comment #6" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I fill in "Comment #7" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I fill in "Comment #8" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I fill in "Comment #9" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I fill in "Comment #10" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I fill in "Comment #11" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I fill in "Comment #12" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
# Go to the first page
And I follow "1"
And I should see "Comment #1"
And I should see "Comment #10"
And "Comment #2" "text" should appear before "Comment #3" "text"
And I should not see "Comment #11"
# Go to the second page
And I follow "2"
And I should see "Comment #11"
And "Comment #11" "text" should appear before "Comment #12" "text"
And I should not see "Comment #10"
# Reply to a comment
And I follow "1"
And I click on "Reply" in "Comment #1" row
And I fill in "Comment #1/1" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And "Comment #1/1" "text" should appear before "Comment #2" "text"
And I click on "Reply" in "Comment #1/1" row
And I fill in "Comment #1/1/1" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I click on "Reply" in "Comment #1/1" row
And I fill in "Comment #1/1/2" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I click on "Reply" in "Comment #1/1/1" row
And I fill in "Comment #1/1/1/1" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I click on "Reply" in "Comment #1/1/1/1" row
And I fill in "Comment #1/1/1/1/1" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I click on "Reply" in "Comment #1/1/1/1" row
And I fill in "Comment #1/1/1/1/2" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I click on "Reply" in "Comment #1/1" row
And I fill in "Comment #1/1/3" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And I click on "Reply" in "Comment #1/1/2" row
And I fill in "Comment #1/1/2/1" in WYSIWYG editor "add_feedback_form_message_ifr"
And I press "Comment"
And "Comment #1/1/1/1/1" "text" should appear before "Comment #1/1/1/1/2" "text"
And "Comment #1/1/1/1/2" "text" should appear before "Comment #1/1/2" "text"
And "Comment #1/1/2/1" "text" should appear before "Comment #1/1/3" "text"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment