From 973fb0f7dc9fcee6c234656d2a6bcaa5f681fa95 Mon Sep 17 00:00:00 2001 From: Bogdanova Olga Date: Sun, 22 Nov 2020 23:45:25 +0300 Subject: [PATCH] Issues-95 --- config/vanilla/bootstrap.before.php | 182 ++++++++++++++++++ .../class.categoriescontroller.php | 35 ++++ .../vanilla/models/class.discussionmodel.php | 3 +- .../vanilla/views/categories/all.php | 5 +- .../vanilla/views/categories/discussions.php | 49 +++++ .../vanilla/views/categories/table.php | 5 +- .../vanilla/views/discussions/index.php | 3 + 7 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 vanilla/applications/vanilla/views/categories/discussions.php diff --git a/config/vanilla/bootstrap.before.php b/config/vanilla/bootstrap.before.php index c97cc59..ce683a0 100644 --- a/config/vanilla/bootstrap.before.php +++ b/config/vanilla/bootstrap.before.php @@ -399,3 +399,185 @@ function updateRolePermissions($roleType, $roles) { } } } + +if (!function_exists('sortsDropDown')) { + /** + * Returns a sorting drop-down menu. + * + * @param string $baseUrl Target URL with no query string applied. + * @param array $filters A multidimensional array of rows with the following properties: + * ** 'name': Friendly name for the filter. + * ** 'param': URL parameter associated with the filter. + * ** 'value': A value for the URL parameter. + * @param string $extraClasses any extra classes you add to the drop down + * @param string|null $default The default label for when no filter is active. If `null`, the default label is "All". + * @param string|null $defaultURL URL override to return to the default, unfiltered state. + * @param string $label Text for the label to attach to the cont + * @return string + */ + function sortsDropDown($baseUrl, array $filters = [], $extraClasses = '', $default = null, $defaultUrl = null, $label = 'Sort') { + if ($default === null) { + $default = t('All'); + } + + $links = []; + $active = paramPreference( + 'sort', + 'CategorySort', + null,//'Vanilla.SaveCategorySortPreference', + null, + false + ); + // Translate filters into links. + foreach ($filters as $filter) { + // Make sure we have the bare minimum: a label and a URL parameter. + if (!array_key_exists('name', $filter)) { + throw new InvalidArgumentException('Sort does not have a name field.'); + } + if (!array_key_exists('param', $filter)) { + throw new InvalidArgumentException('Sort does not have a param field.'); + } + + // Prepare for consumption by linkDropDown. + $query = [$filter['param'] => $filter['value']]; + if (array_key_exists('extra', $filter) && is_array($filter['extra'])) { + $query += $filter['extra']; + } + $url = url($baseUrl . '?' . http_build_query($query)); + $link = [ + 'name' => $filter['name'], + 'url' => $url + ]; + + // If we don't already have an active link, and this parameter and value match, this is the active link. + if ($active === null && Gdn::request()->get($filter['param']) == $filter['value']) { + $active = $filter['value']; + $link['active'] = true; + } else if ($active == $filter['value']){ + $link['active'] = true; + $active = $filter['value']; + } + + // Queue up another filter link. + $links[] = $link; + } + + // Add the default link to the top of the list. + array_unshift($links, [ + 'active' => $active === null, + 'name' => $default, + 'url' => $defaultUrl ?: $baseUrl + ]); + + // Generate the markup for the drop down menu. + $output = linkDropDown($links, 'selectBox-following ' . trim($extraClasses), t($label) . ': '); + return $output; + } +} + +if (!function_exists('categorySorts')) { + /** + * Returns category sorting. + * + * @param string $extraClasses any extra classes you add to the drop down + * @return string + */ + function categorySorts($extraClasses = '') { + if (!Gdn::session()->isValid()) { + return; + } + + $baseUrl = Gdn::request()->path(); + $transientKey = Gdn::session()->transientKey(); + $filters = [ + [ + 'name' => t('New'), + 'param' => 'sort', + 'value' => 'new', + 'extra' => ['TransientKey' => $transientKey, 'save' => 1] + ], + + [ + 'name' => t('Old'), + 'param' => 'sort', + 'value' => 'old', + 'extra' => ['TransientKey' => $transientKey, 'save' => 1] + ] + ]; + + $defaultParams = ['TransientKey' => $transientKey]; + if (Gdn::request()->get('sort')) { + $defaultParams['sort'] = Gdn::request()->get('sort'); + } + + if (!empty($defaultParams)) { + $defaultUrl = $baseUrl.'?'.http_build_query($defaultParams); + } else { + $defaultUrl = $baseUrl; + } + + return sortsDropDown( + $baseUrl, + $filters, + $extraClasses, + t('All'), + $defaultUrl, + 'Sort' + ); + } +} + +if (!function_exists('discussionSorts')) { + /** + * Returns discussions sorting. + * + * @param string $extraClasses any extra classes you add to the drop down + * @return string + */ + function discussionSorts($extraClasses = '') { + if (!Gdn::session()->isValid()) { + return; + } + + $baseUrl = Gdn::request()->path(); + $transientKey = Gdn::session()->transientKey(); + + $filters = [ + [ + 'name' => t('New'), + 'param' => 'sort', + 'value' => 'new', + 'extra' => ['TransientKey' => $transientKey, 'save' => 1] + ], + [ + 'name' => t('Old'), + 'param' => 'sort', + 'value' => 'old', + 'extra' => ['TransientKey' => $transientKey, 'save' => 1] + ] + ]; + + + $defaultParams = ['save' => 1, 'TransientKey' => $transientKey]; + if (Gdn::request()->get('sort')) { + $defaultParams['sort'] = Gdn::request()->get('sort'); + } + + if (!empty($defaultParams)) { + $defaultUrl = $baseUrl.'?'.http_build_query($defaultParams); + } else { + $defaultUrl = $baseUrl; + } + + return sortsDropDown( + $baseUrl, + $filters, + $extraClasses, + t('All'), + $defaultUrl, + 'Sort' + ); + } +} + + diff --git a/vanilla/applications/vanilla/controllers/class.categoriescontroller.php b/vanilla/applications/vanilla/controllers/class.categoriescontroller.php index 2e6fb48..2bf3d24 100644 --- a/vanilla/applications/vanilla/controllers/class.categoriescontroller.php +++ b/vanilla/applications/vanilla/controllers/class.categoriescontroller.php @@ -31,6 +31,8 @@ class CategoriesController extends VanillaController { /** @var bool Value indicating if the category-following filter should be displayed when rendering a view */ public $enableFollowingFilter = true;//false; + const SORT_LAST_POST = 'new'; + const SORT_OLDEST_POST = 'old'; /** * @var \Closure $categoriesCompatibilityCallback A backwards-compatible callback to get `$this->data('Categories')`. @@ -273,6 +275,7 @@ public function index($categoryIdentifier = '', $page = '0') { ]); $saveFollowing = Gdn::request()->get('save') && Gdn::session()->validateTransientKey(Gdn::request()->get('TransientKey', '')); + $followed = paramPreference( 'followed', 'FollowedCategories', @@ -283,9 +286,23 @@ public function index($categoryIdentifier = '', $page = '0') { } else { $this->enableFollowingFilter = $followed = false; } + $this->setData('EnableFollowingFilter', $this->enableFollowingFilter); $this->setData('Followed', $followed); + $saveSorting =Gdn::request()->get('sort') && Gdn::request()->get('save') && Gdn::session()->validateTransientKey(Gdn::request()->get('TransientKey', '')); + + $sort = paramPreference( + 'sort', + 'CategorySort', + null,//'Vanilla.SaveCategorySortPreference', + null, + $saveSorting + ); + + $this->log('index: sorts: after', ['$sort' => $sort, '$saveSorting'=>$saveSorting]); + $this->setData('CategorySort', $sort); + if ($categoryIdentifier == '') { switch ($layout) { case 'mixed': @@ -585,6 +602,24 @@ public function all($Category = '', $displayAs = '') { ); } + if($this->data('CategorySort')) { + if( $this->data('CategorySort') == self::SORT_OLDEST_POST) { + usort($categoryTree, function ($a, $b) { + return Gdn_Format::toTimestamp($a['LastDateInserted']) - Gdn_Format::toTimestamp($b['LastDateInserted']); + }); + + } else if( $this->data('CategorySort') == self::SORT_LAST_POST) { + usort($categoryTree, function ($a, $b) { + return Gdn_Format::toTimestamp($b['LastDateInserted']) - Gdn_Format::toTimestamp($a['LastDateInserted']); + + }); + } + } else { + usort($categoryTree, function ($a, $b) { // desc + return Gdn_Format::toTimestamp($b['LastDateInserted']) - Gdn_Format::toTimestamp($a['LastDateInserted']); + }); + } + $this->setData('CategoryTree', $categoryTree); // Add modules diff --git a/vanilla/applications/vanilla/models/class.discussionmodel.php b/vanilla/applications/vanilla/models/class.discussionmodel.php index a081ea1..2ebf66d 100644 --- a/vanilla/applications/vanilla/models/class.discussionmodel.php +++ b/vanilla/applications/vanilla/models/class.discussionmodel.php @@ -64,7 +64,8 @@ class DiscussionModel extends Gdn_Model { protected static $allowedSorts = [ 'hot' => ['key' => 'hot', 'name' => 'Hot', 'orderBy' => ['DateLastComment' => 'desc']], 'top' => ['key' => 'top', 'name' => 'Top', 'orderBy' => ['Score' => 'desc', 'DateInserted' => 'desc']], - 'new' => ['key' => 'new', 'name' => 'New', 'orderBy' => ['DateInserted' => 'desc']] + 'new' => ['key' => 'new', 'name' => 'New', 'orderBy' => ['DateInserted' => 'desc']], + 'old' => ['key' => 'old', 'name' => 'Old', 'orderBy' => ['DateInserted' => 'asc']] ]; /** diff --git a/vanilla/applications/vanilla/views/categories/all.php b/vanilla/applications/vanilla/views/categories/all.php index 1027a59..8c5e430 100644 --- a/vanilla/applications/vanilla/views/categories/all.php +++ b/vanilla/applications/vanilla/views/categories/all.php @@ -10,8 +10,11 @@ echo wrap($description, 'div', ['class' => 'P PageDescription']); } $this->fireEvent('AfterPageTitle'); +echo '
'; if ($this->data('EnableFollowingFilter')) { - echo '
'.categoryFilters().'
'; + echo categoryFilters(); } +echo categorySorts(); +echo '
'; $categories = $this->data('CategoryTree'); writeCategoryList($categories, 1); diff --git a/vanilla/applications/vanilla/views/categories/discussions.php b/vanilla/applications/vanilla/views/categories/discussions.php new file mode 100644 index 0000000..6b7aaac --- /dev/null +++ b/vanilla/applications/vanilla/views/categories/discussions.php @@ -0,0 +1,49 @@ +'.$this->data('Title').''; +echo '
'; +if ($this->data('EnableFollowingFilter')) { + echo categoryFilters(); +} +echo categorySorts(); +echo '
'; + +$ViewLocation = $this->fetchViewLocation('discussions', 'discussions'); +?> +
+ CategoryData->numRows() > 0): ?> + CategoryData->result() as $Category) : + if ($Category->CategoryID <= 0) + continue; + + $this->Category = $Category; + $this->DiscussionData = $this->CategoryDiscussionData[$Category->CategoryID]; + + if ($this->DiscussionData->numRows() > 0) : ?> + +
+ +

Name), categoryUrl($Category)); + Gdn::controller()->EventArguments['Category'] = $Category; + Gdn::controller()->fireEvent('AfterCategoryTitle'); + ?>

