From 04133cd5f9a962ac3604badf75ce2de7387b67da Mon Sep 17 00:00:00 2001
From: Dorian Merz <merz@ub.uni-leipzig.de>
Date: Fri, 15 May 2020 15:03:11 +0200
Subject: [PATCH] refs #17357 [fid_bbi] improve tag handling

* adds all my tags section to MyResearch
* clarifies usage of "Your Tags" Recommend (i.e. filter for Favorite Lists)
---
 fid_bbi/languages/de.ini                      |   5 +
 fid_bbi/languages/en.ini                      |   5 +
 module/fid_bbi/config/module.config.php       |  11 ++
 .../Controller/MyResearchController.php       |  68 ++++++++++++
 module/fid_bbi/src/fid_bbi/Db/Table/Tags.php  |  59 ++++++++++
 .../fid_bbi/src/fid_bbi/Recommend/Factory.php |  62 +++++++++++
 .../src/fid_bbi/Recommend/FavoriteFacets.php  |  59 ++++++++++
 themes/fid_bbi/scss/compiled.scss             |  15 +++
 .../fid_bbi/templates/myresearch/menu.phtml   | 104 ++++++++++++++++++
 .../templates/myresearch/usertags.phtml       |  42 +++++++
 10 files changed, 430 insertions(+)
 create mode 100644 module/fid_bbi/src/fid_bbi/Controller/MyResearchController.php
 create mode 100644 module/fid_bbi/src/fid_bbi/Recommend/Factory.php
 create mode 100644 module/fid_bbi/src/fid_bbi/Recommend/FavoriteFacets.php
 create mode 100644 themes/fid_bbi/templates/myresearch/menu.phtml
 create mode 100644 themes/fid_bbi/templates/myresearch/usertags.phtml

diff --git a/fid_bbi/languages/de.ini b/fid_bbi/languages/de.ini
index 0e2e457cfdc..f0674dcf663 100644
--- a/fid_bbi/languages/de.ini
+++ b/fid_bbi/languages/de.ini
@@ -449,6 +449,11 @@ tagged_by_you = "von Ihnen markiert"
 tagged_by_others = "von anderen markiert"
 delete_tag = "Ihre Markierung entfernen"
 confirm_tag = "ebenfalls markieren"
+show_usertags = "Alle meine Tags zeigen"
+favorite_facets_tags_headline = "Listen nach Tags filtern"
+tags_record_count = "So getaggte Records"
+tags_records_on_lists = "Auf folgenden Listen"
+tags_browse = "Tags aller Nutzenden durchstöbern"
 
 #16903
 Open Access = Kostenfrei Zugänglich
diff --git a/fid_bbi/languages/en.ini b/fid_bbi/languages/en.ini
index 84ca71a74ff..2e513a91ee0 100644
--- a/fid_bbi/languages/en.ini
+++ b/fid_bbi/languages/en.ini
@@ -442,6 +442,11 @@ tagged_by_you = "tagged by you"
 tagged_by_others = "tagged by other users"
 delete_tag = "remove your tag"
 confirm_tag = "add your tag"
+show_usertags = "Show all my tags"
+favorite_facets_tags_headline = "Filter lists by tag"
+tags_record_count = "No of Records with this tag"
+tags_records_on_lists = "on favorite lists"
+tags_browse = "Browse all user's tags"
 
 #16903
 Open Access = Free Access
