From 2b05cef5c7f3041444ad415935f482e8b3cacfee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuli=20Sillanp=C3=A4=C3=A4?= <samuli.sillanpaa@helsinki.fi> Date: Fri, 14 Aug 2020 16:29:11 -0400 Subject: [PATCH] Add support for tagging of user lists. - Deprecates VuFind\Db\Row\UserList::getTags() in favor of VuFind\Db\Row\UserList::getResourceTags() - Deprecates VuFind\Db\Table\ResourceTags::destroyLinks() in favor of VuFind\Db\Table\ResourceTags::destroyResourceLinks() - Includes code originally developed as part of pull request #1645. --- config/vufind/config.ini | 2 + .../pgsql/7.1/001-allow-list-tags.sql | 9 ++ module/VuFind/sql/mysql.sql | 2 +- module/VuFind/sql/pgsql.sql | 2 +- .../src/VuFind/Config/AccountCapabilities.php | 13 +++ .../VuFind/Controller/BrowseController.php | 7 +- .../Controller/MyResearchController.php | 38 ++++++++- module/VuFind/src/VuFind/Db/Row/Resource.php | 4 +- module/VuFind/src/VuFind/Db/Row/User.php | 40 +++++++-- module/VuFind/src/VuFind/Db/Row/UserList.php | 85 +++++++++++++++++-- .../src/VuFind/Db/Row/UserListFactory.php | 5 +- .../src/VuFind/Db/Table/ResourceTags.php | 69 +++++++++++++-- module/VuFind/src/VuFind/Db/Table/Tags.php | 38 +++++++++ .../src/VuFind/Db/Table/UserResource.php | 4 +- .../src/VuFind/View/Helper/Root/UserTags.php | 23 ++++- .../View/Helper/Root/UserTagsFactory.php | 5 +- .../VuFind/src/VuFindTest/Unit/DbTestCase.php | 1 + .../templates/myresearch/editlist.phtml | 7 ++ .../templates/myresearch/mylist.phtml | 3 + 19 files changed, 325 insertions(+), 32 deletions(-) create mode 100644 module/VuFind/sql/migrations/pgsql/7.1/001-allow-list-tags.sql diff --git a/config/vufind/config.ini b/config/vufind/config.ini index c8c236fac83..c68fd5e0184 100644 --- a/config/vufind/config.ini +++ b/config/vufind/config.ini @@ -1984,6 +1984,8 @@ lists_view=full ; Tags may be "enabled" or "disabled" (default = "enabled") ; When disabling tags, don't forget to also turn off tag search in searches.ini. tags = enabled +; User list tags may be "enabled" or "disabled" (default = "disabled") +listTags = disabled ; This controls the maximum length of a single tag; it should correspond with the ; field size in the tags database table. max_tag_length = 64 diff --git a/module/VuFind/sql/migrations/pgsql/7.1/001-allow-list-tags.sql b/module/VuFind/sql/migrations/pgsql/7.1/001-allow-list-tags.sql new file mode 100644 index 00000000000..de562b4176c --- /dev/null +++ b/module/VuFind/sql/migrations/pgsql/7.1/001-allow-list-tags.sql @@ -0,0 +1,9 @@ +-- +-- Modifications to table `resource_tags` +-- + +ALTER TABLE "resource_tags" + ALTER COLUMN resource_id DROP NOT NULL; + +ALTER TABLE "resource_tags" + ALTER COLUMN resource_id SET DEFAULT NULL; diff --git a/module/VuFind/sql/mysql.sql b/module/VuFind/sql/mysql.sql index 5f3ff8cb8c0..95663adb92e 100644 --- a/module/VuFind/sql/mysql.sql +++ b/module/VuFind/sql/mysql.sql @@ -88,7 +88,7 @@ CREATE TABLE `resource` ( /*!40101 SET character_set_client = utf8 */; CREATE TABLE `resource_tags` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `resource_id` int(11) NOT NULL DEFAULT '0', + `resource_id` int(11) DEFAULT NULL, `tag_id` int(11) NOT NULL DEFAULT '0', `list_id` int(11) DEFAULT NULL, `user_id` int(11) DEFAULT NULL, diff --git a/module/VuFind/sql/pgsql.sql b/module/VuFind/sql/pgsql.sql index e2c22278141..989f7f45d65 100644 --- a/module/VuFind/sql/pgsql.sql +++ b/module/VuFind/sql/pgsql.sql @@ -47,7 +47,7 @@ DROP TABLE IF EXISTS "resource_tags"; CREATE TABLE resource_tags ( id SERIAL, -resource_id int NOT NULL DEFAULT '0', +resource_id int DEFAULT NULL, tag_id int NOT NULL DEFAULT '0', list_id int DEFAULT NULL, user_id int DEFAULT NULL, diff --git a/module/VuFind/src/VuFind/Config/AccountCapabilities.php b/module/VuFind/src/VuFind/Config/AccountCapabilities.php index 1c559b08812..08cc66117e4 100644 --- a/module/VuFind/src/VuFind/Config/AccountCapabilities.php +++ b/module/VuFind/src/VuFind/Config/AccountCapabilities.php @@ -136,6 +136,19 @@ class AccountCapabilities ? 'disabled' : 'enabled'; } + /** + * Get list tag setting. + * + * @return string + */ + public function getListTagSetting() + { + if (!$this->isAccountAvailable()) { + return 'disabled'; + } + return $this->config->Social->listTags ?? 'disabled'; + } + /** * Get SMS setting ('enabled' or 'disabled'). * diff --git a/module/VuFind/src/VuFind/Controller/BrowseController.php b/module/VuFind/src/VuFind/Controller/BrowseController.php index e609c487d9c..bba2d063936 100644 --- a/module/VuFind/src/VuFind/Controller/BrowseController.php +++ b/module/VuFind/src/VuFind/Controller/BrowseController.php @@ -345,9 +345,14 @@ class BrowseController extends AbstractBase } } else { // Default case: always display tag list for non-alphabetical modes: + $callback = function ($select) { + // Discard user list tags + $select->where->isNotNull('resource_tags.resource_id'); + }; + $tagList = $tagTable->getTagList( $params['findby'], - $this->config->Browse->result_limit + $this->config->Browse->result_limit, $callback ); $resultList = []; foreach ($tagList as $i => $tag) { diff --git a/module/VuFind/src/VuFind/Controller/MyResearchController.php b/module/VuFind/src/VuFind/Controller/MyResearchController.php index 0933d76e98b..60555e02d45 100644 --- a/module/VuFind/src/VuFind/Controller/MyResearchController.php +++ b/module/VuFind/src/VuFind/Controller/MyResearchController.php @@ -909,8 +909,20 @@ class MyResearchController extends AbstractBase }; $results = $runner->run($request, 'Favorites', $setupCallback); + $listTags = []; + + if ($this->listTagsEnabled()) { + if ($list = $results->getListObject()) { + foreach ($list->getListTags() as $tag) { + $listTags[$tag->id] = $tag->tag; + } + } + } return $this->createViewModel( - ['params' => $results->getParams(), 'results' => $results] + [ + 'params' => $results->getParams(), 'results' => $results, + 'listTags' => $listTags + ] ); } catch (ListPermissionException $e) { if (!$this->getUser()) { @@ -1019,8 +1031,18 @@ class MyResearchController extends AbstractBase } } + $listTags = null; + if ($this->listTagsEnabled() && !$newList) { + $listTags = $user->formatTagString($list->getListTags()); + } // Send the list to the view: - return $this->createViewModel(['list' => $list, 'newList' => $newList]); + return $this->createViewModel( + [ + 'list' => $list, + 'newList' => $newList, + 'listTags' => $listTags + ] + ); } /** @@ -2129,4 +2151,16 @@ class MyResearchController extends AbstractBase } return $this->paginationHelper; } + + /** + * Are list tags enabled? + * + * @return bool + */ + protected function listTagsEnabled() + { + $check = $this->serviceLocator + ->get(\VuFind\Config\AccountCapabilities::class); + return $check->getListTagSetting() === 'enabled'; + } } diff --git a/module/VuFind/src/VuFind/Db/Row/Resource.php b/module/VuFind/src/VuFind/Db/Row/Resource.php index 86824d23040..8cf00c60a08 100644 --- a/module/VuFind/src/VuFind/Db/Row/Resource.php +++ b/module/VuFind/src/VuFind/Db/Row/Resource.php @@ -65,7 +65,7 @@ class Resource extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterf public function deleteTags($user, $list_id = null) { $unlinker = $this->getDbTable('ResourceTags'); - $unlinker->destroyLinks($this->id, $user->id, $list_id); + $unlinker->destroyResourceLinks($this->id, $user->id, $list_id); } /** @@ -113,7 +113,7 @@ class Resource extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterf } if (!empty($tagIds)) { $linker = $this->getDbTable('ResourceTags'); - $linker->destroyLinks( + $linker->destroyResourceLinks( $this->id, $user->id, $list_id, $tagIds ); } diff --git a/module/VuFind/src/VuFind/Db/Row/User.php b/module/VuFind/src/VuFind/Db/Row/User.php index 73a4372f8ee..5b2ddd8700a 100644 --- a/module/VuFind/src/VuFind/Db/Row/User.php +++ b/module/VuFind/src/VuFind/Db/Row/User.php @@ -274,6 +274,19 @@ class User extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterface, ->getForUser($this->id, $resourceId, $listId, $source); } + /** + * Get tags assigned by the user to a favorite list. + * + * @param int $listId List id + * + * @return \Laminas\Db\ResultSet\AbstractResultSet + */ + public function getListTags($listId) + { + return $this->getDbTable('Tags') + ->getForList($listId, $this->id); + } + /** * Same as getTags(), but returns a string for use in edit mode rather than an * array of tag objects. @@ -289,14 +302,25 @@ class User extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterface, */ public function getTagString($resourceId = null, $listId = null, $source = null) { - $myTagList = $this->getTags($resourceId, $listId, $source); + return $this->formatTagString($this->getTags($resourceId, $listId, $source)); + } + + /** + * Same as getTagString(), but operates on a list of tags. + * + * @param array $tags Tags + * + * @return string + */ + public function formatTagString($tags) + { $tagStr = ''; - if (count($myTagList) > 0) { - foreach ($myTagList as $myTag) { - if (strstr($myTag->tag, ' ')) { - $tagStr .= "\"$myTag->tag\" "; + if (count($tags) > 0) { + foreach ($tags as $tag) { + if (strstr($tag->tag, ' ')) { + $tagStr .= "\"$tag->tag\" "; } else { - $tagStr .= "$myTag->tag "; + $tagStr .= "$tag->tag "; } } } @@ -412,7 +436,7 @@ class User extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterface, // Remove Resource (related tags are also removed implicitly) $userResourceTable = $this->getDbTable('UserResource'); // true here makes sure that only tags in lists are deleted - $userResourceTable->destroyLinks($resourceIDs, $this->id, true); + $userResourceTable->destroyResourceLinks($resourceIDs, $this->id, true); } /** @@ -656,7 +680,7 @@ class User extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterface, $list->delete($this, true); } $resourceTags = $this->getDbTable('ResourceTags'); - $resourceTags->destroyLinks(null, $this->id); + $resourceTags->destroyResourceLinks(null, $this->id); if ($removeComments) { $comments = $this->getDbTable('Comments'); $comments->deleteByUser($this); diff --git a/module/VuFind/src/VuFind/Db/Row/UserList.php b/module/VuFind/src/VuFind/Db/Row/UserList.php index 508ef3b2669..8a3c8b29c92 100644 --- a/module/VuFind/src/VuFind/Db/Row/UserList.php +++ b/module/VuFind/src/VuFind/Db/Row/UserList.php @@ -30,6 +30,7 @@ namespace VuFind\Db\Row; use Laminas\Session\Container; use VuFind\Exception\ListPermission as ListPermissionException; use VuFind\Exception\MissingField as MissingFieldException; +use VuFind\Tags; /** * Row Definition for user_list @@ -51,14 +52,23 @@ class UserList extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterf */ protected $session = null; + /** + * Tag parser. + * + * @var Tags + */ + protected $tagParser; + /** * Constructor * - * @param \Laminas\Db\Adapter\Adapter $adapter Database adapter - * @param Container $session Session container + * @param \Laminas\Db\Adapter\Adapter $adapter Database adapter + * @param Tags $tagParser Tag parser + * @param Container $session Session container */ - public function __construct($adapter, Container $session = null) + public function __construct($adapter, Tags $tagParser, Container $session = null) { + $this->tagParser = $tagParser; $this->session = $session; parent::__construct('id', 'user_list', $adapter); } @@ -79,11 +89,11 @@ class UserList extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterf } /** - * Get an array of tags associated with this list. + * Get an array of resource tags associated with this list. * * @return array */ - public function getTags() + public function getResourceTags() { $table = $this->getDbTable('User'); $user = $table->select(['id' => $this->user_id])->current(); @@ -93,6 +103,33 @@ class UserList extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterf return $user->getTags(null, $this->id); } + /** + * Get an array of resource tags associated with this list. + * + * @deprecated Deprecated, use getResourceTags. + * + * @return array + */ + public function getTags() + { + return $this->getResourceTags(); + } + + /** + * Get an array of tags assigned to this list. + * + * @return array + */ + public function getListTags() + { + $table = $this->getDbTable('User'); + $user = $table->select(['id' => $this->user_id])->current(); + if (empty($user)) { + return []; + } + return $user->getListTags($this->id, $this->user_id); + } + /** * Update and save the list object using a request object -- useful for * sharing form processing between multiple actions. @@ -110,9 +147,39 @@ class UserList extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterf $this->description = $request->get('desc'); $this->public = $request->get('public'); $this->save($user); + + if (null !== ($tags = $request->get('tags'))) { + $linker = $this->getDbTable('resourcetags'); + $linker->destroyListLinks($this->id, $user->id); + foreach ($this->tagParser->parse($tags) as $tag) { + $this->addListTag($tag, $user); + } + } + return $this->id; } + /** + * Add a tag to the list. + * + * @param string $tagText The tag to save. + * @param \VuFind\Db\Row\User $user The user posting the tag. + * + * @return void + */ + public function addListTag($tagText, $user) + { + $tagText = trim($tagText); + if (!empty($tagText)) { + $tags = $this->getDbTable('tags'); + $tag = $tags->getByText($tagText); + $linker = $this->getDbTable('resourcetags'); + $linker->createLink( + null, $tag->id, $user->id, $this->id + ); + } + } + /** * Saves the properties to the database. * @@ -192,7 +259,9 @@ class UserList extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterf // Remove Resource (related tags are also removed implicitly) $userResourceTable = $this->getDbTable('UserResource'); - $userResourceTable->destroyLinks($resourceIDs, $this->user_id, $this->id); + $userResourceTable->destroyResourceLinks( + $resourceIDs, $this->user_id, $this->id + ); } /** @@ -224,6 +293,10 @@ class UserList extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterf $userResource = $this->getDbTable('UserResource'); $userResource->destroyLinks(null, $this->user_id, $this->id); + // Remove resource_tags rows for list tags: + $linker = $this->getDbTable('resourcetags'); + $linker->destroyListLinks($this->id, $user->id); + // Remove the list itself: return parent::delete(); } diff --git a/module/VuFind/src/VuFind/Db/Row/UserListFactory.php b/module/VuFind/src/VuFind/Db/Row/UserListFactory.php index 949287cce08..31eb9401860 100644 --- a/module/VuFind/src/VuFind/Db/Row/UserListFactory.php +++ b/module/VuFind/src/VuFind/Db/Row/UserListFactory.php @@ -62,6 +62,9 @@ class UserListFactory extends RowGatewayFactory } $sessionManager = $container->get(\Laminas\Session\SessionManager::class); $session = new \Laminas\Session\Container('List', $sessionManager); - return parent::__invoke($container, $requestedName, [$session]); + return parent::__invoke( + $container, $requestedName, + [$container->get(\VuFind\Tags::class), $session] + ); } } diff --git a/module/VuFind/src/VuFind/Db/Table/ResourceTags.php b/module/VuFind/src/VuFind/Db/Table/ResourceTags.php index f886361a2bb..a0df30a8695 100644 --- a/module/VuFind/src/VuFind/Db/Table/ResourceTags.php +++ b/module/VuFind/src/VuFind/Db/Table/ResourceTags.php @@ -232,15 +232,12 @@ class ResourceTags extends Gateway * * @return void */ - public function destroyLinks($resource, $user, $list = null, $tag = null) + public function destroyResourceLinks($resource, $user, $list = null, $tag = null) { $callback = function ($select) use ($resource, $user, $list, $tag) { $select->where->equalTo('user_id', $user); if (null !== $resource) { - if (!is_array($resource)) { - $resource = [$resource]; - } - $select->where->in('resource_id', $resource); + $select->where->in('resource_id', (array)$resource); } if (null !== $list) { if (true === $list) { @@ -263,7 +260,69 @@ class ResourceTags extends Gateway } } }; + $this->processDestroyLinks($callback); + } + + /** + * Unlink rows for the specified resource. + * + * @param string|array $resource ID (or array of IDs) of resource(s) to + * unlink (null for ALL matching resources) + * @param string $user ID of user removing links + * @param string $list ID of list to unlink (null for ALL matching + * tags, 'none' for tags not in a list, true for tags only found in a list) + * @param string|array $tag ID or array of IDs of tag(s) to unlink (null + * for ALL matching tags) + * + * @deprecated Deprecated, use destroyResourceLinks. + * + * @return void + */ + public function destroyLinks($resource, $user, $list = null, $tag = null) + { + $this->destroyResourceLinks($resource, $user, $list, $tag); + } + + /** + * Unlink rows for the specified user list. + * + * @param string $list ID of list to unlink + * @param string $user ID of user removing links + * @param string|array $tag ID or array of IDs of tag(s) to unlink (null + * for ALL matching tags) + * + * @return void + */ + public function destroyListLinks($list, $user, $tag = null) + { + $callback = function ($select) use ($user, $list, $tag) { + $select->where->equalTo('user_id', $user); + // retrieve tags assigned to a user list + // and filter out user resource tags + // (resource_id is NULL for list tags). + $select->where->isNull('resource_id'); + $select->where->equalTo('list_id', $list); + + if (null !== $tag) { + if (is_array($tag)) { + $select->where->in('tag_id', $tag); + } else { + $select->where->equalTo('tag_id', $tag); + } + } + }; + $this->processDestroyLinks($callback); + } + /** + * Process link rows marked to be destroyed. + * + * @param Object $callback Callback function for selecting deleted rows. + * + * @return void + */ + protected function processDestroyLinks($callback) + { // Get a list of all tag IDs being deleted; we'll use these for // orphan-checking: $potentialOrphans = $this->select($callback); diff --git a/module/VuFind/src/VuFind/Db/Table/Tags.php b/module/VuFind/src/VuFind/Db/Table/Tags.php index b6b647e7f78..cb64f486518 100644 --- a/module/VuFind/src/VuFind/Db/Table/Tags.php +++ b/module/VuFind/src/VuFind/Db/Table/Tags.php @@ -111,6 +111,8 @@ class Tags extends Gateway { $callback = function ($select) use ($text) { $select->where->literal('lower(tag) like lower(?)', [$text . '%']); + // Discard tags assigned to a user list. + $select->where->isNotNull('resource_tags.resource_id'); }; return $this->getTagList($sort, $limit, $callback); } @@ -156,6 +158,8 @@ class Tags extends Gateway } else { $select->where->equalTo('tags.tag', $q); } + // Discard tags assigned to a user list. + $select->where->isNotNull('rt.resource_id'); if (!empty($source)) { $select->where->equalTo('source', $source); @@ -327,6 +331,40 @@ class Tags extends Gateway return $this->select($callback); } + /** + * Get tags assigned to a user list. + * + * @param int $listId List ID + * @param string $userId User ID to look up (null for no filter). + * + * @return \Laminas\Db\ResultSet\AbstractResultSet + */ + public function getForList($listId, $userId = null) + { + $callback = function ($select) use ($listId, $userId) { + $select->columns( + [ + 'id' => new Expression( + 'min(?)', ['tags.id'], + [Expression::TYPE_IDENTIFIER] + ), + 'tag' => $this->caseSensitive + ? 'tag' : new Expression('lower(tag)') + ] + ); + $select->join( + ['rt' => 'resource_tags'], 'tags.id = rt.tag_id', [] + ); + $select->where->equalTo('rt.list_id', $listId); + $select->where->isNull('rt.resource_id'); + if ($userId) { + $select->where->equalTo('rt.user_id', $userId); + } + $select->group(['tag'])->order([new Expression('lower(tag)')]); + }; + return $this->select($callback); + } + /** * Get a subquery used for flagging tag ownership (see getForResource). * diff --git a/module/VuFind/src/VuFind/Db/Table/UserResource.php b/module/VuFind/src/VuFind/Db/Table/UserResource.php index 383dc1f44ab..52a242783cd 100644 --- a/module/VuFind/src/VuFind/Db/Table/UserResource.php +++ b/module/VuFind/src/VuFind/Db/Table/UserResource.php @@ -156,7 +156,7 @@ class UserResource extends Gateway // want to leave orphaned tags in the resource_tags table after we have // cleared out favorites in user_resource! $resourceTags = $this->getDbTable('ResourceTags'); - $resourceTags->destroyLinks($resource_id, $user_id, $list_id); + $resourceTags->destroyResourceLinks($resource_id, $user_id, $list_id); // Now build the where clause to figure out which rows to remove: $callback = function ($select) use ($resource_id, $user_id, $list_id) { @@ -168,7 +168,7 @@ class UserResource extends Gateway $select->where->in('resource_id', $resource_id); } // null or true values of $list_id have different meanings in the - // context of the $resourceTags->destroyLinks() call above, since + // context of the $resourceTags->destroyResourceLinks() call above, since // some tags have a null $list_id value. In the case of user_resource // rows, however, every row has a non-null $list_id value, so the // two cases are equivalent and may be handled identically. diff --git a/module/VuFind/src/VuFind/View/Helper/Root/UserTags.php b/module/VuFind/src/VuFind/View/Helper/Root/UserTags.php index 3b86eff300a..7c6ec5a063c 100644 --- a/module/VuFind/src/VuFind/View/Helper/Root/UserTags.php +++ b/module/VuFind/src/VuFind/View/Helper/Root/UserTags.php @@ -47,14 +47,23 @@ class UserTags extends AbstractHelper */ protected $mode; + /** + * List tag mode (enabled or disabled) + * + * @var string + */ + protected $listMode; + /** * Constructor * - * @param string $mode Tag mode (enabled or disabled) + * @param string $mode Tag mode (enabled or disabled) + * @param string $listMode List tag mode (enabled or disabled) */ - public function __construct($mode = 'enabled') + public function __construct($mode = 'enabled', $listMode = 'disabled') { $this->mode = $mode; + $this->listMode = $listMode; } /** @@ -66,4 +75,14 @@ class UserTags extends AbstractHelper { return $this->mode; } + + /** + * Get list mode + * + * @return string + */ + public function getListMode() + { + return $this->listMode; + } } diff --git a/module/VuFind/src/VuFind/View/Helper/Root/UserTagsFactory.php b/module/VuFind/src/VuFind/View/Helper/Root/UserTagsFactory.php index f1d9459cec9..835fd939a30 100644 --- a/module/VuFind/src/VuFind/View/Helper/Root/UserTagsFactory.php +++ b/module/VuFind/src/VuFind/View/Helper/Root/UserTagsFactory.php @@ -62,6 +62,9 @@ class UserTagsFactory implements FactoryInterface throw new \Exception('Unexpected options sent to factory.'); } $capabilities = $container->get(\VuFind\Config\AccountCapabilities::class); - return new $requestedName($capabilities->getTagSetting()); + return new $requestedName( + $capabilities->getTagSetting(), + $capabilities->getListTagSetting() + ); } } diff --git a/module/VuFind/src/VuFindTest/Unit/DbTestCase.php b/module/VuFind/src/VuFindTest/Unit/DbTestCase.php index 52d6b834950..999461d7f8e 100644 --- a/module/VuFind/src/VuFindTest/Unit/DbTestCase.php +++ b/module/VuFind/src/VuFindTest/Unit/DbTestCase.php @@ -154,6 +154,7 @@ abstract class DbTestCase extends TestCase public function getTable($table) { $sm = $this->getServiceManager(); + $sm->setService(\VuFind\Tags::class, new \VuFind\Tags()); return $sm->get(\VuFind\Db\Table\PluginManager::class)->get($table); } } diff --git a/themes/bootstrap3/templates/myresearch/editlist.phtml b/themes/bootstrap3/templates/myresearch/editlist.phtml index 1bd67d0d147..971c6128f56 100644 --- a/themes/bootstrap3/templates/myresearch/editlist.phtml +++ b/themes/bootstrap3/templates/myresearch/editlist.phtml @@ -22,6 +22,13 @@ <label class="control-label" for="list_desc"><?=$this->transEsc('Description') ?></label> <textarea id="list_desc" class="form-control" name="desc" rows="3"><?=isset($this->list['description']) ? $this->escapeHtml($this->list['description']) : ''?></textarea> </div> + <?php if ($this->usertags()->getListMode() === 'enabled'): ?> + <div class="form-group"> + <label class="control-label" for="list_tags"><?=$this->transEsc('Tags') ?>:</label> + <input type="text" name="tags" id="list_tags" class="form-control" value="<?=$this->escapeHtmlAttr($this->listTags)?>"/> + <span class="help-block"><?=$this->transEsc("add_tag_note") ?></span> + </div> + <?php endif; ?> <?php if ($this->userlist()->getMode() === 'public_only'): ?> <input type="hidden" name="public" value="1" /> <?php elseif ($this->userlist()->getMode() === 'private_only'): ?> diff --git a/themes/bootstrap3/templates/myresearch/mylist.phtml b/themes/bootstrap3/templates/myresearch/mylist.phtml index c231b4e302b..e461674c88b 100644 --- a/themes/bootstrap3/templates/myresearch/mylist.phtml +++ b/themes/bootstrap3/templates/myresearch/mylist.phtml @@ -71,6 +71,9 @@ <?php if ($list && !empty($list->description)): ?> <p><?=$this->escapeHtml($list->description)?></p> <?php endif; ?> + <?php if (!empty($listTags)): ?> + <div><?=$this->transEsc('Tags')?>: <?=implode(', ', array_map([$this, 'escapeHtml'], $listTags))?></div> + <?php endif; ?> <?php if ($recordTotal > 0): ?> <form class="form-inline" method="post" name="bulkActionForm" action="<?=$this->url('cart-myresearchbulk')?>" data-lightbox data-lightbox-onsubmit="bulkFormHandler"> <?=$this->context($this)->renderInContext('myresearch/bulk-action-buttons.phtml', ['idPrefix' => '', 'list' => $list ?? null, 'account' => $this->account])?> -- GitLab