From ad7167b979342bdb5d8be64c4f86f83c42ef508d Mon Sep 17 00:00:00 2001 From: Demian Katz <demian.katz@villanova.edu> Date: Tue, 17 Jul 2012 14:59:02 -0400 Subject: [PATCH] Added tag filtering to favorites. --- module/VuFind/src/VuFind/Db/Table/Gateway.php | 13 +- .../VuFind/src/VuFind/Db/Table/Resource.php | 23 +- .../src/VuFind/Db/Table/ResourceTags.php | 247 ++++++++++++++++++ 3 files changed, 265 insertions(+), 18 deletions(-) create mode 100644 module/VuFind/src/VuFind/Db/Table/ResourceTags.php diff --git a/module/VuFind/src/VuFind/Db/Table/Gateway.php b/module/VuFind/src/VuFind/Db/Table/Gateway.php index 57797f482de..6625cbe199b 100644 --- a/module/VuFind/src/VuFind/Db/Table/Gateway.php +++ b/module/VuFind/src/VuFind/Db/Table/Gateway.php @@ -45,16 +45,19 @@ class Gateway extends AbstractTableGateway * Constructor * * @param string $table Name of database table to interface with - * @param string $rowClass Name of class used to represent rows + * @param string $rowClass Name of class used to represent rows (null for + * default) */ - public function __construct($table, $rowClass) + public function __construct($table, $rowClass = null) { $this->table = $table; $this->featureSet = new FeatureSet(); $this->featureSet->addFeature(new GlobalAdapterFeature()); $this->initialize(); - $resultSetPrototype = $this->getResultSetPrototype(); - $resultSetPrototype - ->setArrayObjectPrototype(new $rowClass($this->getAdapter())); + if (!is_null($rowClass)) { + $resultSetPrototype = $this->getResultSetPrototype(); + $resultSetPrototype + ->setArrayObjectPrototype(new $rowClass($this->getAdapter())); + } } } diff --git a/module/VuFind/src/VuFind/Db/Table/Resource.php b/module/VuFind/src/VuFind/Db/Table/Resource.php index f525025388f..02ba8d6a898 100644 --- a/module/VuFind/src/VuFind/Db/Table/Resource.php +++ b/module/VuFind/src/VuFind/Db/Table/Resource.php @@ -167,21 +167,18 @@ class Resource extends Gateway // Adjust for tags if necessary: if (!empty($tags)) { - /* TODO: + $linkingTable = new ResourceTags(); foreach ($tags as $tag) { - $subSelect = $this->select(); - $subSelect->setIntegrityCheck(false) - ->distinct() - ->from(array('rt' => 'resource_tags'), 'rt.resource_id') - ->join(array('t' => 'tags'), 'rt.tag_id = t.id', array()) - ->where('t.tag = ?', $tag) - ->where('rt.user_id = ?', $userId); - if (!is_null($listId)) { - $subSelect->where('rt.list_id = ?', $listId); - } - $select->where('r.id in ?', $subSelect); + $matches + = $linkingTable->getResourcesForTag($tag, $userId, $listId); + $select->where->in( + 'resource.id', + array_map( + function ($i) { return $i['resource_id']; }, + $matches->toArray() + ) + ); } - */ } // Apply sorting, if necessary: diff --git a/module/VuFind/src/VuFind/Db/Table/ResourceTags.php b/module/VuFind/src/VuFind/Db/Table/ResourceTags.php new file mode 100644 index 00000000000..c61897b65ad --- /dev/null +++ b/module/VuFind/src/VuFind/Db/Table/ResourceTags.php @@ -0,0 +1,247 @@ +<?php +/** + * Table Definition for resource_tags + * + * PHP version 5 + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * @category VuFind2 + * @package DB_Models + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org Main Site + */ +namespace VuFind\Db\Table; +use Zend\Db\Sql\Expression; + +/** + * Table Definition for resource_tags + * + * @category VuFind2 + * @package DB_Models + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org Main Site + */ +class ResourceTags extends Gateway +{ + /** + * Constructor + */ + public function __construct() + { + parent::__construct('resource_tags', 'VuFind\Db\Row\Resource'); + } + + /** + * Look up a row for the specified resource. + * + * @param string $resource_id ID of resource to link up + * @param string $tag_id ID of tag to link up + * @param string $user_id ID of user creating link (optional but recommended) + * @param string $list_id ID of list to link up (optional) + * + * @return void + */ + public function createLink($resource_id, $tag_id, $user_id = null, + $list_id = null + ) { + /* TODO + $select = $this->select(); + $select->where('resource_id = ?', $resource_id) + ->where('tag_id = ?', $tag_id); + if (!is_null($list_id)) { + $select->where('list_id = ?', $list_id); + } else { + $select->where('list_id is null'); + } + if (!is_null($user_id)) { + $select->where('user_id = ?', $user_id); + } else { + $select->where('user_id is null'); + } + $result = $this->fetchRow($select); + + // Only create row if it does not already exist: + if (is_null($result)) { + $result = $this->createRow(); + $result->resource_id = $resource_id; + $result->tag_id = $tag_id; + if (!is_null($list_id)) { + $result->list_id = $list_id; + } + if (!is_null($user_id)) { + $result->user_id = $user_id; + } + $result->save(); + } + */ + } + + /** + * Check whether or not the specified tags are present in the table. + * + * @param array $ids IDs to check. + * + * @return array Associative array with two keys: present and missing + */ + public function checkForTags($ids) + { + /* TODO + // Set up return arrays: + $retVal = array('present' => array(), 'missing' => array()); + + // Look up IDs in the table: + $select = $this->select()->distinct()->from($this->_name, 'tag_id'); + foreach ($ids as $current) { + $select->orWhere('tag_id = ?', $current); + } + $results = $this->fetchAll($select); + + // Record all IDs that are present: + foreach ($results as $current) { + $retVal['present'][] = $current->tag_id; + } + + // Detect missing IDs: + foreach ($ids as $current) { + if (!in_array($current, $retVal['present'])) { + $retVal['missing'][] = $current; + } + } + + // Send back the results: + return $retVal; + */ + } + + /** + * Get resources associated with a particular tag. + * + * @param string $tag Tag to match + * @param string $userId ID of user owning favorite list + * @param string $listId ID of list to retrieve (null for all favorites) + * + * @return Zend_Db_Table_Rowset + */ + public function getResourcesForTag($tag, $userId, $listId = null) + { + $callback = function ($select) use ($tag, $userId, $listId) { + $select->columns( + array( + 'resource_id' => new Expression( + 'DISTINCT(?)', array('resource_tags.resource_id'), + array(Expression::TYPE_IDENTIFIER) + ) + ) + ); + $select->join( + array('t' => 'tags'), 'resource_tags.tag_id = t.id', array() + ); + $select->where->equalTo('t.tag', $tag) + ->where->equalTo('resource_tags.user_id', $userId); + if (!is_null($listId)) { + $select->where->equalTo('resource_tags.list_id', $listId); + } + }; + + return $this->select($callback); + } + + /** + * Unlink rows for the specified resource. + * + * @param string|array $resource_id ID (or array of IDs) of resource(s) to + * unlink (null for ALL matching resources) + * @param string $user_id ID of user removing links + * @param string $list_id ID of list to unlink (null for ALL matching + * lists, 'none' for tags not in a list) + * @param string $tag_id ID of tag to unlink (null for ALL matching + * tags) + * + * @return void + */ + public function destroyLinks($resource_id, $user_id, $list_id = null, + $tag_id = null + ) { + /* TODO + $db = $this->getAdapter(); + + $where = $db->quoteInto('user_id = ?', $user_id); + + if (!is_null($resource_id)) { + if (is_array($resource_id)) { + $resourceSQL = array(); + foreach ($resource_id as $current) { + $resourceSQL[] = $db->quoteInto('resource_id = ?', $current); + } + $where .= ' AND (' . implode(' OR ', $resourceSQL) . ')'; + } else { + $where .= $db->quoteInto(' AND resource_id = ?', $resource_id); + } + } + if (!is_null($list_id)) { + if ($list_id != 'none') { + $where .= $db->quoteInto(' AND list_id = ?', $list_id); + } else { + // special case -- if $list_id is set to the string "none", we + // want to delete tags that are not associated with lists. + $where .= ' AND list_id is null'; + } + } + if (!is_null($tag_id)) { + $where .= $db->quoteInto(' AND tag_id = ?', $tag_id); + } + + // Get a list of all tag IDs being deleted; we'll use these for + // orphan-checking: + $select = $this->select()->distinct()->from($this->_name, 'tag_id') + ->where($where); + $potentialOrphans = $this->fetchAll($select); + + // Now delete the unwanted rows: + $this->delete($where); + + // Check for orphans: + if (count($potentialOrphans) > 0) { + $ids = array(); + foreach ($potentialOrphans as $current) { + $ids[] = $current->tag_id; + } + $checkResults = $this->checkForTags($ids); + if (count($checkResults['missing']) > 0) { + $tagTable = new VuFind_Model_Db_Tags(); + $tagTable->deleteByIdArray($checkResults['missing']); + } + } + */ + } + + /** + * Assign anonymous tags to the specified user ID. + * + * @param int $id User ID to own anonymous tags. + * + * @return void + */ + public function assignAnonymousTags($id) + { + /* TODO + $this->update(array('user_id' => $id), 'user_id IS NULL'); + */ + } +} -- GitLab