+ +
    + fetchViewLocation('discussions', 'discussions')); ?> +
+ + DiscussionData->numRows() == $this->DiscussionsPerCategory) : ?> +
+ UrlCode); ?> +
+ + +
+ + + + + +
+ +
diff --git a/vanilla/applications/vanilla/views/categories/table.php b/vanilla/applications/vanilla/views/categories/table.php index 4014238..eaaa826 100644 --- a/vanilla/applications/vanilla/views/categories/table.php +++ b/vanilla/applications/vanilla/views/categories/table.php @@ -7,9 +7,12 @@ fireEvent('AfterDescription'); $this->fireEvent('AfterPageTitle'); +echo '
'; if ($this->data('EnableFollowingFilter')) { - echo '
'.categoryFilters().'
'; + echo categoryFilters(); } +echo categorySorts(); +echo '
'; $categories = $this->data('CategoryTree'); writeCategoryTable($categories); ?> diff --git a/vanilla/applications/vanilla/views/discussions/index.php b/vanilla/applications/vanilla/views/discussions/index.php index 0d17da7..33c4628 100644 --- a/vanilla/applications/vanilla/views/discussions/index.php +++ b/vanilla/applications/vanilla/views/discussions/index.php @@ -45,6 +45,9 @@ if ($this->data('EnableFollowingFilter')) { echo discussionFilters(); } +if($this instanceof CategoriesController) { + echo discussionSorts(); +} $this->fireEvent('PageControls'); echo '';