Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor hierarchy tree to an HTML-based one. #3277

Merged
merged 19 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions config/vufind/HierarchyDefault.ini
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ solrCacheTime = 43200
;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
; Which Tree Renderer to Use - Default is HTMLTree
treeRenderer = HTMLTree
; Control whether or not to display the full hierarchy tree in record mode
; (true = show full hierarchy, false = only show path to current selected node,
; default = true)
Expand Down
4 changes: 2 additions & 2 deletions config/vufind/HierarchyFlat.ini
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ show = false
;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
; Which Tree Renderer to Use - Default is HTMLTree
;treeRenderer = HTMLTree
; Control whether or not to display the full hierarchy tree in record mode
; (true = show full hierarchy, false = only show path to current selected node,
; default = true)
Expand Down
161 changes: 55 additions & 106 deletions module/VuFind/src/VuFind/Controller/HierarchyController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* PHP version 8
*
* Copyright (C) Villanova University 2010-2023.
* Copyright (C) The National Library of Finland 2024.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
Expand All @@ -23,67 +24,93 @@
* @category VuFind
* @package Controller
* @author Demian Katz <demian.katz@villanova.edu>
* @author Ere Maijala <ere.maijala@helsinki.fi>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:plugins:controllers Wiki
*/

namespace VuFind\Controller;

use Laminas\Stdlib\ResponseInterface;

use function array_slice;
use function count;
use function is_object;

/**
* Hierarchy Controller
*
* @category VuFind
* @package Controller
* @author Demian Katz <demian.katz@villanova.edu>
* @author Ere Maijala <ere.maijala@helsinki.fi>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:plugins:controllers Wiki
*/
class HierarchyController extends AbstractBase
{
/**
* XML output routine
* Output JSON
*
* @param string $xml XML to output
* @param array $result Result to be encoded as JSON
* @param int $status Response status code
*
* @return \Laminas\Http\Response
* @return ResponseInterface
*/
protected function output($xml)
protected function outputJSON(array $result, int $status = 200): ResponseInterface
{
$response = $this->getResponse();
$headers = $response->getHeaders();
$headers->addHeaderLine('Content-type', 'text/xml');
$response->setContent($xml);
$headers->addHeaderLine('Content-type', 'application/json');
$response->setContent(json_encode($result));
$response->setStatusCode($status);
return $response;
}

/**
* Output JSON
*
* @param string $json A JSON string
* @param int $status Response status code
* Gets a Hierarchy Tree
*
* @return \Laminas\Http\Response
* @return mixed
*/
protected function outputJSON($json, $status = 200)
public function gettreeAction()
{
$response = $this->getResponse();
$headers = $response->getHeaders();
$headers->addHeaderLine('Content-type', 'application/json');
$response->setContent($json);
$response->setStatusCode($status);
return $response;
$this->disableSessionWrites(); // avoid session write timing bug

$id = $this->params()->fromQuery('id');
$source = $this->params()->fromQuery('sourceId', DEFAULT_SEARCH_BACKEND);
$loader = $this->getRecordLoader();
$message = 'Service Unavailable'; // default error message
try {
$recordDriver = $loader->load($id, $source);
$hierarchyDriver = $recordDriver->tryMethod('getHierarchyDriver');
if (is_object($hierarchyDriver)) {
return $this->outputJSON([
'html' => $hierarchyDriver->render(
$recordDriver,
$this->params()->fromQuery('context', 'Record'),
'List',
$this->params()->fromQuery('hierarchyId', ''),
$this->params()->fromQuery(),
),
]);
}
} catch (\Exception $e) {
// Let exceptions fall through to error condition below:
$message = APPLICATION_ENV === 'development' ? (string)$e : 'Unexpected exception';
}

// If we got this far, something went wrong:
$code = 503;
$response = ['error' => compact('code', 'message')];
return $this->outputJSON($response, $code);
}

/**
* Search the tree and echo a json result of items that
* matched the keywords.
* Search the tree and output a JSON result of items that matched the keywords.
*
* @return \Laminas\Http\Response
* @return ResponseInterface
*/
public function searchtreeAction()
public function searchtreeAction(): ResponseInterface
{
$this->disableSessionWrites(); // avoid session write timing bug
$config = $this->getConfig();
Expand Down Expand Up @@ -113,102 +140,24 @@ public function searchtreeAction()
'limitReached' => $limitReached,
'results' => array_slice($resultIDs, 0, $limit),
];
return $this->outputJSON(json_encode($returnArray));
}