diff --git a/module/fid_bbi/config/module.config.php b/module/fid_bbi/config/module.config.php
index 89228772e86..db2ec71a6cc 100644
--- a/module/fid_bbi/config/module.config.php
+++ b/module/fid_bbi/config/module.config.php
@@ -36,6 +36,7 @@ $config = [
         'factories' => [
             'fid_bbi\Controller\FeedbackController' => 'VuFind\Controller\AbstractBaseFactory',
             'fid_bbi\Controller\SearchController'   => 'VuFind\Controller\AbstractBaseFactory',
+            'fid_bbi\Controller\MyResearchController'   => 'VuFind\Controller\AbstractBaseFactory',
             'fid_bbi\Controller\RecordController'   => 'VuFind\Controller\AbstractBaseWithConfigFactory',
         ],
         'aliases'   => [
@@ -45,6 +46,7 @@ $config = [
             'search'   => 'fid_bbi\Controller\SearchController',
             'Record'   => 'fid_bbi\Controller\RecordController',
             'record'   => 'fid_bbi\Controller\RecordController',
+            'VuFind\Controller\MyResearchController' => 'fid_bbi\Controller\MyResearchController',
         ],
     ],
     'vufind'      => [
@@ -66,6 +68,14 @@ $config = [
                     'worldcat'        => 'fid_bbi\RecordTab\Worldcat',
                 ],
             ],
+            'recommend' => [
+                'factories' => [
+                    'fid_bbi\Recommend\FavoriteFacets' => 'fid_bbi\Recommend\Factory::getFavoriteFacets',
+                ],
+                'aliases' => [
+                    'VuFind\Recommend\FavoriteFacets' => 'fid_bbi\Recommend\FavoriteFacets',
+                ]
+            ],
             'db_table'          => [
                 'aliases'    => [
                     BaseTagsTable::class => BBITagsTable::class,
@@ -165,6 +175,7 @@ $recordRoutes = [
 $staticRoutes = [
     'MyResearch/Acquisition',
     'MyResearch/ResetPassword',
+    'MyResearch/Usertags',
     'dds/Home',
     'dds/Email',
     'Record/EblLink',
diff --git a/module/fid_bbi/src/fid_bbi/Controller/MyResearchController.php b/module/fid_bbi/src/fid_bbi/Controller/MyResearchController.php
new file mode 100644
index 00000000000..6d472a86961
--- /dev/null
+++ b/module/fid_bbi/src/fid_bbi/Controller/MyResearchController.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * MyResearch Controller
+ *
+ * PHP version 7
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Dorian Merz <merz@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Site
+ */
+namespace fid_bbi\Controller;
+
+/**
+ * Controller for the user account area.
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Dorian Merz <merz@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Site
+ */
+class MyResearchController extends \finc\Controller\MyResearchController
+{
+    public function usertagsAction() {
+
+        // Not logged in?  Force user to log in:
+        if (!$this->getAuthManager()->isLoggedIn()) {
+            // Allow bypassing of post-login redirect
+            if ($this->params()->fromQuery('redirect', true)) {
+                $this->setFollowupUrlToReferer();
+            }
+            return $this->forwardTo('MyResearch', 'Login');
+        }
+        $user = $this->getUser();
+        $tags = [];
+        if ($user) {
+            $tags =
+                $this->serviceLocator->get('VuFind\Db\Table\PluginManager')
+                ->get('tags')
+                ->getAllForUser($user->id);
+            $lists = [];
+            foreach ($user->getLists() as $list) {
+                $lists[$list->id] = [
+                    'id' => $list->id,
+                    'title' => $list->title,
+                ];
+            }
+        }
+        return $this->createViewModel(compact('lists','tags'));
+    }
+}
diff --git a/module/fid_bbi/src/fid_bbi/Db/Table/Tags.php b/module/fid_bbi/src/fid_bbi/Db/Table/Tags.php
index 6a12ea30212..69a0511e80f 100644
--- a/module/fid_bbi/src/fid_bbi/Db/Table/Tags.php
+++ b/module/fid_bbi/src/fid_bbi/Db/Table/Tags.php
@@ -104,4 +104,63 @@ class Tags extends BaseTags
         };
         return $this->select($callback);
     }
+
+    /**
+     * Get a list of all tags generated by the user in favorites lists.  Note that
+     * the returned list WILL NOT include tags attached to records that are not
+     * saved in favorites lists.
+     *
+     * @param string $userId     User ID to look up.
+     * @param string $resourceId Filter for tags tied to a specific resource (null
+     * for no filter).
+     * @param int    $listId     Filter for tags tied to a specific list (null for no
+     * filter).
+     * @param string $source     Filter for tags tied to a specific record source
+     * (null for no filter).
+     *
+     * @return \Zend\Db\ResultSet\AbstractResultSet
+     */
+    public function getAllForUser($userId, $source = null)
+    {
+        $callback = function ($select) use ($userId, $source) {
+            $select->columns(
+                [
+                    'id' => new Expression(
+                        'min(?)', ['tags.id'],
+                        [Expression::TYPE_IDENTIFIER]
+                    ),
+                    'tag' => $this->caseSensitive
+                        ? 'tag' : new Expression('lower(tag)'),
+                    'cnt' => new Expression(
+                        'COUNT(DISTINCT(?))', ['rt.resource_id'],
+                        [Expression::TYPE_IDENTIFIER]
+                    ),
+                    'lists' => new Expression(
+                        'GROUP_CONCAT(DISTINCT(?))', ['ur.list_id'],
+                        [Expression::TYPE_IDENTIFIER]
+                    )
+                ]
+            );
+            $select->join(
+                ['rt' => 'resource_tags'], 'tags.id = rt.tag_id', []
+            );
+            $select->join(
+                ['r' => 'resource'], 'rt.resource_id = r.id', []
+            );
+            $select->join(
+                ['ur' => 'user_resource'], 'r.id = ur.resource_id', [], \Zend\Db\Sql\Select::JOIN_LEFT_OUTER
+            );
+            $select->group(['tag'])->order([new Expression('lower(tag)')]);
+
+            // contrary to the VuFind core approach we want all
+            // TAGS of RECORDS from the list
+            // not only those tagged within the list
+            $select->where->equalTo('rt.user_id', $userId);
+
+            if (null !== $source) {
+                $select->where->equalTo('r.source', $source);
+            }
+        };
+        return $this->select($callback);
+    }
 }
diff --git a/module/fid_bbi/src/fid_bbi/Recommend/Factory.php b/module/fid_bbi/src/fid_bbi/Recommend/Factory.php
new file mode 100644
index 00000000000..6d97cc7c78e
--- /dev/null
+++ b/module/fid_bbi/src/fid_bbi/Recommend/Factory.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Recommendation Module Factory Class
+ *
+ * PHP version 7
+ *
+ * Copyright (C) Villanova University 2014.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Recommendations
+ * @author   Dorian Merz <merz@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:hierarchy_components Wiki
+ */
+namespace fid_bbi\Recommend;
+
+use Zend\ServiceManager\ServiceManager;
+
+/**
+ * Recommendation Module Factory Class
+ *
+ * @category VuFind
+ * @package  Recommendations
+ * @author   Dorian Merz <merz@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:hierarchy_components Wiki
+ *
+ * @codeCoverageIgnore
+ */
+class Factory
+{
+    /**
+     * Factory for FavoriteFacets module.
+     * This is an unaltered copy of the VuFind-version of this function.
+     * Needed to ensure correct namespacing
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return FavoriteFacets
+     */
+    public static function getFavoriteFacets(ServiceManager $sm)
+    {
+        return new FavoriteFacets(
+            $sm->get('VuFind\Config\PluginManager'),
+            null,
+            $sm->get('VuFind\Config\AccountCapabilities')->getTagSetting()
+        );
+    }
+}
diff --git a/module/fid_bbi/src/fid_bbi/Recommend/FavoriteFacets.php b/module/fid_bbi/src/fid_bbi/Recommend/FavoriteFacets.php
new file mode 100644
index 00000000000..5235036c286
--- /dev/null
+++ b/module/fid_bbi/src/fid_bbi/Recommend/FavoriteFacets.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * FavoriteFacets Recommendations Module
+ *
+ * PHP version 7
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Recommendations
+ * @author   Dorian Merz <merz@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:recommendation_modules Wiki
+ */
+namespace fid_bbi\Recommend;
+
+use VuFind\Recommend\FavoriteFacets as BaseRecommend;
+
+/**
+ * FavoriteFacets Recommendations Module
+ *
+ * This class provides special facets for the Favorites area (tags/lists)
+ * FID BBI gets an individualized headline for the section.
+ *
+ * @category VuFind
+ * @package  Recommendations
+ * @author   Dorian Merz <merz@ub.uni-leipzig.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:recommendation_modules Wiki
+ */
+class FavoriteFacets extends BaseRecommend
+{
+    /**
+     * Store the configuration of the recommendation module.
+     *
+     * @param string $settings Settings from searches.ini.
+     *
+     * @return void
+     */
+    public function setConfig($settings)
+    {
+        // Only display tags when enabled:
+        $this->mainFacets = ($this->tagSetting !== 'disabled')
+            ? ['tags' => 'favorite_facets_tags_headline'] : [];
+    }
+}
diff --git a/themes/fid_bbi/scss/compiled.scss b/themes/fid_bbi/scss/compiled.scss
index fed1f2b7125..1c41a41030d 100644
--- a/themes/fid_bbi/scss/compiled.scss
+++ b/themes/fid_bbi/scss/compiled.scss
@@ -638,4 +638,19 @@ button.search-filter-toggle {
     @extend .fa;
     @extend .fa-users;
   }
+}
+
+table.tags {
+  border-top: 1px solid $charcoal;
+  border-bottom: 1px solid $charcoal;
+  th, td {
+    padding: .3em;
+  }
+  th {
+    border-bottom: 1px solid $charcoal;
+  }
+}
+
+.tag-browse-button a {
+  font-size: larger;
 }
\ No newline at end of file
diff --git a/themes/fid_bbi/templates/myresearch/menu.phtml b/themes/fid_bbi/templates/myresearch/menu.phtml
new file mode 100644
index 00000000000..d63a4b87f95
--- /dev/null
+++ b/themes/fid_bbi/templates/myresearch/menu.phtml
@@ -0,0 +1,104 @@
+<?php
+/**
+* copied from /fid/templates/myresearch/menu.phtml
+* which is
+* copied from /bootstrap3/templates/myresearch/menu.phtml
+* changed to include user tags menu entry
+*
+* @author   Dorian Merz <merz@ub.uni-leipzig.de>
+* @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+* @link     https://vufind.org Main Page
+*/
+?>
+<!-- fid_bbi: myresearch - menu.phtml -->
+<?php
+  $user = $this->auth()->isLoggedIn();
+?>
+<?php /* Offcanvas closing button missing in BS3! CK*/ ?>
+<button class="close-offcanvas btn btn-link" data-toggle="offcanvas"><?=$this->transEsc('navigate_back') ?></button>
+
+<?php if (!empty($user)): ?>
+  <h4><?=$this->transEsc('Your Account')?></h4>
+  <div class="myresearch-menu account-menu">
+    <?php if ('ils-none' !== $this->ils()->getOfflineMode()): ?>
+      <a href="<?=$this->url('myresearch-profile')?>"<?=$this->active == 'profile' ? ' class="active"' : ''?>>
+        <i class="fa fa-fw fa-user" aria-hidden="true"></i>
+        <?=$this->transEsc('Profile')?>
+      </a>
+
+      <?php /* refs #15480 add password change to fid profile */ ?>
+        <a href="<?=$this->url('fid/user/reset-password')?>" data-lightbox>
+          <span class="no-padding">
+            <i class="fa fa-fw fa-lock" aria-hidden="true"></i>
+          </span>
+          <?=$this->transEsc('Change Password')?>
+        </a>
+
+        <a href="<?=$this->url('fid/user/change-username')?>" data-lightbox>
+          <span class="no-padding">
+            <i class="fa fa-fw fa-envelope" aria-hidden="true"></i>
+          </span>
+          <?=$this->transEsc('fid::username_change_link')?>
+        </a>
+
+        <span class="logout-button">
+          <a href="<?=$this->url('myresearch-logout')?>">
+            <span class="no-padding">
+            <span class="no-padding">
+              <i class="fa fa-fw fa-sign-out" aria-hidden="true"></i>
+            </span>
+            <?=$this->transEsc("Logout")?>
+          </a>
+        </span>
+
+      <?php if ($user->libraryCardsEnabled()): ?>
+        <a href="<?=$this->url('librarycards-home')?>"<?=$this->active == 'librarycards' ? ' class="active"' : ''?>>
+          <i class="fa fa-fw fa-barcode" aria-hidden="true"></i> <?=$this->transEsc('Library Cards')?>
+        </a>
+      <?php endif; ?>
+    <?php endif; ?>
+  </div>
+
+    <?php if ('enabled' === $this->usertags()->getMode()): ?>
+        <br/>
+        <h4><?=$this->translate('Your Tags')?></h4>
+        <div class="myresearch-menu">
+            <a href="<?=$this->url('myresearch-usertags')?>"><?=$this->translate('show_usertags')?></a>
+        </div>
+    <?php endif; ?>
+
+  <?php if ($this->userlist()->getMode() !== 'disabled'): ?>
+        <br />
+    <h4><?=$this->transEsc('Your Lists')?></h4>
+
+    <div class="myresearch-menu">
+      <?php if ($this->accountCapabilities()->getSavedSearchSetting() === 'enabled'): ?>
+        <a href="<?=$this->url('search-history')?>?require_login"<?=$this->active == 'history' ? ' class="active"' : ''?>>
+          <i class="fa fa-fw fa-search" aria-hidden="true"></i> <?=$this->transEsc('history_saved_searches')?>
+        </a>
+      <?php endif; ?>
+      <a href="<?=$this->url('myresearch-favorites')?>"<?=$this->active == 'favorites' ? ' class="active"' : ''?>>
+        <i class="fa fa-fw fa-star" aria-hidden="true"></i> <?=$this->transEsc('Your Favorites')?>
+      </a>
+      <?php $lists = $user->getLists() ?>
+      <?php foreach ($lists as $list): ?>
+        <a href="<?=$this->url('userList', ['id' => $list['id']])?>"<?=$this->active == 'list' . $list['id'] ? ' class="active"' : ''?>>
+          <?=$this->escapeHtml($list['title'])?>
+          <span class="badge"><?=$list->cnt ?></span>
+        </a>
+      <?php endforeach; ?>
+      <a href="<?=$this->url('editList', ['id' => 'NEW'])?>">
+        <i class="fa fa-fw fa-plus" aria-hidden="true"></i> <?=$this->transEsc('Create a List') ?>
+      </a>
+      <?=$this->context($this)->renderInContext('myresearch/menu-additional-entries.phtml', array())?>
+    </div>
+  <?php endif ?>
+  <?php if ($this->permission()->allowDisplay('fid.ReadList')): ?>
+  <br/>
+  <h4><?=$this->transEsc('fid::admin_section')?></h4>
+  <div class="myresearch-menu">
+      <a href="<?=$this->url('fid/admin/list')?>"><?=$this->transEsc('fid::permission_read_user_list')?></a>
+  </div>
+  <?php endif; ?>
+  <!-- fid_bbi: myresearch - menu.phtml END -->
+<?php endif; ?>
diff --git a/themes/fid_bbi/templates/myresearch/usertags.phtml b/themes/fid_bbi/templates/myresearch/usertags.phtml
new file mode 100644
index 00000000000..a19a72b1574
--- /dev/null
+++ b/themes/fid_bbi/templates/myresearch/usertags.phtml
@@ -0,0 +1,42 @@
+<!-- fid_bbi: myresearch - usertags -->
+<div class="<?=$this->layoutClass('mainbody')?>">
+    <?php /* finc V5: adds offcanvas-toggler missing in VF5, compare with finc/fid themes during update - CK */ ?>
+    <?=$this->render('RecordDriver/DefaultRecord/offcanvas-toggler-myresearch'); ?>
+<h2><?=$this->translate('Your Tags')?></h2>
+    <?php if (!empty($tags)): ?>
+    <table class="tags">
+        <tr>
+            <th><?=$this->translate('Tag')?></th>
+            <th><?=$this->translate('tags_record_count')?></th>
+            <th><?=$this->translate('tags_records_on_lists')?></th>
+        </tr>
+    <?php foreach ($tags as $tag): ?>
+        <tr>
+        <td><a href="<?=$this->url('tag-home',[],['query' => ['lookfor' => $tag->tag]])?>">
+        <?=$tag->tag?>
+        </a></td>
+        <td><?=$tag->cnt ?></td>
+        <td>
+        <?php $onLists = explode(',',$tag->lists ?? '');
+            if (!empty($onLists)):?>
+            <? foreach ($onLists as $id): ?>
+                <?php if ($list = $lists[$id] ?? null): ?>
+                <span><a href="<?=$this->url('userList',['id'=>$list['id']])?>"><?=$list['title']?></a></span>
+                <?php endif; ?>
+            <?php endforeach; ?>
+        <?php endif; ?>
+        </td>
+        </tr>
+    <?php endforeach; ?>
+    </table>
+    <?php endif; ?>
+    <br/>
+    <div class="tag-browse-button">
+        <a href="<?=$this->url('browse-tag')?>"><?=$this->translate('tags_browse')?></a>
+    </div>
+</div>
+
+<div class="<?=$this->layoutClass('sidebar')?>">
+    <?=$this->context($this)->renderInContext("myresearch/menu.phtml", ['active' => 'profile'])?>
+</div>
+<!-- fid_bbi: myresearch - usertags - END -->
\ No newline at end of file
-- 
GitLab