From e83452e4a5f8b9a3eeb851095f28a73272650a7b Mon Sep 17 00:00:00 2001 From: Demian Katz <demian.katz@villanova.edu> Date: Tue, 6 Nov 2012 13:26:57 -0500 Subject: [PATCH] Began work on collection module -- basic hierarchy display is now functional. --- config/vufind/HierarchyDefault.ini | 17 ++ config/vufind/HierarchyFlat.ini | 17 ++ config/vufind/config.ini | 10 +- module/VuFind/config/module.config.php | 33 ++- module/VuFind/src/VuFind/Bootstrap.php | 7 +- .../VuFind/Hierarchy/Driver/AbstractBase.php | 172 +++++++++++++++ .../Hierarchy/Driver/ConfigurationBased.php | 127 +++++++++++ .../src/VuFind/Hierarchy/Driver/Factory.php | 73 +++++++ .../VuFind/Hierarchy/Driver/PluginManager.php | 51 +++++ .../Hierarchy/TreeDataSource/AbstractBase.php | 131 +++++++++++ .../TreeDataSource/PluginManager.php | 51 +++++ .../VuFind/Hierarchy/TreeDataSource/Solr.php | 204 ++++++++++++++++++ .../Hierarchy/TreeDataSource/XMLFile.php | 100 +++++++++ .../Hierarchy/TreeRenderer/AbstractBase.php | 147 +++++++++++++ .../VuFind/Hierarchy/TreeRenderer/JSTree.php | 183 ++++++++++++++++ .../Hierarchy/TreeRenderer/PluginManager.php | 51 +++++ .../src/VuFind/RecordDriver/PluginManager.php | 16 ++ .../src/VuFind/RecordDriver/SolrDefault.php | 107 +++++++++ .../src/VuFind/RecordTab/HierarchyTree.php | 126 +++++++++++ module/VuFind/xsl/Hierarchy/RecordList.xsl | 30 +++ solr/biblio/conf/schema.xml | 9 + themes/blueprint/css/styles.css | 10 +- .../SolrDefault/result-list.phtml | 11 + .../templates/RecordTab/hierarchytree.phtml | 22 ++ .../templates/RecordTab/hierarchytree.phtml | 22 ++ 25 files changed, 1720 insertions(+), 7 deletions(-) create mode 100644 config/vufind/HierarchyDefault.ini create mode 100644 config/vufind/HierarchyFlat.ini create mode 100644 module/VuFind/src/VuFind/Hierarchy/Driver/AbstractBase.php create mode 100644 module/VuFind/src/VuFind/Hierarchy/Driver/ConfigurationBased.php create mode 100644 module/VuFind/src/VuFind/Hierarchy/Driver/Factory.php create mode 100644 module/VuFind/src/VuFind/Hierarchy/Driver/PluginManager.php create mode 100644 module/VuFind/src/VuFind/Hierarchy/TreeDataSource/AbstractBase.php create mode 100644 module/VuFind/src/VuFind/Hierarchy/TreeDataSource/PluginManager.php create mode 100644 module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php create mode 100644 module/VuFind/src/VuFind/Hierarchy/TreeDataSource/XMLFile.php create mode 100644 module/VuFind/src/VuFind/Hierarchy/TreeRenderer/AbstractBase.php create mode 100644 module/VuFind/src/VuFind/Hierarchy/TreeRenderer/JSTree.php create mode 100644 module/VuFind/src/VuFind/Hierarchy/TreeRenderer/PluginManager.php create mode 100644 module/VuFind/src/VuFind/RecordTab/HierarchyTree.php create mode 100644 module/VuFind/xsl/Hierarchy/RecordList.xsl create mode 100644 themes/blueprint/templates/RecordTab/hierarchytree.phtml create mode 100644 themes/jquerymobile/templates/RecordTab/hierarchytree.phtml diff --git a/config/vufind/HierarchyDefault.ini b/config/vufind/HierarchyDefault.ini new file mode 100644 index 00000000000..833131f7c55 --- /dev/null +++ b/config/vufind/HierarchyDefault.ini @@ -0,0 +1,17 @@ +[HierarchyTree] +; Are hierarchy trees visible? -- true or false (default false) +show = true +; The source of the hierarchy data -- may be Solr or XMLFile +treeSource = Solr +; When using Solr as a treeSource, this value determines how long tree data is +; cached (in seconds) -- default 12h +solrCacheTime = 43200 +; When using XMLFile as a treeSource, this value specifies where tree data is found +;XMLFileDir = /usr/local/vufind/hierarchy_xml +; Sorting requires the hierarchy_sequence field to be populated; defaults to false +sorting = true +; Which Tree Renderer to Use - Default is JSTree +;treeRenderer = JSTree +; Control whether or not to display the full hierarchy tree in record mode +; (true = show full hierarchy, false = show partial hierarchy, default = true) +fullHierarchyRecordView = true diff --git a/config/vufind/HierarchyFlat.ini b/config/vufind/HierarchyFlat.ini new file mode 100644 index 00000000000..e7696bcc02a --- /dev/null +++ b/config/vufind/HierarchyFlat.ini @@ -0,0 +1,17 @@ +[HierarchyTree] +; Are hierarchy trees visible? -- true or false (default false) +show = false +; The source of the hierarchy data -- may be Solr or XMLFile +;treeSource = Solr +; When using Solr as a treeSource, this value determines how long tree data is +; cached (in seconds) -- default 12h +;solrCacheTime = 0 +; When using XMLFile as a treeSource, this value specifies where tree data is found +;XMLFileDir = /usr/local/vufind/hierarchy_xml +; Sorting requires the hierarchy_sequence field to be populated; defaults to false +;sorting = true +; Which Tree Renderer to Use - Default is JSTree +;treeRenderer = JSTree +; Control whether or not to display the full hierarchy tree in record mode +; (true = show full hierarchy, false = show partial hierarchy, default = true) +fullHierarchyRecordView = true diff --git a/config/vufind/config.ini b/config/vufind/config.ini index 500568f5362..daa6b4d77ae 100644 --- a/config/vufind/config.ini +++ b/config/vufind/config.ini @@ -767,4 +767,12 @@ HMACkey = mySuperSecretValue ; Default dir_permission seems to be 0700. ;dir_permission = 0700 ; Default file_permission seems to be 0600. -;file_permission = 0600 \ No newline at end of file +;file_permission = 0600 + +; This section addresses hierarchical records in the Solr index +[Hierarchy] +; Name of hierarchy driver to use if no value is specified in the hierarchytype +; field of the Solr index. +driver = Default +; Should we display hierarchy trees? (default = false) +;showTree = true \ No newline at end of file diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php index 267aae7b9b1..39ea5c2c216 100644 --- a/module/VuFind/config/module.config.php +++ b/module/VuFind/config/module.config.php @@ -174,6 +174,34 @@ $config = array( 'userstatsfields' => 'VuFind\Db\Table\UserStatsFields', ), ), + 'hierarchy_driver_plugin_manager' => array( + 'factories' => array( + 'default' => function ($sm) { + return \VuFind\Hierarchy\Driver\Factory::get($sm->getServiceLocator(), 'HierarchyDefault'); + }, + 'flat' => function ($sm) { + return \VuFind\Hierarchy\Driver\Factory::get($sm->getServiceLocator(), 'HierarchyFlat'); + }, + ) + ), + 'hierarchy_treedatasource_plugin_manager' => array( + 'factories' => array( + 'solr' => function ($sm) { + $cacheDir = $sm->getServiceLocator()->get('VuFind\CacheManager')->getCacheDir(); + return new \VuFind\Hierarchy\TreeDataSource\Solr( + rtrim($cacheDir, '/') . '/hierarchy' + ); + }, + ), + 'invokables' => array( + 'xmlfile' => 'VuFind\Hierarchy\TreeDataSource\XMLFile', + ), + ), + 'hierarchy_treerenderer_plugin_manager' => array( + 'invokables' => array( + 'jstree' => 'VuFind\Hierarchy\TreeRenderer\JSTree', + ) + ), 'ils_driver_plugin_manager' => array( 'abstract_factories' => array('VuFind\ILS\Driver\PluginFactory'), 'invokables' => array( @@ -256,13 +284,13 @@ $config = array( 'Holdings' => 'HoldingsILS', 'Description' => 'Description', 'TOC' => 'TOC', 'UserComments' => 'UserComments', 'Reviews' => 'Reviews', 'Excerpt' => 'Excerpt', - 'Details' => 'StaffViewArray', + 'HierarchyTree' => 'HierarchyTree', 'Details' => 'StaffViewArray', ), 'VuFind\RecordDriver\SolrMarc' => array( 'Holdings' => 'HoldingsILS', 'Description' => 'Description', 'TOC' => 'TOC', 'UserComments' => 'UserComments', 'Reviews' => 'Reviews', 'Excerpt' => 'Excerpt', - 'Details' => 'StaffViewMARC', + 'HierarchyTree' => 'HierarchyTree', 'Details' => 'StaffViewMARC', ), 'VuFind\RecordDriver\Summon' => array( 'Description' => 'Description', @@ -282,6 +310,7 @@ $config = array( 'invokables' => array( 'description' => 'VuFind\RecordTab\Description', 'excerpt' => 'VuFind\RecordTab\Excerpt', + 'hierarchytree' => 'VuFind\RecordTab\HierarchyTree', 'holdingsils' => 'VuFind\RecordTab\HoldingsILS', 'holdingsworldcat' => 'VuFind\RecordTab\HoldingsWorldCat', 'reviews' => 'VuFind\RecordTab\Reviews', diff --git a/module/VuFind/src/VuFind/Bootstrap.php b/module/VuFind/src/VuFind/Bootstrap.php index 2af408df0f1..95499d83776 100644 --- a/module/VuFind/src/VuFind/Bootstrap.php +++ b/module/VuFind/src/VuFind/Bootstrap.php @@ -88,9 +88,10 @@ class Bootstrap // Use naming conventions to set up a bunch of services based on namespace: $namespaces = array( - 'Auth', 'Autocomplete', 'Db\Table', 'ILS\Driver', 'Recommend', - 'RecordDriver', 'RecordTab', 'Related', 'Resolver\Driver', 'Session', - 'Statistics\Driver' + 'Auth', 'Autocomplete', 'Db\Table', 'Hierarchy\Driver', + 'Hierarchy\TreeDataSource', 'Hierarchy\TreeRenderer', 'ILS\Driver', + 'Recommend', 'RecordDriver', 'RecordTab', 'Related', 'Resolver\Driver', + 'Session', 'Statistics\Driver' ); foreach ($namespaces as $ns) { $serviceName = 'VuFind\\' . str_replace('\\', '', $ns) . 'PluginManager'; diff --git a/module/VuFind/src/VuFind/Hierarchy/Driver/AbstractBase.php b/module/VuFind/src/VuFind/Hierarchy/Driver/AbstractBase.php new file mode 100644 index 00000000000..353f1d32ae3 --- /dev/null +++ b/module/VuFind/src/VuFind/Hierarchy/Driver/AbstractBase.php @@ -0,0 +1,172 @@ +<?php +/** + * Hierarchy interface. + * + * 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 Hierarchy + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_a_search_object Wiki + */ +namespace VuFind\Hierarchy\Driver; +use VuFind\Hierarchy\TreeDataSource\PluginManager as DataManager, + VuFind\Hierarchy\TreeRenderer\PluginManager as RendererManager; + +/** + * Hierarchy interface class. + * + * Interface Hierarchy based drivers. + * This should be extended to implement functionality for specific + * Hierarchy Systems (i.e. Calm etc.). + * + * @category VuFind2 + * @package Hierarchy + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_a_search_object Wiki + */ +abstract class AbstractBase +{ + /** + * Driver configuration + * + * @var \Zend\Config\Config + */ + protected $config; + + /** + * Tree data source plugin manager + * + * @var DataManager + */ + protected $dataManager; + + /** + * Are trees globally enabled? + * + * @var bool + */ + protected $enabled = true; + + /** + * Tree renderer plugin manager + * + * @var RendererManager + */ + protected $rendererManager; + + /** + * Find out whether or not to show the tree + * + * @return bool + */ + abstract public function showTree(); + + /** + * Constructor + * + * @param \Zend\Config\Config $config Configuration + * @param DataManager $dataManager Tree data source plugin manager + * @param RendererManager $rendererManager Tree renderer plugin manager + * @param array $options Extra options (if any) + */ + public function __construct(\Zend\Config\Config $config, + DataManager $dataManager, RendererManager $rendererManager, + $options = array() + ) { + $this->config = $config; + $this->dataManager = $dataManager; + $this->rendererManager = $rendererManager; + if (isset($options['enabled'])) { + $this->enabled = (bool) $options['enabled']; + } + } + + /** + * Returns the Source of the Tree + * + * @return object The tree data source object + */ + public function getTreeSource() + { + $source = $this->dataManager->get($this->getTreeSourceType()); + $source->setHierarchyDriver($this); + return $source; + } + + /** + * Returns the actual object for generating trees + * + * @param \VuFind\RecordDriver\AbstractBase $driver Record driver + * + * @return object + */ + public function getTreeRenderer(\VuFind\RecordDriver\AbstractBase $driver) + { + $renderer = $this->rendererManager->get($this->getTreeRendererType()); + $renderer->setRecordDriver($driver); + return $renderer; + } + + /** + * Render the tree for a given record. + * + * @param \VuFind\RecordDriver\AbstractBase $driver Record driver + * @param string $context Context in which the + * tree is being created + * @param string $mode Type of tree required + * @param string $hierarchyID Hierarchy ID to get + * the tree for + * + * @return string + */ + public function render(\VuFind\RecordDriver\AbstractBase $driver, $context, + $mode, $hierarchyID + ) { + if (!$this->showTree()) { + return false; + } + return $this->getTreeRenderer($driver) + ->render($context, $mode, $hierarchyID, $driver->getUniqueID()); + } + + /** + * Returns the Tree Renderer Type + * + * @return string + */ + abstract public function getTreeRendererType(); + + /** + * Get Tree Settings + * + * Returns all the configuration settings for a hierarchy tree + * + * @return array The values of the configuration setting + */ + abstract public function getTreeSettings(); + + /** + * Get Tree Data Source Type + * + * @return string + */ + abstract public function getTreeSourceType(); +} \ No newline at end of file diff --git a/module/VuFind/src/VuFind/Hierarchy/Driver/ConfigurationBased.php b/module/VuFind/src/VuFind/Hierarchy/Driver/ConfigurationBased.php new file mode 100644 index 00000000000..b7020e52a01 --- /dev/null +++ b/module/VuFind/src/VuFind/Hierarchy/Driver/ConfigurationBased.php @@ -0,0 +1,127 @@ +<?php +/** + * Configuration-Based Hierarchy Driver + * + * PHP version 5 + * + * Copyright (C) Villanova University 2007. + * + * 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 Hierarchy_Drivers + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_an_ils_driver Wiki + */ +namespace VuFind\Hierarchy\Driver; + +/** + * Configuration-Based Hierarchy Driver + * + * @category VuFind2 + * @package Hierarchy_Drivers + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_an_ils_driver Wiki + */ +class ConfigurationBased extends AbstractBase +{ + /** + * Default tree renderer + * + * @var string + */ + protected $defaultTreeRenderer = 'JSTree'; + + /** + * Show Tree + * + * Returns the configuration setting for displaying a hierarchy tree + * + * @return bool The boolean value of the configuration setting + */ + public function showTree() + { + $treeConfigDriver = isset($this->config->HierarchyTree->show) + ? $this->config->HierarchyTree->show : false; + return ($this->enabled && $treeConfigDriver); + } + + /** + * Get Tree Renderer Type + * + * Returns the configuration setting for generating a hierarchy tree + * + * @return string The value of the configuration setting + */ + public function getTreeRendererType() + { + return isset($this->config->HierarchyTree->treeRenderer) + ? $this->config->HierarchyTree->treeRenderer + : $this->defaultTreeRenderer; + } + + /** + * Get Tree Data Source Type + * + * @return string + */ + public function getTreeSourceType() + { + return isset($this->config->HierarchyTree->treeSource) + ? $this->config->HierarchyTree->treeSource + : 'Solr'; + } + + /** + * Get Tree Cache Time + * + * Returns the configuration setting for hierarchy tree caching time when + * using solr to build the tree + * + * @return int The value of the configuration setting + */ + public function getTreeCacheTime() + { + return isset($this->config->HierarchyTree->solrCacheTime) + ? $this->config->HierarchyTree->solrCacheTime : 43200; + } + + /** + * Check if sorting is enabled in the hierarchy Options + * + * Returns the configuration setting for hierarchy tree sorting + * + * @return bool The value of the configuration setting + */ + public function treeSorting() + { + return isset($this->config->HierarchyTree->sorting) + ? $this->config->HierarchyTree->sorting : false; + } + + /** + * Get Tree Settings + * + * Returns all the configuration settings for a hierarchy tree + * + * @return array The values of the configuration setting + */ + public function getTreeSettings() + { + return isset($this->config->HierarchyTree) + ? $this->config->HierarchyTree->toArray() : array(); + } +} \ No newline at end of file diff --git a/module/VuFind/src/VuFind/Hierarchy/Driver/Factory.php b/module/VuFind/src/VuFind/Hierarchy/Driver/Factory.php new file mode 100644 index 00000000000..9cf273e8747 --- /dev/null +++ b/module/VuFind/src/VuFind/Hierarchy/Driver/Factory.php @@ -0,0 +1,73 @@ +<?php +/** + * Hierarchy Factory Class + * + * 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 Hierarchy_Drivers + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_a_search_object Wiki + */ +namespace VuFind\Hierarchy\Driver; + +/** + * Hierarchy Factory Class + * + * This is a factory class to build objects for managing hierarchies. + * + * @category VuFind2 + * @package Hierarchy_Drivers + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_a_search_object Wiki + */ +class Factory +{ + /** + * This constructs a hierarchy driver using VuFind's service setup. + * + * @param \Zend\ServiceManager\ServiceManager $sm Service manager + * @param string $config Name of config to load + * @param string $class Name of driver class + * + * @return object + */ + public static function get(\Zend\ServiceManager\ServiceManager $sm, $config, + $class = 'VuFind\Hierarchy\Driver\ConfigurationBased' + ) { + // Set up options based on global VuFind settings: + $globalConfig = \VuFind\Config\Reader::getConfig(); + $options = array( + 'enabled' => isset($globalConfig->Hierarchy->showTree) + ? $globalConfig->Hierarchy->showTree : false + ); + + // Load driver-specific configuration: + $driverConfig = \VuFind\Config\Reader::getConfig($config); + + // Build object: + return new $class( + $driverConfig, + $sm->get('VuFind\HierarchyTreeDataSourcePluginManager'), + $sm->get('VuFind\HierarchyTreeRendererPluginManager'), + $options + ); + } +} \ No newline at end of file diff --git a/module/VuFind/src/VuFind/Hierarchy/Driver/PluginManager.php b/module/VuFind/src/VuFind/Hierarchy/Driver/PluginManager.php new file mode 100644 index 00000000000..5dfda51ca92 --- /dev/null +++ b/module/VuFind/src/VuFind/Hierarchy/Driver/PluginManager.php @@ -0,0 +1,51 @@ +<?php +/** + * Hierarchy driver plugin manager + * + * 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 Hierarchy_Drivers + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/creating_a_session_handler Wiki + */ +namespace VuFind\Hierarchy\Driver; + +/** + * Hierarchy driver plugin manager + * + * @category VuFind2 + * @package Hierarchy_Drivers + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/creating_a_session_handler Wiki + */ +class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager +{ + /** + * Return the name of the base class or interface that plug-ins must conform + * to. + * + * @return string + */ + protected function getExpectedInterface() + { + return 'VuFind\Hierarchy\Driver\AbstractBase'; + } +} \ No newline at end of file diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/AbstractBase.php b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/AbstractBase.php new file mode 100644 index 00000000000..f8861c76ae9 --- /dev/null +++ b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/AbstractBase.php @@ -0,0 +1,131 @@ +<?php +/** + * Hierarchy Tree Data Source (abstract base) + * + * 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 HierarchyTree_DataSource + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_an_authentication_handler Wiki + */ +namespace VuFind\Hierarchy\TreeDataSource; +use Zend\Log\LoggerInterface; + +/** + * Hierarchy Tree Data Source (abstract base) + * + * This is a base helper class for producing hierarchy Trees. + * + * @category VuFind2 + * @package HierarchyTree_DataSource + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_an_authentication_handler Wiki + */ +abstract class AbstractBase implements \Zend\Log\LoggerAwareInterface +{ + /** + * Logger object for debug info (or false for no debugging). + * + * @var LoggerInterface|bool + */ + protected $logger = false; + + /** + * Hierarchy driver + * + * @var \VuFind\Hierarchy\Driver\AbstractBase + */ + protected $hierarchyDriver = null; + + /** + * Set the logger + * + * @param LoggerInterface $logger Logger to use. + * + * @return void + */ + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + } + + /** + * Output a debug message, if appropriate + * + * @param string $msg Message to display + * + * @return void + * @access protected + */ + protected function debug($msg) + { + if ($this->logger) { + $this->logger->debug($msg); + } + } + + /** + * Get the hierarchy driver + * + * @return \VuFind\Hierarchy\Driver\AbstractBase + * @throws \Exception + */ + protected function getHierarchyDriver() + { + if (null === $this->hierarchyDriver) { + throw new \Exception('Missing hierarchy driver'); + } + return $this->hierarchyDriver; + } + + /** + * Set the hierarchy driver + * + * @param \VuFind\Hierarchy\Driver\AbstractBase $driver Hierarchy driver + * + * @return AbstractBase + */ + public function setHierarchyDriver(\VuFind\Hierarchy\Driver\AbstractBase $driver) + { + $this->hierarchyDriver = $driver; + return $this; + } + + /** + * Get XML for the specified hierarchy ID. + * + * @param string $id Hierarchy ID. + * + * @return string + */ + abstract public function getXML($id); + + /** + * Does this data source support the specified hierarchy ID? + * + * @param string $id Hierarchy ID. + * + * @return bool + */ + abstract public function supports($id); +} + +?> \ No newline at end of file diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/PluginManager.php b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/PluginManager.php new file mode 100644 index 00000000000..f3a6b4cd028 --- /dev/null +++ b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/PluginManager.php @@ -0,0 +1,51 @@ +<?php +/** + * Hierarchy tree data source plugin manager + * + * 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 HierarchyTree_DataSource + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/creating_a_session_handler Wiki + */ +namespace VuFind\Hierarchy\TreeDataSource; + +/** + * Hierarchy tree data source plugin manager + * + * @category VuFind2 + * @package HierarchyTree_DataSource + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/creating_a_session_handler Wiki + */ +class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager +{ + /** + * Return the name of the base class or interface that plug-ins must conform + * to. + * + * @return string + */ + protected function getExpectedInterface() + { + return 'VuFind\Hierarchy\TreeDataSource\AbstractBase'; + } +} \ No newline at end of file diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php new file mode 100644 index 00000000000..3d6a01ca566 --- /dev/null +++ b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php @@ -0,0 +1,204 @@ +<?php +/** + * Hierarchy Tree Data Source (Solr) + * + * 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 HierarchyTree_DataSource + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_an_authentication_handler Wiki + */ +namespace VuFind\Hierarchy\TreeDataSource; +use VuFind\Connection\Manager as ConnectionManager; + +/** + * Hierarchy Tree Data Source (Solr) + * + * This is a base helper class for producing hierarchy Trees. + * + * @category VuFind2 + * @package HierarchyTree_DataSource + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_an_authentication_handler Wiki + */ +class Solr extends AbstractBase +{ + /** + * Solr connection + * + * @var object + */ + protected $db; + + /** + * Cache directory + * + * @var string + */ + protected $cacheDir; + + /** + * Constructor. + * + * @param string $cacheDir Directory to use for caching results (optional) + */ + public function __construct($cacheDir = null) + { + $this->db = ConnectionManager::connectToIndex(); + $this->cacheDir = rtrim($cacheDir, '/'); + } + + /** + * Get XML for the specified hierarchy ID. + * + * Build the XML file from the Solr fields + * + * TODO: this should return false if it fails. + * + * @param string $id Hierarchy ID. + * + * @return string + */ + public function getXML($id) + { + $top = $this->db->getRecord($id); + $cacheFile = (null !== $this->cacheDir) + ? $this->cacheDir . '/hierarchyTree_' . urlencode($id) . '.xml' + : false; + + $cacheTime = $this->getHierarchyDriver()->getTreeCacheTime(); + + if ($cacheFile && file_exists($cacheFile) + && filemtime($cacheFile) > (time() - $cacheTime) + ) { + $this->debug("Using cached data from $cacheFile"); + $xml = file_get_contents($cacheFile); + } else { + $starttime = microtime(true); + $xml = '<root><item id="' . + htmlspecialchars($id) . + '">' . + '<content><name>' . htmlspecialchars($top['title']) . + '</name></content>'; + $count = 0; + $xml .= $this->getChildren($id, $count); + $xml .= '</item></root>'; + if ($cacheFile) { + if (!file_exists($this->cacheDir)) { + mkdir($this->cacheDir); + } + file_put_contents($cacheFile, $xml); + } + $this->debug( + "Hierarchy of $count records built in " . + abs(microtime(true) - $starttime) + ); + } + return $xml; + } + + /** + * Get Solr Children + * + * @param string $parentID The starting point for the current recursion + * (equivlent to Solr field hierarchy_parent_id) + * @param string $count The total count of items in the tree + * before this recursion + * + * @return string + */ + protected function getChildren($parentID, &$count) + { + $query = 'hierarchy_parent_id:"' . addcslashes($parentID, '"') . '"'; + $results = $this->db->search(array('query' => $query, 'limit' => 10000)); + if ($results === false) { + return ''; + } + $xml = array(); + $sorting = $this->getHierarchyDriver()->treeSorting(); + + foreach ($results['response']['docs'] as $doc) { + ++$count; + if ($sorting) { + foreach ($doc['hierarchy_parent_id'] as $key => $val) { + if ($val == $parentID) { + $sequence = $doc['hierarchy_sequence'][$key]; + } + } + } + + $this->debug("$parentID: " . $doc['id']); + $xmlNode = ''; + $xmlNode .= '<item id="' . htmlspecialchars($doc['id']) . + '"><content><name>' . + htmlspecialchars($doc['title_full']) . '</name></content>'; + $xmlNode .= $this->getChildren($doc['id'], $count); + $xmlNode .= '</item>'; + array_push($xml, array((isset($sequence)?$sequence: 0),$xmlNode)); + } + + if ($sorting) { + $this->sortNodes($xml, 0); + } + + $xmlReturnString = ''; + foreach ($xml as $node) { + $xmlReturnString .= $node[1]; + } + return $xmlReturnString; + } + + /** + * Sort Nodes + * + * @param array &$array The Array to Sort + * @param string $key The key to sort on + * + * @return void + */ + protected function sortNodes(&$array, $key) + { + $sorter=array(); + $ret=array(); + reset($array); + foreach ($array as $ii => $va) { + $sorter[$ii]=$va[$key]; + } + asort($sorter); + foreach ($sorter as $ii => $va) { + $ret[$ii]=$array[$ii]; + } + $array=$ret; + } + + /** + * Does this data source support the specified hierarchy ID? + * + * @param string $id Hierarchy ID. + * + * @return bool + */ + public function supports($id) + { + // Assume all IDs are supported. + return true; + } +} diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/XMLFile.php b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/XMLFile.php new file mode 100644 index 00000000000..1d883899f47 --- /dev/null +++ b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/XMLFile.php @@ -0,0 +1,100 @@ +<?php +/** + * Hierarchy Tree Data Source (XML File) + * + * 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 HierarchyTree_DataSource + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_an_authentication_handler Wiki + */ +namespace VuFind\Hierarchy\TreeDataSource; + +/** + * Hierarchy Tree Data Source (XML File) + * + * This is a base helper class for producing hierarchy Trees. + * + * @category VuFind2 + * @package HierarchyTree_DataSource + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_an_authentication_handler Wiki + */ +class XMLFile extends AbstractBase +{ + /** + * Base path to XML files + * + * @var string + */ + protected $basePath = null; + + /** + * Get the base path for XML files. + * + * @return string + */ + protected function getBasePath() + { + if (null === $this->basePath) { + $settings = $this->getHierarchyDriver()->getTreeSettings(); + $this->basePath = isset($settings['XMLFileDir']) + ? $settings['XMLFileDir'] : ''; + } + return $this->basePath; + } + + /** + * Get the full filename for the XML file for a specific ID. + * + * @param string $id Hierarchy ID. + * + * @return string + */ + protected function getFilename($id) + { + return $this->getBasePath() . '/' . $id . '.xml'; + } + + /** + * Get XML for the specified hierarchy ID. + * + * @param string $id Hierarchy ID. + * + * @return string + */ + public function getXML($id) + { + return file_get_contents($this->getFilename($id)); + } + + /** + * Does this data source support the specified hierarchy ID? + * + * @param string $id Hierarchy ID. + * + * @return bool + */ + public function supports($id) + { + return file_exists($this->getFilename($id)); + } +} diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/AbstractBase.php b/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/AbstractBase.php new file mode 100644 index 00000000000..0a6e5027168 --- /dev/null +++ b/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/AbstractBase.php @@ -0,0 +1,147 @@ +<?php +/** + * Hierarchy Tree Renderer + * + * 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 HierarchyTree_Renderer + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_an_authentication_handler Wiki + */ +namespace VuFind\Hierarchy\TreeRenderer; + +/** + * Hierarchy Tree Renderer + * + * This is a base helper class for producing hierarchy Trees. + * + * @category VuFind2 + * @package HierarchyTree_Renderer + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_an_authentication_handler Wiki + */ +abstract class AbstractBase +{ + /** + * Hierarchical record to work on + * + * @var \VuFind\RecordDriver\AbstractBase + */ + protected $recordDriver = null; + + /** + * Source of hierarchy data + * + * @var \VuFind\Hierarchy\TreeDataSource\AbstractBase + */ + protected $dataSource = null; + + /** + * Set the record driver to operate on + * + * @param \VuFind\RecordDriver\AbstractBase $driver Record driver + * + * @return AbstractBase + */ + public function setRecordDriver(\VuFind\RecordDriver\AbstractBase $driver) + { + $this->recordDriver = $driver; + return $this; + } + + /** + * Get the current record driver + * + * @return \VuFind\RecordDriver\AbstractBase + * @throws \Exception + */ + protected function getRecordDriver() + { + if (null === $this->recordDriver) { + throw new \Exception('Missing record driver object'); + } + return $this->recordDriver; + } + + /** + * Get the current hierarchy data source + * + * @return \VuFind\Hierarchy\TreeDataSource\AbstractBase + * @throws \Exception + */ + protected function getDataSource() + { + if (null === $this->dataSource) { + // Load the hierarchy driver from the record driver -- throw exception if + // this fails, since we shouldn't be using this class for drivers that do + // not support hierarchies! + $hierarchyDriver = $this->getRecordDriver() + ->tryMethod('getHierarchyDriver'); + if (!is_object($hierarchyDriver)) { + throw new \Exception('Cannot load hierarchy driver from record driver.'); + } + $this->dataSource = $hierarchyDriver->getTreeSource(); + } + return $this->dataSource; + } + + /** + * Get a list of trees containing the item represented by the stored record + * driver. + * + * @param string $hierarchyID Optional filter: specific hierarchy ID to retrieve + * + * @return mixed An array of hierarchy IDS if an archive tree exists, + * false if it does not + */ + abstract public function getTreeList($hierarchyID = false); + + /** + * Render the Hierarchy Tree + * + * @param string $context The context from which the call has been made + * @param string $mode The mode in which the tree should be generated + * @param string $hierarchyID The hierarchy ID of the tree to fetch (optional) + * @param string $recordID The current record ID (optional) + * + * @return mixed The desired hierarchy tree output (or false on error) + */ + abstract public function render( + $context, $mode, $hierarchyID, $recordID = false + ); + + /** + * Get Hierarchy Name + * + * @param string $hierarchyID The hierarchy ID to find the title for + * @param string $inHierarchies An array of hierarchy IDs + * @param string $inHierarchiesTitle An array of hierarchy Titles + * + * @return string A hierarchy title + */ + public function getHierarchyName( + $hierarchyID, $inHierarchies, $inHierarchiesTitle + ) { + $keys = array_flip($inHierarchies); + $key = $keys[$hierarchyID]; + return $inHierarchiesTitle[$key]; + } +} \ No newline at end of file diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/JSTree.php b/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/JSTree.php new file mode 100644 index 00000000000..476b2ef7d37 --- /dev/null +++ b/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/JSTree.php @@ -0,0 +1,183 @@ +<?php +/** + * Hierarchy Tree Renderer for the JS_Tree plugin + * + * 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 HierarchyTree_Renderer + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_an_authentication_handler Wiki + */ +namespace VuFind\Hierarchy\TreeRenderer; + +/** + * Hierarchy Tree Renderer + * + * This is a helper class for producing hierarchy trees. + * + * @category VuFind2 + * @package HierarchyTree_Renderer + * @author Luke O'Sullivan <l.osullivan@swansea.ac.uk> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/building_an_authentication_handler Wiki + */ + +class JSTree extends AbstractBase + implements \VuFind\I18n\Translator\TranslatorAwareInterface +{ + /** + * Translator (or null if unavailable) + * + * @var \Zend\I18n\Translator\Translator + */ + protected $translator = null; + + /** + * Set a translator + * + * @param \Zend\I18n\Translator\Translator $translator Translator + * + * @return AbstractBase + */ + public function setTranslator(\Zend\I18n\Translator\Translator $translator) + { + $this->translator = $translator; + return $this; + } + + /** + * Translate a string if a translator is available. + * + * @param string $msg Message to translate + * + * @return string + */ + public function translate($msg) + { + return null !== $this->translator + ? $this->translator->translate($msg) : $msg; + } + + /** + * Get a list of trees containing the item represented by the stored record + * driver. + * + * @param string $hierarchyID Optional filter: specific hierarchy ID to retrieve + * + * @return mixed An array of hierarchy IDS if an archive tree exists, + * false if it does not + */ + public function getTreeList($hierarchyID = false) + { + $record = $this->getRecordDriver(); + $id = $record->getUniqueID(); + $inHierarchies = $record->getHierarchyTopID(); + $inHierarchiesTitle = $record->getHierarchyTopTitle(); + + if ($hierarchyID) { + // Specific Hierarchy Supplied + if (in_array($hierarchyID, $inHierarchies) + && $this->getDataSource()->supports($hierarchyID) + ) { + return array( + $hierarchyID => $this->getHierarchyName( + $hierarchyID, $inHierarchies, $inHierarchiesTitle + ) + ); + } + } else { + // Return All Hierarchies + $i = 0; + $hierarchies = array(); + foreach ($inHierarchies as $hierarchyTopID) { + if ($this->getDataSource()->supports($hierarchyTopID)) { + $hierarchies[$hierarchyTopID] = $inHierarchiesTitle[$i]; + } + $i++; + } + if (!empty($hierarchies)) { + return $hierarchies; + } + } + + // If we got this far, we couldn't find valid match(es). + return false; + } + + /** + * Render the Hierarchy Tree + * + * @param string $context The context from which the call has been made + * @param string $mode The mode in which the tree should be generated + * @param string $hierarchyID The hierarchy ID of the tree to fetch (optional) + * @param string $recordID The current record ID (optional) + * + * @return mixed The desired hierarchy tree output (or false on error) + */ + public function render($context, $mode, $hierarchyID, $recordID = false) + { + if (!empty($context) && !empty($mode)) { + return $this->transformCollectionXML( + $context, $mode, $hierarchyID, $recordID + ); + } + return false; + } + + /** + * transformCollectionXML + * + * Transforms Collection XML to Desired Format + * + * @param string $context The Context in which the tree is being displayed + * @param string $mode The Mode in which the tree is being displayed + * @param string $hierarchyID The hierarchy to get the tree for + * @param string $recordID The currently selected Record (false for none) + * + * @return string A HTML List + */ + protected function transformCollectionXML( + $context, $mode, $hierarchyID, $recordID + ) { + $record = $this->getRecordDriver(); + $inHierarchies = $record->getHierarchyTopID(); + $inHierarchiesTitle = $record->getHierarchyTopTitle(); + + $hierarchyTitle = $this->getHierarchyName( + $hierarchyID, $inHierarchies, $inHierarchiesTitle + ); + + // Set up parameters for XSL transformation + $params = array( + 'titleText' => $this->translate('collection_view_record'), + 'collectionID' => $hierarchyID, + 'collectionTitle' => $hierarchyTitle, + 'baseURL' => '%%%%VUFIND-BASE-URL%%%%', + 'context' => $context, + 'recordID' => $recordID + ); + + // Transform the XML + $xmlFile = $this->getDataSource()->getXML($hierarchyID); + $transformation = ucfirst($context) . ucfirst($mode); + $xslFile = "Hierarchy/{$transformation}.xsl"; + return \VuFind\XSLT\Processor::process($xslFile, $xmlFile, $params); + } +} \ No newline at end of file diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/PluginManager.php b/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/PluginManager.php new file mode 100644 index 00000000000..9499a2927ec --- /dev/null +++ b/module/VuFind/src/VuFind/Hierarchy/TreeRenderer/PluginManager.php @@ -0,0 +1,51 @@ +<?php +/** + * Hierarchy tree renderer plugin manager + * + * 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 HierarchyTree_Renderer + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/creating_a_session_handler Wiki + */ +namespace VuFind\Hierarchy\TreeRenderer; + +/** + * Hierarchy tree renderer plugin manager + * + * @category VuFind2 + * @package HierarchyTree_Renderer + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/creating_a_session_handler Wiki + */ +class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager +{ + /** + * Return the name of the base class or interface that plug-ins must conform + * to. + * + * @return string + */ + protected function getExpectedInterface() + { + return 'VuFind\Hierarchy\TreeRenderer\AbstractBase'; + } +} \ No newline at end of file diff --git a/module/VuFind/src/VuFind/RecordDriver/PluginManager.php b/module/VuFind/src/VuFind/RecordDriver/PluginManager.php index 4f1f901a0ed..97896b779ef 100644 --- a/module/VuFind/src/VuFind/RecordDriver/PluginManager.php +++ b/module/VuFind/src/VuFind/RecordDriver/PluginManager.php @@ -48,6 +48,22 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager ) { parent::__construct($configuration); + // Add an initializer for setting up hierarchies + $initializer = function ($instance, $manager) { + $hasHierarchyType = is_callable(array($instance, 'getHierarchyType')); + if ($hasHierarchyType + && is_callable(array($instance, 'setHierarchyDriverManager')) + ) { + $sm = $manager->getServiceLocator(); + if ($sm->has('VuFind\HierarchyDriverPluginManager')) { + $instance->setHierarchyDriverManager( + $sm->get('VuFind\HierarchyDriverPluginManager') + ); + } + } + }; + $this->addInitializer($initializer, false); + // Record drivers are not meant to be shared -- every time we retrieve one, // we are building a brand new object. $this->setShareByDefault(false); diff --git a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php index b159d3db2f5..1b74ae5cbc0 100644 --- a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php +++ b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php @@ -89,6 +89,20 @@ class SolrDefault extends AbstractBase */ protected $snippet = false; + /** + * Hierarchy driver plugin manager + * + * @var \VuFind\Hierarchy\Driver\PluginManager + */ + protected $hierarchyDriverManager = null; + + /** + * Hierarchy driver for current object + * + * @var \VuFind\Hierarchy\Driver\AbstractBase + */ + protected $hierarchyDriver = null; + /** * Constructor. */ @@ -1030,6 +1044,99 @@ class SolrDefault extends AbstractBase return array(); } + /** + * Get a hierarchy driver appropriate to the current object. (May be false if + * disabled/unavailable). + * + * @return \VuFind\Hierarchy\Driver\AbstractBase|bool + */ + public function getHierarchyDriver() + { + if (null === $this->hierarchyDriver + && null !== $this->hierarchyDriverManager + ) { + $type = $this->getHierarchyType(); + $this->hierarchyDriver = $type + ? $this->hierarchyDriverManager->get($type) : false; + } + return $this->hierarchyDriver; + } + + /** + * Inject a hierarchy driver plugin manager. + * + * @param \VuFind\Hierarchy\Driver\PluginManager $pm Hierarchy driver manager + * + * @return SolrDefault + */ + public function setHierarchyDriverManager( + \VuFind\Hierarchy\Driver\PluginManager $pm + ) { + $this->hierarchyDriverManager = $pm; + return $this; + } + + /** + * Get the hierarchy_top_id(s) associated with this item (empty if none). + * + * @return array + */ + public function getHierarchyTopID() + { + return isset($this->fields['hierarchy_top_id']) + ? $this->fields['hierarchy_top_id'] : array(); + } + + /** + * Get the absolute parent title(s) associated with this item + * (empty if none). + * + * @return array + */ + public function getHierarchyTopTitle() + { + return isset($this->fields['hierarchy_top_title']) + ? $this->fields['hierarchy_top_title'] : array(); + } + + /** + * Get a list of hierarchy trees containing this record. + * + * @param string $hierarchyID The hierarchy to get the tree for + * + * @return mixed An associative array of hierachy trees on success (id => title), + * false if no hierarchies found + */ + public function getHierarchyTrees($hierarchyID = false) + { + $hierarchyDriver = $this->getHierarchyDriver(); + if ($hierarchyDriver && $hierarchyDriver->showTree()) { + return $hierarchyDriver->getTreeRenderer($this) + ->getTreeList($hierarchyID); + } + return false; + } + + /** + * Get the Hierarchy Type (false if none) + * + * @return string|bool + */ + public function getHierarchyType() + { + if (isset($this->fields['hierarchy_top_id'])) { + $hierarchyType = isset($this->fields['hierarchytype']) + ? $this->fields['hierarchytype'] : false; + if (!$hierarchyType) { + $config = ConfigReader::getConfig(); + $hierarchyType = isset($config->Hierarchy->driver) + ? $config->Hierarchy->driver : false; + } + return $hierarchyType; + } + return false; + } + /** * Return the unique identifier of this record within the Solr index; * useful for retrieving additional information (like tags and user diff --git a/module/VuFind/src/VuFind/RecordTab/HierarchyTree.php b/module/VuFind/src/VuFind/RecordTab/HierarchyTree.php new file mode 100644 index 00000000000..060fccd29e1 --- /dev/null +++ b/module/VuFind/src/VuFind/RecordTab/HierarchyTree.php @@ -0,0 +1,126 @@ +<?php +/** + * HierarchyTree tab + * + * 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 RecordTabs + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/creating_a_session_handler Wiki + */ +namespace VuFind\RecordTab; +use VuFind\Config\Reader as ConfigReader; + +/** + * HierarchyTree tab + * + * @category VuFind2 + * @package RecordTabs + * @author Demian Katz <demian.katz@villanova.edu> + * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License + * @link http://vufind.org/wiki/creating_a_session_handler Wiki + */ +class HierarchyTree extends AbstractBase +{ + /** + * Tree data + * + * @var array + */ + protected $treeList = null; + + /** + * Get the on-screen description for this tab. + * + * @return string + */ + public function getDescription() + { + return 'hierarchy_tree'; + } + + /** + * Is this tab active? + * + * @return bool + */ + public function isActive() + { + $trees = $this->getTreeList(); + return !empty($trees); + } + + /** + * Get the ID of the active tree (false if none) + * + * @return string|bool + */ + public function getActiveTree() + { + $treeList = $this->getTreeList(); + if (count($treeList) == 1) { + $keys = array_keys($treeList); + return $keys[0]; + } else { + return ($request = $this->getRequest()) + ? $request->getQuery('hierarchy', false) + : false; + } + } + + /** + * Get an array of tree data + * + * @return array + */ + public function getTreeList() + { + if (null === $this->treeList) { + $this->treeList + = $this->getRecordDriver()->tryMethod('getHierarchyTrees'); + if (null === $this->treeList) { + $this->treeList = array(); + } + } + return $this->treeList; + } + + /** + * Render a hierarchy tree + * + * @param string $baseUrl Base URL to use in links within tree + * @param string $id Hierarchy ID (omit to use active tree) + * + * @return string + */ + public function renderTree($baseUrl, $id = null) + { + $id = (null === $id) ? $this->getActiveTree() : $id; + $recordDriver = $this->getRecordDriver(); + $hierarchyDriver = $recordDriver->tryMethod('getHierarchyDriver'); + if (is_object($hierarchyDriver)) { + $tree = $hierarchyDriver->render($recordDriver, 'Record', 'List', $id); + return str_replace( + '%%%%VUFIND-BASE-URL%%%%', rtrim($baseUrl, '/'), $tree + ); + } + return ''; + } +} \ No newline at end of file diff --git a/module/VuFind/xsl/Hierarchy/RecordList.xsl b/module/VuFind/xsl/Hierarchy/RecordList.xsl new file mode 100644 index 00000000000..71aa6969c06 --- /dev/null +++ b/module/VuFind/xsl/Hierarchy/RecordList.xsl @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl"> + + <xsl:template match="/"> + <div id="treeList"> + <xsl:apply-templates select="//root"> + </xsl:apply-templates> + </div> + </xsl:template> + + <xsl:template match="item"> + <ul> + <xsl:variable name="id" select="@id" /> + <li> + <xsl:attribute name="id">tree-<xsl:value-of select="$id"/></xsl:attribute> + <xsl:attribute name="class"> + <xsl:choose> + <xsl:when test="$recordID = $id">currentRecord</xsl:when> + </xsl:choose> + </xsl:attribute> + <xsl:variable name="baseModule">Record</xsl:variable> + <a href="{$baseURL}/{$baseModule}/{$id}/HierarchyTree?hierarchy={$collectionID}&recordID={$id}#tree-{$id}" title="{$titleText}"> + <xsl:value-of select="./content/name" /> + </a> + <xsl:apply-templates select="item"/> + </li> + </ul> + </xsl:template> + +</xsl:stylesheet> diff --git a/solr/biblio/conf/schema.xml b/solr/biblio/conf/schema.xml index 5b786c38462..e7ec375b603 100644 --- a/solr/biblio/conf/schema.xml +++ b/solr/biblio/conf/schema.xml @@ -176,6 +176,15 @@ <field name="container_issue" type="text" indexed="true" stored="true"/> <field name="container_start_page" type="text" indexed="true" stored="true"/> <field name="container_reference" type="text" indexed="true" stored="true"/> + <!-- Hierarchy Fields --> + <field name="hierarchytype" type="string" index="true" stored="true" multiValued="false"/> + <field name="hierarchy_top_id" type="string" index="true" stored="true" multiValued="true"/> + <field name="hierarchy_top_title" type="string" index="true" stored="true" multiValued="true"/> + <field name="hierarchy_parent_id" type="string" indexed="true" stored="true" multiValued="true"/> + <field name="hierarchy_parent_title" type="string" indexed="true" stored="true" multiValued="true"/> + <field name="hierarchy_sequence" type="string" indexed="true" stored="true" multiValued="true"/> + <field name="is_hierarchy_id" type="string" indexed="true" stored="true" multiValued="false"/> + <field name="is_hierarchy_title" type="string" indexed="true" stored="true" multiValued="false"/> <!-- Used for loading correct record driver --> <field name="recordtype" type="string" indexed="false" stored="true"/> <!-- Tracking fields to keep track of oldest and most recent index times --> diff --git a/themes/blueprint/css/styles.css b/themes/blueprint/css/styles.css index fa7a0b79493..d97a5f6ebc9 100644 --- a/themes/blueprint/css/styles.css +++ b/themes/blueprint/css/styles.css @@ -1735,4 +1735,12 @@ div#closeContextHelp:active { /* Make sure COinS information is invisible */ .Z3988 { display: none; -} \ No newline at end of file +} + +.currentTree, .hierarchyTreeLinkText { + background-image:url(../images/fugue/treeCurrent.png); + background-repeat:no-repeat; + background-position: left; + padding:.5em .5em .5em 20px; + margin-right:1em; +} diff --git a/themes/blueprint/templates/RecordDriver/SolrDefault/result-list.phtml b/themes/blueprint/templates/RecordDriver/SolrDefault/result-list.phtml index efb9e2cbfab..601825ececa 100644 --- a/themes/blueprint/templates/RecordDriver/SolrDefault/result-list.phtml +++ b/themes/blueprint/templates/RecordDriver/SolrDefault/result-list.phtml @@ -107,6 +107,17 @@ <div class="savedLists info hide"> <strong><?=$this->transEsc("Saved in")?>:</strong> </div> + + <? $trees = $this->driver->tryMethod('getHierarchyTrees'); if (!empty($trees)): ?> + <? foreach ($trees as $hierarchyID => $hierarchyTitle): ?> + <div class="hierarchyTreeLink"> + <input type="hidden" value="<?=$this->escapeHtml($hierarchyID)?>" class="hiddenHierarchyId" /> + <a class="hierarchyTreeLinkText" href="<?=$this->recordLink()->getTabUrl($this->driver, 'HierarchyTree')?>?hierarchy=<?=urlencode($hierarchyID)?>#tabnav" title="<?=$this->transEsc('hierarchy_tree')?>"> + <?=$this->transEsc('hierarchy_view_context')?><? if (count($trees) > 1): ?>: <?=$this->escapeHtml($hierarchyTitle)?><? endif; ?> + </a> + </div> + <? endforeach; ?> + <? endif; ?> </div> <div class="clear"></div> diff --git a/themes/blueprint/templates/RecordTab/hierarchytree.phtml b/themes/blueprint/templates/RecordTab/hierarchytree.phtml new file mode 100644 index 00000000000..656aaf248f6 --- /dev/null +++ b/themes/blueprint/templates/RecordTab/hierarchytree.phtml @@ -0,0 +1,22 @@ +<? + // Set page title. + $this->headTitle($this->translate('hierarchy_tree') . ': ' . $this->driver->getBreadcrumb()); + $hierarchyTreeList = $this->tab->getTreeList(); + $activeTree = $this->tab->getActiveTree(); +?> +<div> + <? if (count($hierarchyTreeList) > 1): ?> + <div id="treeSelector"> + <? foreach ($hierarchyTreeList as $hierarchy => $hierarchyTitle): ?> + <a class="tree<?=($activeTree == $hierarchy) ? ' currentTree' : ''?>" href="<?=$this->recordLink()->getTabUrl($this->driver, 'HierarchyTree')?>?hierarchy=<?=urlencode($hierarchy)?>"><?=$this->escapeHtml($hierarchyTitle)?></a> + <? endforeach; ?> + </div> + <? endif; ?> + <? if ($activeTree): ?> + <div id="hierarchyTreeHolder"> + <div id="hierarchyTree"> + <?=$this->tab->renderTree($this->url('home'))?> + </div> + </div> + <? endif; ?> +</div> diff --git a/themes/jquerymobile/templates/RecordTab/hierarchytree.phtml b/themes/jquerymobile/templates/RecordTab/hierarchytree.phtml new file mode 100644 index 00000000000..656aaf248f6 --- /dev/null +++ b/themes/jquerymobile/templates/RecordTab/hierarchytree.phtml @@ -0,0 +1,22 @@ +<? + // Set page title. + $this->headTitle($this->translate('hierarchy_tree') . ': ' . $this->driver->getBreadcrumb()); + $hierarchyTreeList = $this->tab->getTreeList(); + $activeTree = $this->tab->getActiveTree(); +?> +<div> + <? if (count($hierarchyTreeList) > 1): ?> + <div id="treeSelector"> + <? foreach ($hierarchyTreeList as $hierarchy => $hierarchyTitle): ?> + <a class="tree<?=($activeTree == $hierarchy) ? ' currentTree' : ''?>" href="<?=$this->recordLink()->getTabUrl($this->driver, 'HierarchyTree')?>?hierarchy=<?=urlencode($hierarchy)?>"><?=$this->escapeHtml($hierarchyTitle)?></a> + <? endforeach; ?> + </div> + <? endif; ?> + <? if ($activeTree): ?> + <div id="hierarchyTreeHolder"> + <div id="hierarchyTree"> + <?=$this->tab->renderTree($this->url('home'))?> + </div> + </div> + <? endif; ?> +</div> -- GitLab