/**
* Gets a Hierarchy Tree
*
* @return mixed
*/
public function gettreeAction()
{
$this->disableSessionWrites(); // avoid session write timing bug
// Retrieve the record from the index
$id = $this->params()->fromQuery('id');
$source = $this->params()
->fromQuery('hierarchySource', DEFAULT_SEARCH_BACKEND);
$loader = $this->getRecordLoader();
try {
if ($recordDriver = $loader->load($id, $source)) {
$results = $recordDriver->getHierarchyDriver()->render(
$recordDriver,
$this->params()->fromQuery('context'),
$this->params()->fromQuery('mode'),
$this->params()->fromQuery('hierarchyID')
);
if ($results) {
return $this->output($results);
}
}
} catch (\Exception $e) {
// Let exceptions fall through to error condition below:
}

// If we got this far, something went wrong:
return $this->output(
'<error>' . $this->translate('hierarchy_tree_error') . '</error>'
);
}

/**
* Gets a Hierarchy Tree
*
* @return mixed
*/
public function gettreejsonAction()
{
$this->disableSessionWrites(); // avoid session write timing bug
// Retrieve the record from the index
$id = $this->params()->fromQuery('id');
$source = $this->params()
->fromQuery('hierarchySource', DEFAULT_SEARCH_BACKEND);
$loader = $this->getRecordLoader();
$message = 'Service Unavailable'; // default error message
try {
if ($recordDriver = $loader->load($id, $source)) {
$results = $recordDriver->getHierarchyDriver()
->getTreeRenderer($recordDriver)->getJSON(
$this->params()->fromQuery('hierarchyID'),
$this->params()->fromQuery('context')
);
if ($results) {
return $this->outputJSON($results);
} else {
return $this->outputJSON($results, 204); // No Content
}
}
} catch (\Exception $e) {
// Let exceptions fall through to error condition below:
$message = APPLICATION_ENV === 'development'
? (string)$e : 'Unexpected exception';
}

// If we got this far, something went wrong:
$code = 503;
$response = ['error' => compact('code', 'message')];
return $this->outputJSON(json_encode($response), $code);
// Service Unavailable
return $this->outputJSON($returnArray);
}

/**
* Get a record for display within a tree
*
* @return mixed
* @return ResponseInterface
*/
public function getrecordAction()
public function getrecordAction(): ResponseInterface
{
$id = $this->params()->fromQuery('id');
$source = $this->params()
->fromQuery('hierarchySource', DEFAULT_SEARCH_BACKEND);
$source = $this->params()->fromQuery('source', DEFAULT_SEARCH_BACKEND);
$loader = $this->getRecordLoader();
try {
$record = $loader->load($id, $source);
$result = $this->getViewRenderer()->record($record)
->getCollectionBriefRecord();
$result = $this->getViewRenderer()->record($record)->getCollectionBriefRecord();
} catch (\VuFind\Exception\RecordMissing $e) {
$result = $this->getViewRenderer()
->render('collection/collection-record-error.phtml');
$result = $this->getViewRenderer()->render('collection/collection-record-error.phtml');
}
$response = $this->getResponse();
$response->setContent($result);
Expand Down
37 changes: 29 additions & 8 deletions module/VuFind/src/VuFind/Hierarchy/Driver/AbstractBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,25 +134,25 @@ public function getTreeRenderer(\VuFind\RecordDriver\AbstractBase $driver)
* 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 $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
* @param string $hierarchyID Hierarchy ID to get the tree for
* @param array $options Additional options for the renderer
*
* @return string
*/
public function render(
\VuFind\RecordDriver\AbstractBase $driver,
$context,
$mode,
$hierarchyID
string $context,
string $mode,
string $hierarchyID,
array $options
) {
if (!$this->showTree()) {
return false;
}
return $this->getTreeRenderer($driver)
->render($context, $mode, $hierarchyID, $driver->getUniqueID());
->render($context, $mode, $hierarchyID, $driver->getUniqueID(), $options);
}

/**
Expand All @@ -177,4 +177,25 @@ abstract public function getTreeSettings();
* @return string
*/
abstract public function getTreeSourceType();

/**
* Check if sorting is enabled in the hierarchy Options
*
* @return bool
*/
abstract public function treeSorting();

/**
* Get Collection Link Type
*
* @return string
*/
abstract public function getCollectionLinkType();

/**
* Get tree cache time in seconds
*
* @return int
*/
abstract public function getTreeCacheTime();
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ConfigurationBased extends AbstractBase
*
* @var string
*/
protected $defaultTreeRenderer = 'JSTree';
protected $defaultTreeRenderer = 'HTMLTree';

/**
* Show Tree
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
*/
protected $aliases = [
'json' => Json::class,
'xml' => Xml::class,
];

/**
Expand All @@ -57,7 +56,6 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
*/
protected $factories = [
Json::class => AbstractBaseFactory::class,
Xml::class => AbstractBaseFactory::class,
];

/**
Expand Down