From e69394f6cdac5dcda9046d922f18f7b90bdc042c Mon Sep 17 00:00:00 2001 From: Dorian Merz <merz@ub.uni-leipzig.de> Date: Thu, 14 Nov 2019 10:30:04 +0100 Subject: [PATCH] refs #16050 [fid_bbi] user Tags * activates user list tags * translations for "Your Tags" * show all tags on favorites overview ** fixes bug inherited from bootstrap3 theme * show all tags for user in select list ** adapts VuFind-core DB query ** TODO: Is this a Bug? File a Pull Request --- fid_bbi/config/vufind/config.ini | 5 +- fid_bbi/languages/de.ini | 6 +- fid_bbi/languages/en.ini | 6 +- module/fid_bbi/config/module.config.php | 18 ++ module/fid_bbi/src/fid_bbi/Db/Table/Tags.php | 104 ++++++++ .../DefaultRecord/list-entry.phtml | 228 ++++++++++++++++++ 6 files changed, 364 insertions(+), 3 deletions(-) create mode 100644 module/fid_bbi/src/fid_bbi/Db/Table/Tags.php create mode 100644 themes/fid_bbi/templates/RecordDriver/DefaultRecord/list-entry.phtml diff --git a/fid_bbi/config/vufind/config.ini b/fid_bbi/config/vufind/config.ini index 7ccc05e0eb2..96774c7c958 100644 --- a/fid_bbi/config/vufind/config.ini +++ b/fid_bbi/config/vufind/config.ini @@ -118,4 +118,7 @@ sender_email = "noreply@hab.de" [Mail] ; enable search tools (send, export, ...) without login require_login = false -user_email_in_to = true \ No newline at end of file +user_email_in_to = true + +[Social] +tags = enabled \ No newline at end of file diff --git a/fid_bbi/languages/de.ini b/fid_bbi/languages/de.ini index 5784dacadb3..08599f5477d 100644 --- a/fid_bbi/languages/de.ini +++ b/fid_bbi/languages/de.ini @@ -438,4 +438,8 @@ report_errors_send_success = "Vielen Dank für Ihr Feedback." history_saved_searches = "Meine gespeicherten Suchen" #15969 -copied_link_to_clipboard = "Link in Zwischenablage kopiert" \ No newline at end of file +copied_link_to_clipboard = "Link in Zwischenablage kopiert" + +#16050 +add_tag_note = "Trennen Sie Tags mit einem Leerzeichen oder mit [ENTER]. Max. Länge eines Tags: 25 Zeichen." +Your Tags = Meine Tags \ No newline at end of file diff --git a/fid_bbi/languages/en.ini b/fid_bbi/languages/en.ini index f64e548a518..136c18cbbc6 100644 --- a/fid_bbi/languages/en.ini +++ b/fid_bbi/languages/en.ini @@ -431,4 +431,8 @@ Your Profile = "My Profile" history_saved_searches = "My Saved Searches" #15969 -copied_link_to_clipboard = "Copied Link to Clipboard" \ No newline at end of file +copied_link_to_clipboard = "Copied Link to Clipboard" + +#16050 +add_tag_note = "Use a whitespace character or press [ENTER] to separate tags. Maximum length of a tag is 25 characters." +Your Tags = My Tags \ No newline at end of file diff --git a/module/fid_bbi/config/module.config.php b/module/fid_bbi/config/module.config.php index 6f02bff9c41..f5197d56401 100644 --- a/module/fid_bbi/config/module.config.php +++ b/module/fid_bbi/config/module.config.php @@ -19,6 +19,11 @@ * @license http://opensource.org/licenses/gpl-2.0.php GNU GPLv2 */ +use VuFind\Db\Table\Tags as BaseTagsTable; +use fid_bbi\Db\Table\Tags as BBITagsTable; +use VuFind\Db\Row\Tags as BaseTagsRow; +use VuFind\Db\Table\GatewayFactory as TableGatewayFactory; + $config = [ 'forms' => require_once 'form.config.php', 'controllers' => [ @@ -64,6 +69,19 @@ $config = [ 'worldcat' => 'fid_bbi\RecordTab\Worldcat', ], ], + 'db_table' => [ + 'aliases' => [ + BaseTagsTable::class => BBITagsTable::class, + ], + 'factories' => [ + BBITagsTable::class => TableGatewayFactory::class, + ] + ], + 'db_row' => [ + 'aliases' => [ + 'fid_bbi\Db\Row\Tags' => BaseTagsRow::class, + ] + ] ], 'recorddriver_tabs' => [ 'finc\RecordDriver\SolrDefault' => [ diff --git a/module/fid_bbi/src/fid_bbi/Db/Table/Tags.php b/module/fid_bbi/src/fid_bbi/Db/Table/Tags.php new file mode 100644 index 00000000000..04199f1d938 --- /dev/null +++ b/module/fid_bbi/src/fid_bbi/Db/Table/Tags.php @@ -0,0 +1,104 @@ +<?php +/** + * Table Definition for tags + * + * 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 Db_Table + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link https://vufind.org Main Site + */ +namespace fid_bbi\Db\Table; + +use VuFind\Db\Table\Tags as BaseTags; +use Zend\Db\Sql\Expression; + +/** + * Table Definition for tags + * + * @category VuFind + * @package Db_Table + * @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 Tags extends BaseTags +{ + /** + * 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 getForUser($userId, $resourceId = null, $listId = null, + $source = null + ) { + $callback = function ($select) use ($userId, $resourceId, $listId, $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] + ) + ] + ); + $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', [] + ); + $select->group(['tag'])->order([new Expression('lower(tag)')]); + + $select->where->equalTo('ur.user_id', $userId) + ->equalTo('rt.user_id', $userId); + + if (null !== $source) { + $select->where->equalTo('r.source', $source); + } + + if (null !== $resourceId) { + $select->where->equalTo('r.record_id', $resourceId); + } + if (null !== $listId) { + $select->where->equalTo('rt.list_id', $listId); + } + }; + return $this->select($callback); + } +} diff --git a/themes/fid_bbi/templates/RecordDriver/DefaultRecord/list-entry.phtml b/themes/fid_bbi/templates/RecordDriver/DefaultRecord/list-entry.phtml new file mode 100644 index 00000000000..44822387e0c --- /dev/null +++ b/themes/fid_bbi/templates/RecordDriver/DefaultRecord/list-entry.phtml @@ -0,0 +1,228 @@ +<!-- fid_bbi: RecordDriver - DefaultRecord - list-entry --> +<?php /*copied from finc */?> +<?php +// Set up some convenience variables: +$id = $this->driver->getUniqueId(); +$source = $this->driver->getSourceIdentifier(); +if (isset($this->list) && is_object($this->list)) { + $list_id = $this->list->id; + $user_id = $this->list->user_id; +} else { + $list_id = null; + $user_id = $this->user ? $this->user->id : null; +} +// finc: next line finc-specific; required to display public favorites lists, #12052, see also below - CK +$isEditable = $this->user && $this->user->id === $user_id; +// Thumbnail +$coverDetails = $this->record($this->driver)->getCoverDetails('list-entry', 'medium', $this->recordLink()->getUrl($this->driver)); +$cover = $coverDetails['html']; +$thumbnail = false; +$thumbnailAlignment = $this->record($this->driver)->getThumbnailAlignment('list'); +if ($cover): + ob_start(); ?> + <div class="media-<?=$thumbnailAlignment?> <?=$this->escapeHtmlAttr($coverDetails['size'])?>"> + <?=$cover?> + </div> + <?php $thumbnail = ob_get_contents(); ?> + <?php ob_end_clean(); ?> +<?php endif; ?> +<div class="result<?php if ($this->driver->supportsAjaxStatus()): ?> ajaxItem<?php endif ?>"> + <input type="hidden" value="<?=$this->escapeHtmlAttr($id)?>" class="hiddenId"/> + <input type="hidden" value="<?=$this->escapeHtmlAttr($source)?>" class="hiddenSource"/> + <?=$this->record($this->driver)->getCheckbox()?> + <div class="media"> + <?php if ($thumbnail && $thumbnailAlignment == 'left'): ?> + <?=$thumbnail?> + <?php endif; ?> + <div class="media-body"> + <div class="result-body"> + <div class="resultItemLine1"> + <?php $missing = $this->driver instanceof \VuFind\RecordDriver\Missing; ?> + <?php if (!$missing): ?><a href="<?=$this->recordLink()->getUrl($this->driver)?>" class="getFull" data-view="<?=$this->params->getOptions()->getListViewOption()?>"><?php endif; ?> + <span class="title"><?=$this->record($this->driver)->getTitleHtml()?></span> + <?php if (!$missing): ?></a><?php endif; ?> + </div> + + <div class="resultItemLine2"> + <?php if ($this->driver->isCollection()): ?> + <?=implode('<br>', array_map(array($this, 'escapeHtml'), $this->driver->getSummary()));?> + <?php else: ?> + <?php $summAuthors = $this->driver->getPrimaryAuthors(); + if (!empty($summAuthors)): ?> + <?=$this->transEsc('by')?> + <?php $authorCount = count($summAuthors); + foreach ($summAuthors as $i => $summAuthor): ?> + <a href="<?=$this->record($this->driver)->getLink('author', $summAuthor)?>"><?=$this->escapeHtml($summAuthor)?></a><?=($i + 1 < $authorCount ? ';' : '')?> + <?php endforeach; ?> + <?php endif; ?> + + <?php $journalTitle = $this->driver->getContainerTitle(); + $summDate = $this->driver->getPublicationDates(); ?> + <?php if (!empty($journalTitle)): ?> + <?=!empty($summAuthor) ? '<br/>' : ''?> + <?=/* TODO: handle highlighting more elegantly here */ + $this->transEsc('Published in') . ' <a href="' . $this->record($this->driver)->getLink('journaltitle', str_replace(array('{{{{START_HILITE}}}}', '{{{{END_HILITE}}}}'), '', $journalTitle)) . '">' . $this->highlight($journalTitle) . '</a>';?> + <?=!empty($summDate) ? ' (' . $this->escapeHtml($summDate[0]) . ')' : ''?> + <?php elseif (!empty($summDate)): ?> + <?=!empty($summAuthor) ? '<br/>' : ''?> + <?=$this->transEsc('Published') . ' ' . $this->escapeHtml($summDate[0])?> + <?php endif; ?> + <?php $summInCollection = $this->driver->getContainingCollections(); + if (false && !empty($summInCollection)): ?> + <?php foreach ($summInCollection as $collId => $collText): ?> + <div> + <b><?=$this->transEsc("in_collection_label")?></b> + <a class="collectionLinkText" href="<?=$this->url('collection', array('id' => $collId))?>?recordID=<?=urlencode($this->driver->getUniqueID())?>"> + <?=$this->escapeHtml($collText)?> + </a> + </div> + <?php endforeach; ?> + <?php endif; ?> + <?php endif; ?> + </div> + + <div class="last"> + <?php if (!$this->driver->isCollection()) { + if ($snippet = $this->driver->getHighlightedSnippet()) { + if (!empty($snippet['caption'])) { + echo '<strong>' . $this->transEsc($snippet['caption']) . ':</strong> '; + } + if (!empty($snippet['snippet'])) { + echo '<span class="quotestart">“</span>...' . $this->highlight($snippet['snippet']) . '...<span class="quoteend">”</span><br/>'; + } + } + } ?> + + <?php /*fid_bbi #16050*/ + $listTags = ($this->usertags()->getMode() !== 'disabled') ? $this->driver->getTags( + $list_id, $user_id, 'tag',$user_id + ) : array(); + ?> + + <?php $listNotes = $this->driver->getListNotes($list_id, $user_id); ?> + <?php if (count($listNotes) > 0): ?> + <strong><?=$this->transEsc('Notes')?>:</strong> + <?php if (count($listNotes) > 1): ?><br/><?php endif; ?> + <?php foreach ($listNotes as $note): ?> + <?=$this->escapeHtml($note)?><br/> + <?php endforeach; ?> + <?php endif; ?> + + <?php if (count($this->lists) > 0): ?> + <strong><?=$this->transEsc('Saved in')?>:</strong> + <?php $i = 0; + foreach ($this->lists as $current): ?> + <a href="<?=$this->url('userList', array('id' => $current->id))?>"><?=$this->escapeHtml($current->title)?></a><?php if ($i++ < count($this->lists) - 1): ?>,<?php endif; ?> + <?php endforeach; ?> + <br/> + <?php endif; ?> + + <div class="callnumAndLocation ajax-availability hidden"> + <?php if ($this->driver->supportsAjaxStatus()): ?> + <strong class="hideIfDetailed"><?=$this->transEsc('Call Number')?>:</strong> + <span class="callnumber ajax-availability hidden"> + <?=$this->transEsc('Loading')?>...<br/> + </span> + <strong><?=$this->transEsc('Located')?>:</strong> + <span class="location ajax-availability hidden"> + <?=$this->transEsc('Loading')?>... + </span> + <div class="locationDetails"></div> + <?php else: ?> + <?php $summCallNo = $this->driver->getCallNumber(); + if (!empty($summCallNo)): ?> + <strong><?=$this->transEsc('Call Number')?>:</strong> <?=$this->escapeHtml($summCallNo)?> + <?php endif; ?> + <?php endif; ?> + </div> + + <?php /* We need to find out if we're supposed to display an OpenURL link ($openUrlActive), + but even if we don't plan to display the link, we still want to get the $openUrl + value for use in generating a COinS (Z3988) tag -- see bottom of file. + */ + $openUrl = $this->openUrl($this->driver, 'results'); + $openUrlActive = $openUrl->isActive(); + $doi = $this->doi($this->driver, 'results'); + $doiActive = $doi->isActive(); + // Account for replace_other_urls setting + $urls = $this->record($this->driver)->getLinkDetails($openUrlActive); + + if ($openUrlActive || $doiActive || !empty($urls)): + ?> + <?php if ($openUrlActive): ?> + <br/> + <?=$openUrl->renderTemplate()?> + <?php endif; ?> + + <?php if ($doiActive): ?> + <br/> + <?=$doi->renderTemplate()?> + <?php endif; ?> + + <?php if (!is_array($urls)) { + $urls = []; + } + if (!$this->driver->isCollection()): + foreach ($urls as $current): ?> + <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>" class="fulltext" target="new"><i class="fa fa-external-link" + aria-hidden="true"></i> <?=($current['url'] == $current['desc']) ? $this->transEsc('Get full text') : $this->escapeHtml($current['desc'])?> + </a> + <?php endforeach; ?> + <?php endif; ?> + <?php endif; ?> + <br/> + + <?=$this->record($this->driver)->getFormatList()?> + + <?php if (!$openUrlActive && empty($urls) && $this->driver->supportsAjaxStatus()): ?> + <span class="status ajax-availability hidden"><?=$this->transEsc('Loading')?>...</span> + <br/><br/> + <?php endif; ?> + <?=$this->record($this->driver)->getPreviews()?> + </div> + </div> + + <div class="result-links hidden-print"> + <?php /* finc: next line finc-specific; required to display public favorites lists, #12052, see also above - CK */ ?> + <?php if ($isEditable): ?> + <i class="fa fa-fw fa-edit" aria-hidden="true"></i> <a + href="<?=$this->url('myresearch-edit')?>?id=<?=urlencode($id)?>&source=<?=urlencode($source)?><?php if (null !== $list_id): ?>&list_id=<?=urlencode($list_id)?><?php endif; ?>" + class="edit tool"><?=$this->transEsc('Edit')?></a><br/> + <?php /* Use a different delete URL if we're removing from a specific list or the overall favorites: */ + $deleteUrl = null === $list_id + ? $this->url('myresearch-favorites') + : $this->url('userList', ['id' => $list_id]); + $deleteUrlGet = $deleteUrl . '?delete=' . urlencode($id) . '&source=' . urlencode($source); + + $dLabel = 'delete-label-' . preg_replace('[\W]', '-', $id); + ?> + <div class="dropdown"> + <i class="fa fa-fw fa-trash-o" aria-hidden="true"></i> <a class="dropdown-toggle" id="<?=$dLabel?>" role="button" data-toggle="dropdown" href="<?=$deleteUrlGet?>"> + <?=$this->transEsc('Delete')?> + </a> + <ul class="dropdown-menu" role="menu" aria-labelledby="<?=$dLabel?>"> + <li><a onClick="$.post('<?=$deleteUrl?>', {'delete':'<?=$this->escapeJs($id)?>','source':'<?=$this->escapeJs($source)?>','confirm':true},function(){location.reload(true)})" + title="<?=$this->transEsc('confirm_delete_brief')?>"><?=$this->transEsc('confirm_dialog_yes')?></a></li> + <li><a><?=$this->transEsc('confirm_dialog_no')?></a></li> + </ul> + </div> + + <?=$this->driver->supportsCoinsOpenUrl() ? '<span class="Z3988" title="' . $this->escapeHtmlAttr($this->driver->getCoinsOpenUrl()) . '"></span>' : ''?> + <?php endif; ?> + </div> + </div> + + <?php /*fid_bbi #16050*/ if (!empty($listTags)): ?> + <strong><?=$this->transEsc('Your Tags')?>:</strong> + <?php foreach ($listTags as $tag): ?> + <a href="<?=$this->currentPath() . $results->getUrlQuery()->addFacet('tags', $tag->tag)?>"><?=$this->escapeHtml($tag->tag)?></a> + <?php endforeach; ?> + <br/> + <?php endif; ?> + + <?php if ($thumbnail && $thumbnailAlignment == 'right'): ?> + <?=$thumbnail?> + <?php endif; ?> + </div> +</div> +<!-- fid_bbi: RecordDriver - DefaultRecord - list-entry - END --> \ No newline at end of file -- GitLab