Skip to content

Commit 514de5d

Browse files
committed
Issues-227
1 parent 748b3d7 commit 514de5d

File tree

9 files changed

+403
-100
lines changed

9 files changed

+403
-100
lines changed

config/vanilla/bootstrap.before.php

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -417,13 +417,7 @@ function updateRolePermissions($roleType, $roles) {
417417
*/
418418
function sortsDropDown($baseUrl, array $filters = [], $extraClasses = '', $default = null, $defaultUrl = null, $label = 'Sort') {
419419
$links = [];
420-
$active = paramPreference(
421-
'sort',
422-
'CategorySort',
423-
null,
424-
null,
425-
false
426-
);
420+
$active = Gdn::session()->getPreference('CategorySort', null);
427421
// Translate filters into links.
428422
foreach ($filters as $filter) {
429423
// Make sure we have the bare minimum: a label and a URL parameter.
@@ -486,8 +480,7 @@ function categorySorts($extraClasses = '') {
486480
return;
487481
}
488482

489-
$baseUrl = Gdn::request()->getFullPath();
490-
483+
$baseUrl = preg_replace('/\?.*/', '', Gdn::request()->getFullPath());
491484
$transientKey = Gdn::session()->transientKey();
492485
$filters = [
493486
[
@@ -505,11 +498,7 @@ function categorySorts($extraClasses = '') {
505498
]
506499
];
507500

508-
$defaultParams = ['TransientKey' => $transientKey];
509-
if (Gdn::request()->get('sort')) {
510-
$defaultParams['sort'] = Gdn::request()->get('sort');
511-
}
512-
501+
$defaultParams = [];
513502
if (!empty($defaultParams)) {
514503
$defaultUrl = $baseUrl.'?'.http_build_query($defaultParams);
515504
} else {
@@ -539,9 +528,8 @@ function discussionSorts($extraClasses = '') {
539528
return;
540529
}
541530

542-
$baseUrl = Gdn::request()->getFullPath();
531+
$baseUrl = preg_replace('/\?.*/', '', Gdn::request()->getFullPath());
543532
$transientKey = Gdn::session()->transientKey();
544-
545533
$filters = [
546534
[
547535
'name' => t('New'),
@@ -558,11 +546,7 @@ function discussionSorts($extraClasses = '') {
558546
];
559547

560548

561-
$defaultParams = ['save' => 1, 'TransientKey' => $transientKey];
562-
if (Gdn::request()->get('sort')) {
563-
$defaultParams['sort'] = '';
564-
}
565-
549+
$defaultParams = [];
566550
if (!empty($defaultParams)) {
567551
$defaultUrl = $baseUrl.'?'.http_build_query($defaultParams);
568552
} else {
@@ -595,7 +579,7 @@ function discussionFilters($extraClasses = '') {
595579
return;
596580
}
597581

598-
$baseUrl = Gdn::request()->getFullPath();
582+
$baseUrl = preg_replace('/\?.*/', '', Gdn::request()->getFullPath());
599583
$transientKey = Gdn::session()->transientKey();
600584
$filters = [
601585
[
@@ -612,11 +596,7 @@ function discussionFilters($extraClasses = '') {
612596
]
613597
];
614598

615-
$defaultParams = ['save' => 1, 'TransientKey' => $transientKey];
616-
if (Gdn::request()->get('followed')) {
617-
$defaultParams['followed'] = '';
618-
}
619-
599+
$defaultParams = [];
620600
if (!empty($defaultParams)) {
621601
$defaultUrl = $baseUrl.'?'.http_build_query($defaultParams);
622602
} else {
@@ -650,7 +630,7 @@ function categoryFilters($extraClasses = '') {
650630
return;
651631
}
652632

653-
$baseUrl = Gdn::request()->getFullPath();
633+
$baseUrl = preg_replace('/\?.*/', '', Gdn::request()->getFullPath());
654634
$transientKey = Gdn::session()->transientKey();
655635
$filters = [
656636
[
@@ -668,11 +648,7 @@ function categoryFilters($extraClasses = '') {
668648
]
669649
];
670650

671-
$defaultParams = ['save' => 1, 'TransientKey' => $transientKey];
672-
if (Gdn::request()->get('followed')) {
673-
$defaultParams['followed'] = '';
674-
}
675-
651+
$defaultParams = [];
676652
if (!empty($defaultParams)) {
677653
$defaultUrl = $baseUrl.'?'.http_build_query($defaultParams);
678654
} else {
@@ -714,13 +690,7 @@ function filtersDropDown($baseUrl, array $filters = [], $extraClasses = '', $def
714690

715691
if (c('Vanilla.EnableCategoryFollowing')) {
716692
$links = [];
717-
$active = paramPreference(
718-
'followed',
719-
'FollowedCategories',
720-
'Vanilla.SaveFollowingPreference',
721-
null,
722-
false
723-
);
693+
$active = Gdn::session()->getPreference('FollowedCategories', null);
724694

725695
// Translate filters into links.
726696
foreach ($filters as $filter) {

config/vanilla/bootstrap.early.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,81 @@
6060
// Delete the records with UserID=0 (Guests) from UserRole table
6161
// FIX: https://github.com/topcoder-platform/forums/issues/108
6262
Gdn::sql()->delete('UserRole',['UserID' => 0]);
63+
64+
// FIX: https://github.com/topcoder-platform/forums/issues/227
65+
// Sorting discussions by last date.
66+
// The last date can be any of InsertedDate(discussion), UpdatedDate(discussion), InsertedDate(comment) or UpdatedDate(comment).
67+
// The new columns will be added to keep the last date and who made changes.
68+
// By default Vanilla uses only DateInserted in calculated columns.
69+
// Moreover, the calculated columns (LastCommentID, LastDiscussionID and others) are used in calculations/aggregations.
70+
// Don't modified default Vanilla calculated columns.
71+
if(!Gdn::structure()->table('Discussion')->columnExists('LastDiscussionCommentsDate')) {
72+
Gdn::structure()->table('Discussion')
73+
->column('LastDiscussionCommentsDate', 'datetime', true, ['index', 'index.CategoryPages'])
74+
->column('LastDiscussionCommentsUserID', 'int', true)
75+
->set(false, false);
76+
// Step 1. Calculate the last date for discussions.
77+
$query = "UPDATE GDN_Discussion p
78+
SET p.LastDiscussionCommentsDate = (SELECT greatest(COALESCE(MAX(c.DateInserted), 0), COALESCE(MAX(c.DateUpdated), 0), COALESCE(p.DateUpdated, 0), COALESCE(p.DateInserted,0))
79+
FROM GDN_Comment c WHERE p.DiscussionID = c.DiscussionID)";
80+
Gdn::sql()->query($query);
81+
82+
// Step 2. Update discussions with comments.
83+
$query = "UPDATE GDN_Discussion p
84+
SET p.LastDiscussionCommentsUserID = (
85+
SELECT CASE
86+
WHEN COALESCE(p.DateUpdated,p.DateInserted) > COALESCE(c.DateUpdated,c.DateInserted) THEN
87+
COALESCE(p.UpdateUserID, p.InsertUserID)
88+
ELSE COALESCE(c.UpdateUserID,c.InsertUserID) END AS LastUserID FROM GDN_Comment c
89+
WHERE c.DiscussionID = p.DiscussionID ORDER BY c.DateUpdated DESC,c.DateInserted DESC LIMIT 1)";
90+
Gdn::sql()->query($query);
91+
92+
// Step 3. Update discussions without comments.
93+
$query ="UPDATE GDN_Discussion p
94+
SET p.LastDiscussionCommentsUserID = COALESCE(p.UpdateUserID,p.InsertUserID)
95+
WHERE p.LastDiscussionCommentsUserID IS NULL";
96+
Gdn::sql()->query($query);
97+
}
98+
99+
// Sorting categories by the last date
100+
// https://github.com/topcoder-platform/forums/issues/227
101+
if(!Gdn::structure()->table('Category')->columnExists('LastDiscussionCommentsUserID')) {
102+
Gdn::structure()->table('Category')
103+
->column('LastDiscussionCommentsUserID', 'int', true)
104+
->column('LastDiscussionCommentsDiscussionID', 'int', true)
105+
->column('LastDiscussionCommentsDate', 'datetime', true)
106+
->set(false, false);
107+
108+
// Step1. Update categories with type 'discussions':
109+
$query = "UPDATE GDN_Category c
110+
SET c.LastDiscussionCommentsDate = (SELECT MAX(d.LastDiscussionCommentsDate)FROM GDN_Discussion d WHERE d.CategoryID = c.CategoryID),
111+
c.LastDiscussionCommentsUserID = (SELECT d.LastDiscussionCommentsUserID FROM GDN_Discussion d
112+
WHERE d.CategoryID = c.CategoryID ORDER BY d.LastDiscussionCommentsDate DESC limit 1),
113+
c.LastDiscussionCommentsDiscussionID = (SELECT d.DiscussionID FROM GDN_Discussion d
114+
WHERE d.CategoryID = c.CategoryID ORDER BY d.LastDiscussionCommentsDate DESC limit 1)";
115+
Gdn::sql()->query($query);
116+
117+
118+
// Step2. Update all ancestor categories.
119+
// The MAX category depth is 4 for challenges
120+
$ancestorQuery = "UPDATE GDN_Category pc, (
121+
SELECT c1.ParentCategoryID AS ParentCategoryID, c1.LastDiscussionCommentsDate, c1.LastDiscussionCommentsUserID, c1.LastDiscussionCommentsDiscussionID
122+
FROM GDN_Category c1 inner join (SELECT c.ParentCategoryID, MAX(c.LastDiscussionCommentsDate) AS LastDiscussionCommentsDate FROM GDN_Category c
123+
GROUP BY c.ParentCategoryID) c2 on c1.ParentCategoryID = c2.ParentCategoryID AND c1.LastDiscussionCommentsDate = c2.LastDiscussionCommentsDate) c3
124+
SET pc.LastDiscussionCommentsDiscussionID = c3.LastDiscussionCommentsDiscussionID, pc.LastDiscussionCommentsUserID = c3.LastDiscussionCommentsUserID,
125+
pc.LastDiscussionCommentsDate = c3.LastDiscussionCommentsDate
126+
WHERE pc.CategoryID = c3.ParentCategoryID AND pc.Depth = %d";
127+
128+
for ($i = 3; $i > -1; $i--) {
129+
Gdn::sql()->query(sprintf($ancestorQuery, $i));
130+
}
131+
132+
//Step 3. Update categories without discussions.
133+
$emptyAncestorQuery = "UPDATE GDN_Category p
134+
SET p.LastDiscussionCommentsDate = COALESCE(p.DateUpdated, p.DateInserted)
135+
WHERE p.LastDiscussionCommentsDate IS NULL && p.LastDiscussionCommentsUserID IS NULL &&
136+
p.LastDiscussionCommentsDiscussionID IS NULL";
137+
Gdn::sql()->query($emptyAncestorQuery);
138+
}
139+
63140
}

vanilla/applications/vanilla/controllers/class.categoriescontroller.php

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -275,32 +275,26 @@ public function index($categoryIdentifier = '', $page = '0') {
275275
'EnableFollowingFilter' => &$this->enableFollowingFilter
276276
]);
277277

278-
$saveFollowing = Gdn::request()->get('followed') && Gdn::request()->get('save') && Gdn::session()->validateTransientKey(Gdn::request()->get('TransientKey', ''));
279-
280-
$followed = paramPreference(
281-
'followed',
282-
'FollowedCategories',
283-
'Vanilla.SaveFollowingPreference',
284-
null,
285-
$saveFollowing
286-
);
278+
$followed = Gdn::request()->get('followed', null);
279+
$saveFollowing = $followed !== null && Gdn::request()->get('save') && Gdn::session()->validateTransientKey(Gdn::request()->get('TransientKey', ''));
280+
if($saveFollowing) {
281+
$followed = Gdn::request()->get('followed');
282+
Gdn::session()->setPreference('FollowedCategories', $followed);
283+
}
287284
} else {
288285
$this->enableFollowingFilter = $followed = false;
289286
}
290287

288+
$followed = Gdn::session()->getPreference('FollowedCategories', false);
291289
$this->setData('EnableFollowingFilter', $this->enableFollowingFilter);
292290
$this->setData('Followed', $followed);
293291

294-
$saveSorting =Gdn::request()->get('sort') && Gdn::request()->get('save') && Gdn::session()->validateTransientKey(Gdn::request()->get('TransientKey', ''));
295-
296-
$sort = paramPreference(
297-
'sort',
298-
'CategorySort',
299-
null,//'Vanilla.SaveCategorySortPreference',
300-
null,
301-
$saveSorting
302-
);
303-
292+
$sort = Gdn::request()->get('sort', null);
293+
$saveSorting = $sort !== null && Gdn::request()->get('save') && Gdn::session()->validateTransientKey(Gdn::request()->get('TransientKey', ''));
294+
if($saveSorting) {
295+
Gdn::session()->setPreference('CategorySort', $sort);
296+
}
297+
$sort = Gdn::session()->getPreference('CategorySort', false);
304298
$this->setData('CategorySort', $sort);
305299

306300
if ($categoryIdentifier == '') {
@@ -412,7 +406,7 @@ public function index($categoryIdentifier = '', $page = '0') {
412406

413407
// Get a DiscussionModel
414408
$discussionModel = new DiscussionModel();
415-
$discussionModel->setSort(Gdn::request()->get());
409+
$discussionModel->setSort($sort);
416410
$discussionModel->setFilters(Gdn::request()->get());
417411
$this->setData('Sort', $discussionModel->getSort());
418412
$this->setData('Filters', $discussionModel->getFilters());
@@ -604,18 +598,18 @@ public function all($Category = '', $displayAs = '') {
604598
if($this->data('CategorySort')) {
605599
if( $this->data('CategorySort') == self::SORT_OLDEST_POST) {
606600
usort($categoryTree, function ($a, $b) {
607-
return Gdn_Format::toTimestamp($a['LastDateInserted']) - Gdn_Format::toTimestamp($b['LastDateInserted']);
601+
return Gdn_Format::toTimestamp($a['LastDiscussionCommentsDate']) - Gdn_Format::toTimestamp($b['LastDiscussionCommentsDate']);
608602
});
609603

610604
} else if( $this->data('CategorySort') == self::SORT_LAST_POST) {
611605
usort($categoryTree, function ($a, $b) {
612-
return Gdn_Format::toTimestamp($b['LastDateInserted']) - Gdn_Format::toTimestamp($a['LastDateInserted']);
606+
return Gdn_Format::toTimestamp($b['LastDiscussionCommentsDate']) - Gdn_Format::toTimestamp($a['LastDiscussionCommentsDate']);
613607

614608
});
615609
}
616610
} else {
617611
usort($categoryTree, function ($a, $b) { // desc
618-
return Gdn_Format::toTimestamp($b['LastDateInserted']) - Gdn_Format::toTimestamp($a['LastDateInserted']);
612+
return Gdn_Format::toTimestamp($b['LastDiscussionCommentsDate']) - Gdn_Format::toTimestamp($a['LastDiscussionCommentsDate']);
619613
});
620614
}
621615

vanilla/applications/vanilla/controllers/class.discussionscontroller.php

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,23 +126,26 @@ public function index($Page = false) {
126126
//FIX: the module is always enabled to show the view filter
127127
$followingEnabled = true;//$categoryModel->followingEnabled();
128128
if ($followingEnabled) {
129-
$saveFollowing = Gdn::request()->get('followed') && Gdn::request()->get('save') && Gdn::session()->validateTransientKey(Gdn::request()->get('TransientKey', ''));
130-
$followed = paramPreference(
131-
'followed',
132-
'FollowedCategories', //FIX: 'FollowedDiscussions' -Use one parameter for discussions/categories
133-
'Vanilla.SaveFollowingPreference',
134-
null,
135-
$saveFollowing
136-
);
129+
$followed = Gdn::request()->get('followed', null);
130+
$saveFollowing = Gdn::request()->get('followed') !== null && Gdn::request()->get('save') && Gdn::session()->validateTransientKey(Gdn::request()->get('TransientKey', ''));
131+
if($saveFollowing) {
132+
Gdn::session()->setPreference('FollowedCategories', $followed);
133+
}
137134
if ($this->SelfUrl === "discussions") {
138135
$this->enableFollowingFilter = true;
139136
}
140-
} else {
141-
$followed = false;
142137
}
138+
139+
$followed = Gdn::session()->getPreference('FollowedCategories', false);
143140
$this->setData('EnableFollowingFilter', $this->enableFollowingFilter);
144141
$this->setData('Followed', $followed);
145142

143+
$sort = Gdn::request()->get('sort', null);
144+
$saveSorting = $sort !== null && Gdn::request()->get('save') && Gdn::session()->validateTransientKey(Gdn::request()->get('TransientKey', ''));
145+
if($saveSorting) {
146+
Gdn::session()->setPreference('CategorySort', $sort);
147+
}
148+
146149
// Set criteria & get discussions data
147150
$this->setData('Category', false, true);
148151
$DiscussionModel = new DiscussionModel();

0 commit comments

Comments
 (0)