Fix Bug #985492: faceted search feature

This commit is contained in:
Sebastian Meyer 2012-08-22 21:22:29 +02:00
commit d222dd6040
21 changed files with 1199 additions and 453 deletions

View File

@ -1,6 +1,6 @@
<?php
/***************************************************************
* Copyright notice
* Copyright notice
*
* (c) 2012 Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* All rights reserved
@ -106,13 +106,13 @@ class tx_dlf_cli extends t3lib_cli {
// Set basic information about the script.
$this->cli_help = array (
'name' => 'Command Line Interface for Goobi.Presentation',
'synopsis' => '###OPTIONS###',
'description' => 'Currently the only task available is "index".'.LF.'Try "/PATH/TO/TYPO3/cli_dispatch.phpsh dlf index" to view more options.',
'examples' => '/PATH/TO/TYPO3/cli_dispatch.phpsh dlf TASK -ARG1=VALUE1 -ARG2=VALUE2',
'options' => '',
'license' => 'GNU GPL - free software!',
'author' => 'Sebastian Meyer <sebastian.meyer@slub-dresden.de>',
'name' => 'Command Line Interface for Goobi.Presentation',
'synopsis' => '###OPTIONS###',
'description' => 'Currently the only task available is "index".'.LF.'Try "/PATH/TO/TYPO3/cli_dispatch.phpsh dlf index" to view more options.',
'examples' => '/PATH/TO/TYPO3/cli_dispatch.phpsh dlf TASK -ARG1=VALUE1 -ARG2=VALUE2',
'options' => '',
'license' => 'GNU GPL - free software!',
'author' => 'Sebastian Meyer <sebastian.meyer@slub-dresden.de>',
);
// Run parent constructor.

View File

@ -180,7 +180,7 @@ final class tx_dlf_document {
* @var integer
* @access protected
*/
protected $parentid = 0;
protected $parentId = 0;
/**
* This holds the physical pages
@ -229,7 +229,7 @@ final class tx_dlf_document {
* @var string
* @access protected
*/
protected $recordid;
protected $recordId;
/**
* This holds the singleton object of each document with its UID as array key
@ -658,9 +658,28 @@ final class tx_dlf_document {
$this->_getDmdSec();
// Is this metadata format supported?
if (!empty($this->formats[$this->dmdSec[$dmdId]['type']]['class'])) {
if (!empty($this->formats[$this->dmdSec[$dmdId]['type']])) {
$class = $this->formats[$this->dmdSec[$dmdId]['type']]['class'];
if (!empty($this->formats[$this->dmdSec[$dmdId]['type']]['class'])) {
$class = $this->formats[$this->dmdSec[$dmdId]['type']]['class'];
// Get the metadata from class.
if (class_exists($class) && ($obj = t3lib_div::makeInstance($class)) instanceof tx_dlf_format) {
$obj->extractMetadata($this->dmdSec[$dmdId]['xml'], $metadata);
} else {
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_document->getMetadata('.$id.', '.$_cPid.')] Invalid class/method "'.$class.'->extractMetadata()" for metadata format "'.$this->dmdSec[$dmdId]['type'].'"', $this->extKey, SYSLOG_SEVERITY_WARNING);
}
}
}
} else {
@ -674,23 +693,6 @@ final class tx_dlf_document {
}
// Get the metadata from class.
if (class_exists($class) && ($obj = t3lib_div::makeInstance($class)) instanceof tx_dlf_format) {
$obj->extractMetadata($this->dmdSec[$dmdId]['xml'], $metadata);
} else {
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_document->getMetadata('.$id.', '.$_cPid.')] Invalid class/method "'.$class.'->extractMetadata()" for metadata format "'.$this->dmdSec[$dmdId]['type'].'"', $this->extKey, SYSLOG_SEVERITY_ERROR);
}
return array ();
}
// Get the structure's type.
if (!empty($this->logicalUnits[$id])) {
@ -880,7 +882,7 @@ final class tx_dlf_document {
$titledata = $this->getMetadata($this->_getToplevelId(), $cPid);
// Set record identifier for METS file.
array_unshift($titledata['record_id'], $this->recordid);
array_unshift($titledata['record_id'], $this->recordId);
return $titledata;
@ -1432,7 +1434,7 @@ final class tx_dlf_document {
$this->pid = $pid;
$this->parentid = $partof;
$this->parentId = $partof;
}
@ -1606,15 +1608,15 @@ final class tx_dlf_document {
}
/**
* This returns $this->parentid via __get()
* This returns $this->parentId via __get()
*
* @access protected
*
* @return integer The UID of the parent document or zero if not applicable
*/
protected function _getParentid() {
protected function _getParentId() {
return $this->parentid;
return $this->parentId;
}
@ -1775,15 +1777,15 @@ final class tx_dlf_document {
}
/**
* This returns $this->recordid via __get()
* This returns $this->recordId via __get()
*
* @access protected
*
* @return mixed The METS file's record identifier
*/
protected function _getRecordid() {
protected function _getRecordId() {
return $this->recordid;
return $this->recordId;
}
@ -1963,7 +1965,7 @@ final class tx_dlf_document {
if (!empty($objId[0]['OBJID'])) {
$this->recordid = (string) $objId[0]['OBJID'];
$this->recordId = (string) $objId[0]['OBJID'];
}
@ -1974,7 +1976,7 @@ final class tx_dlf_document {
if (method_exists($hookObj, 'construct_postProcessRecordId')) {
$this->recordid = $hookObj->construct_postProcessRecordId($xml, $this->recordid);
$this->recordId = $hookObj->construct_postProcessRecordId($xml, $this->recordId);
}
@ -1982,9 +1984,9 @@ final class tx_dlf_document {
}
if (!empty($this->recordid)) {
if (!empty($this->recordId)) {
$whereClause = 'tx_dlf_documents.record_id='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->recordid, 'tx_dlf_documents').tx_dlf_helper::whereClause('tx_dlf_documents');
$whereClause = 'tx_dlf_documents.record_id='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->recordId, 'tx_dlf_documents').tx_dlf_helper::whereClause('tx_dlf_documents');
} else {
@ -2014,7 +2016,7 @@ final class tx_dlf_document {
if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) {
list ($this->uid, $this->pid, $this->recordid, $this->parentid, $location) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
list ($this->uid, $this->pid, $this->recordId, $this->parentId, $location) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
// Load XML file...
if ($this->load($location)) {
@ -2122,7 +2124,7 @@ final class tx_dlf_document {
// SimpleXMLElement objects can't be serialized, thus save the XML as string for serialization
$this->asXML = $this->xml->asXML();
return array ('uid', 'pid', 'parentid', 'asXML');
return array ('uid', 'pid', 'parentId', 'asXML');
}
@ -2187,7 +2189,7 @@ final class tx_dlf_document {
}
/* No xclasses allowed for this class!
/* No xclasses allowed for final classes!
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_document.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_document.php']);
}

View File

@ -1,6 +1,6 @@
<?php
/***************************************************************
* Copyright notice
* Copyright notice
*
* (c) 2011 Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* All rights reserved
@ -28,14 +28,14 @@
/**
* Interface 'tx_dlf_format' for the 'dlf' extension.
*
* @author Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* @copyright Copyright (c) 2011, Sebastian Meyer, SLUB Dresden
* @package TYPO3
* @subpackage tx_dlf
* @access public
* @abstract
*/
*
* @author Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* @copyright Copyright (c) 2011, Sebastian Meyer, SLUB Dresden
* @package TYPO3
* @subpackage tx_dlf
* @access public
* @abstract
*/
interface tx_dlf_format {
/**
@ -53,8 +53,8 @@ interface tx_dlf_format {
}
/* No xclasses for interfaces!
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_format.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_format.php']);
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_format.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_format.php']);
}
*/

View File

@ -46,22 +46,12 @@ class tx_dlf_helper {
public static $extKey = 'dlf';
/**
* The encryption key
* @see encrypt() / decrypt()
* The locallang array for common use
*
* @var string
* @access private
* @var array
* @access protected
*/
private static $ENCRYPTION_KEY = 'b8b311560d3e6f8dea0aa445995b1b2b';
/**
* The initialization vector for encryption
* @see encrypt() / decrypt()
*
* @var string
* @access private
*/
private static $ENCRYPTION_IV = '381416de30a5c970f8f486aa6d5cc932';
protected static $locallang = array ();
/**
* Searches the array recursively for a given value and returns the corresponding key if successful
@ -253,9 +243,21 @@ class tx_dlf_helper {
}
$iv = substr(self::$ENCRYPTION_IV, 0, mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CFB));
if (empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])) {
$decrypted = mcrypt_decrypt(MCRYPT_BLOWFISH, self::$ENCRYPTION_KEY, base64_decode($encrypted), MCRYPT_MODE_CFB, $iv);
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_helper->decrypt('.$encrypted.', '.$hash.')] No encryption key set in TYPO3 configuration', $this->extKey, SYSLOG_SEVERITY_ERROR);
}
return;
}
$iv = substr(md5($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']), 0, mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CFB));
$decrypted = mcrypt_decrypt(MCRYPT_BLOWFISH, $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'], base64_decode($encrypted), MCRYPT_MODE_CFB, $iv);
$salt = substr($hash, 0, 10);
@ -302,9 +304,21 @@ class tx_dlf_helper {
}
$iv = substr(self::$ENCRYPTION_IV, 0, mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CFB));
if (empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])) {
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_BLOWFISH, self::$ENCRYPTION_KEY, $string, MCRYPT_MODE_CFB, $iv));
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_helper->encrypt('.$string.')] No encryption key set in TYPO3 configuration', $this->extKey, SYSLOG_SEVERITY_ERROR);
}
return;
}
$iv = substr(md5($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']), 0, mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CFB));
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_BLOWFISH, $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'], $string, MCRYPT_MODE_CFB, $iv));
$salt = substr(md5(uniqid(rand(), TRUE)), 0, 10);
@ -330,7 +344,7 @@ class tx_dlf_helper {
return $GLOBALS['BE_USER'];
} elseif (!isset($_COOKIE['be_typo_user'])) {
} elseif (!isset($_COOKIE['be_typo_user'])) { // TODO: Since TYPO3 4.6 the cookie name is configurable in $TYPO3_CONF_VARS['BE']['cookieName']
// Initialize backend session with CLI user's rights.
$userObj = t3lib_div::makeInstance('t3lib_beUserAuth');
@ -530,6 +544,71 @@ class tx_dlf_helper {
}
/**
* Wrapper function for getting localizations in frontend and backend
*
* @param string $key: The locallang key to translate
* @param string $default: Default return value if no translation is available
* @param boolean $hsc: Should the result be htmlspecialchar()'ed?
*
* @return string The translated string or the given key on failure
*/
public static function getLL($key, $default = '', $hsc = FALSE) {
// Set initial output to default value.
$translated = (string) $default;
// Load common locallang file.
if (empty(self::$locallang)) {
$file = t3lib_extMgm::extPath(self::$extKey, 'common/locallang.xml');
if (TYPO3_MODE === 'FE') {
self::$locallang = $GLOBALS['TSFE']->readLLfile($file);
} elseif (TYPO3_MODE === 'BE') {
self::$locallang = $GLOBALS['LANG']->includeLLFile($file, FALSE, TRUE);
} elseif (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_helper->getLL('.$key.', '.$default.', ['.($hsc ? 'TRUE' : 'FALSE').'])] Unexpected TYPO3_MODE "'.TYPO3_MODE.'"', $this->extKey, SYSLOG_SEVERITY_ERROR);
}
}
// Get translation.
if (!empty(self::$locallang['default'][$key])) {
if (TYPO3_MODE === 'FE') {
$translated = $GLOBALS['TSFE']->getLLL($key, self::$locallang);
} elseif (TYPO3_MODE === 'BE') {
$translated = $GLOBALS['LANG']->getLLL($key, self::$locallang, FALSE);
} elseif (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_helper->getLL('.$key.', '.$default.', ['.($hsc ? 'TRUE' : 'FALSE').'])] Unexpected TYPO3_MODE "'.TYPO3_MODE.'"', $this->extKey, SYSLOG_SEVERITY_ERROR);
}
}
// Escape HTML characters if applicable.
if ($hsc) {
$translated = htmlspecialchars($translated);
}
return $translated;
}
/**
* Get the URN of an object
* @see http://www.persistent-identifier.de/?link=316

View File

@ -150,7 +150,7 @@ class tx_dlf_indexing {
}
self::$solr->commit();
self::$solr->service->commit();
// Get document title from database.
$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
@ -271,9 +271,9 @@ class tx_dlf_indexing {
try {
// Delete Solr document.
self::$solr->deleteByQuery('uid:'.$uid);
self::$solr->service->deleteByQuery('uid:'.$uid);
self::$solr->commit();
self::$solr->service->commit();
} catch (Exception $e) {
@ -539,7 +539,7 @@ class tx_dlf_indexing {
try {
self::$solr->addDocument($solrDoc);
self::$solr->service->addDocument($solrDoc);
} catch (Exception $e) {
@ -602,7 +602,7 @@ class tx_dlf_indexing {
if (!self::$solr) {
// Connect to Solr server.
if (self::$solr = tx_dlf_solr::solrConnect($core)) {
if (self::$solr = tx_dlf_solr::getInstance($core)) {
// Load indexing configuration if needed.
if ($pid) {

View File

@ -1,6 +1,6 @@
<?php
/***************************************************************
* Copyright notice
* Copyright notice
*
* (c) 2011 Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* All rights reserved
@ -28,13 +28,13 @@
/**
* Metadata format class 'tx_dlf_mods' for the 'dlf' extension.
*
* @author Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* @copyright Copyright (c) 2011, Sebastian Meyer, SLUB Dresden
* @package TYPO3
* @subpackage tx_dlf
* @access public
*/
*
* @author Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* @copyright Copyright (c) 2011, Sebastian Meyer, SLUB Dresden
* @package TYPO3
* @subpackage tx_dlf
* @access public
*/
class tx_dlf_mods implements tx_dlf_format {
/**

View File

@ -1,6 +1,6 @@
<?php
/***************************************************************
* Copyright notice
* Copyright notice
*
* (c) 2011 Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* All rights reserved
@ -28,14 +28,14 @@
/**
* Base class 'tx_dlf_module' for the 'dlf' extension.
*
* @author Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* @copyright Copyright (c) 2011, Sebastian Meyer, SLUB Dresden
* @package TYPO3
* @subpackage tx_dlf
* @access public
* @abstract
*/
*
* @author Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* @copyright Copyright (c) 2011, Sebastian Meyer, SLUB Dresden
* @package TYPO3
* @subpackage tx_dlf
* @access public
* @abstract
*/
abstract class tx_dlf_module extends t3lib_SCbase {
public $extKey = 'dlf';
@ -232,7 +232,7 @@ abstract class tx_dlf_module extends t3lib_SCbase {
/* No xclasses for abstract classes!
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_module.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_module.php']);
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_module.php']);
}
*/

View File

@ -1,6 +1,6 @@
<?php
/***************************************************************
* Copyright notice
* Copyright notice
*
* (c) 2011 Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* All rights reserved
@ -28,14 +28,14 @@
/**
* Base class 'tx_dlf_plugin' for the 'dlf' extension.
*
* @author Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* @copyright Copyright (c) 2011, Sebastian Meyer, SLUB Dresden
* @package TYPO3
* @subpackage tx_dlf
* @access public
* @abstract
*/
*
* @author Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* @copyright Copyright (c) 2011, Sebastian Meyer, SLUB Dresden
* @package TYPO3
* @subpackage tx_dlf
* @access public
* @abstract
*/
abstract class tx_dlf_plugin extends tslib_pibase {
public $extKey = 'dlf';
@ -317,7 +317,7 @@ abstract class tx_dlf_plugin extends tslib_pibase {
/* No xclasses for abstract classes!
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_plugin.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_plugin.php']);
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_plugin.php']);
}
*/

View File

@ -1,6 +1,6 @@
<?php
/***************************************************************
* Copyright notice
* Copyright notice
*
* (c) 2011 Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* All rights reserved
@ -24,27 +24,158 @@
// TODO: Clean up and reduce code duplication. Consider switching to Solarium.
/**
* [CLASS/FUNCTION INDEX of SCRIPT]
*/
*/
/**
* Solr class 'tx_dlf_solr' for the 'dlf' extension.
*
* @author Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* @author Henrik Lochmann <dev@mentalmotive.com>
* @copyright Copyright (c) 2011, Sebastian Meyer, SLUB Dresden
* @package TYPO3
* @subpackage tx_dlf
* @access public
*/
*
* @author Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* @author Henrik Lochmann <dev@mentalmotive.com>
* @copyright Copyright (c) 2011, Sebastian Meyer, SLUB Dresden
* @package TYPO3
* @subpackage tx_dlf
* @access public
*/
class tx_dlf_solr {
/**
* This holds the core name
*
* @var string
* @access protected
*/
protected $core = '';
/**
* This holds the PID for the configuration
*
* @var integer
* @access protected
*/
protected $cPid = 0;
/**
* The extension key
*
* @var string
* @access public
*/
public static $extKey = 'dlf';
public $extKey = 'dlf';
/**
* This holds the filter query
*
* @var array
* @access protected
*/
protected $filter = array ();
/**
* This holds the max results
*
* @var integer
* @access protected
*/
protected $limit = 50000;
/**
* This holds the number of hits for last search
*
* @var integer
* @access protected
*/
protected $numberOfHits = 0;
/**
* Is the search instantiated successfully?
*
* @var boolean
* @access protected
*/
protected $ready = FALSE;
/**
* This holds the singleton search objects with their core as array key
*
* @var array(tx_dlf_solr)
* @access protected
*/
protected static $registry = array ();
/**
* This holds the Solr service object
*
* @var Apache_Solr_Service
* @access protected
*/
protected $service;
/**
* This is a singleton class, thus instances must be created by this method
*
* @access public
*
* @param mixed $core: Name or UID of the core to load
*
* @return tx_dlf_solr Instance of this class
*/
public static function getInstance($core) {
// Save parameter for logging purposes.
$_core = $core;
// Get core name if UID is given.
if (t3lib_div::testInt($core)) {
$core = tx_dlf_helper::getIndexName($core, 'tx_dlf_solrcores');
}
// Check if core is set.
if (empty($core)) {
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_solr->getInstance('.$_core.')] Invalid core name "'.$core.'" for Apache Solr', $this->extKey, SYSLOG_SEVERITY_ERROR);
}
return;
}
// Check if there is an instance in the registry already.
if (is_object(self::$registry[$core]) && self::$registry[$core] instanceof self) {
// Return singleton instance if available.
return self::$registry[$core];
}
// Create new instance...
$instance = new self($core);
// ...and save it to registry.
if ($instance->ready) {
self::$registry[$core] = $instance;
// Return new instance.
return $instance;
} else {
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_solr->getInstance('.$_core.')] Could not connect to Apache Solr server', $this->extKey, SYSLOG_SEVERITY_ERROR);
}
return;
}
}
/**
* Returns the request URL for a specific Solr core
@ -82,19 +213,428 @@ class tx_dlf_solr {
}
/**
* Get SolrPhpClient service object and establish connection to Solr server
* @see EXT:dlf/lib/SolrPhpClient/Apache/Solr/Service.php
* Get next unused Solr core number
*
* @access public
*
* @param mixed $core: Name or UID of the core to load
* @param integer $start: Number to start with
*
* @return mixed Instance of Apache_Solr_Service or NULL on failure
* @return integer First unused core number found
*/
public static function solrConnect($core = 0) {
public static function solrGetCoreNumber($start = 0) {
// Save parameter for logging purposes.
$_core = $core;
$start = max(intval($start), 0);
// Check if core already exists.
if (self::getInstance('dlfCore'.$start) === NULL) {
return $start;
} else {
return self::solrGetCoreNumber($start + 1);
}
}
/**
* Processes a search request.
*
* @access public
*
* @param string $query: The search query
*
* @return tx_dlf_list The result list
*/
public function search($query = '*') {
// Sanitize query string.
$query = (string) $query;
if (empty($query)) {
$query = '*';
}
// Perform search.
$query = $this->service->search($query, 0, $this->limit, $this->filter);
$this->numberOfHits = count($query->response->docs);
$toplevel = array ();
$checks = array ();
// Get metadata configuration.
if ($numHits) {
$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
'tx_dlf_metadata.index_name AS index_name,tx_dlf_metadata.tokenized AS tokenized,tx_dlf_metadata.indexed AS indexed,tx_dlf_metadata.is_listed AS is_listed,tx_dlf_metadata.is_sortable AS is_sortable',
'tx_dlf_metadata',
'(tx_dlf_metadata.is_listed=1 OR tx_dlf_metadata.is_sortable=1) AND tx_dlf_metadata.pid='.intval($this->cPid).tx_dlf_helper::whereClause('tx_dlf_metadata'),
'',
'tx_dlf_metadata.sorting ASC',
''
);
$metadata = array ();
$sorting = array ();
while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
if ($resArray['is_listed']) {
$metadata[$resArray['index_name']] = $resArray['index_name'].'_'.($resArray['tokenized'] ? 't' : 'u').'s'.($resArray['indexed'] ? 'i' : 'u');
}
if ($resArray['is_sortable']) {
$sorting[$resArray['index_name']] = $resArray['index_name'].'_sorting';
}
}
}
// Keep track of relevance.
$i = 0;
// Process results.
foreach ($query->response->docs as $doc) {
// Prepate document's metadata.
$docMeta = array ();
foreach ($metadata as $index_name => $solr_name) {
if (!empty($doc->$solr_name)) {
$docMeta[$index_name] = (is_array($doc->$solr_name) ? $doc->$solr_name : array ($doc->$solr_name));
}
}
// Prepate document's metadata for sorting.
$docSorting = array ();
foreach ($sorting as $index_name => $solr_name) {
if (!empty($doc->$solr_name)) {
$docSorting[$index_name] = (is_array($doc->$solr_name) ? $doc->$solr_name[0] : $doc->$solr_name);
}
}
// Add relevance to sorting values.
$docSorting['relevance'] = str_pad($i, 6, '0', STR_PAD_LEFT);
// Split toplevel documents from subparts.
if ($doc->toplevel == 1) {
$toplevel[$doc->uid] = array (
'uid' => $doc->uid,
'page' => $doc->page,
'metadata' => $docMeta,
'sorting' => $docSorting,
'subparts' => (!empty($toplevel[$doc->uid]['subparts']) ? $toplevel[$doc->uid]['subparts'] : array ())
);
} else {
$toplevel[$doc->uid]['subparts'][] = array (
'uid' => $doc->uid,
'page' => $doc->page,
'metadata' => $docMeta,
'sorting' => $docSorting
);
if (!in_array($doc->uid, $check)) {
$checks[] = $doc->uid;
}
}
$i++;
}
// Check if the toplevel documents have metadata.
foreach ($checks as $check) {
if (empty($toplevel[$check]['uid'])) {
// Get information for toplevel document.
$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
'tx_dlf_documents.uid AS uid,tx_dlf_documents.metadata AS metadata,tx_dlf_documents.metadata_sorting AS metadata_sorting',
'tx_dlf_documents',
'tx_dlf_documents.uid='.intval($check).tx_dlf_helper::whereClause('tx_dlf_documents'),
'',
'',
'1'
);
// Process results.
if ($GLOBALS['TYPO3_DB']->sql_num_rows($result)) {
$resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
// Prepare document's metadata.
$metadata = unserialize($resArray['metadata']);
if (!empty($metadata['type'][0]) && t3lib_div::testInt($metadata['type'][0])) {
$metadata['type'][0] = tx_dlf_helper::getIndexName($metadata['type'][0], 'tx_dlf_structures', $this->cPid);
}
if (!empty($metadata['owner'][0]) && t3lib_div::testInt($metadata['owner'][0])) {
$metadata['owner'][0] = tx_dlf_helper::getIndexName($metadata['owner'][0], 'tx_dlf_libraries', $this->cPid);
}
if (!empty($metadata['collection']) && is_array($metadata['collection'])) {
foreach ($metadata['collection'] as $i => $collection) {
if (t3lib_div::testInt($collection)) {
$metadata['collection'][$i] = tx_dlf_helper::getIndexName($metadata['collection'][$i], 'tx_dlf_collections', $this->cPid);
}
}
}
// Prepare document's metadata for sorting.
$sorting = unserialize($resArray['metadata_sorting']);
if (!empty($sorting['type']) && t3lib_div::testInt($sorting['type'])) {
$sorting['type'] = tx_dlf_helper::getIndexName($sorting['type'], 'tx_dlf_structures', $this->cPid);
}
if (!empty($sorting['owner']) && t3lib_div::testInt($sorting['owner'])) {
$sorting['owner'] = tx_dlf_helper::getIndexName($sorting['owner'], 'tx_dlf_libraries', $this->cPid);
}
if (!empty($sorting['collection']) && t3lib_div::testInt($sorting['collection'])) {
$sorting['collection'] = tx_dlf_helper::getIndexName($sorting['collection'], 'tx_dlf_collections', $this->cPid);
}
$toplevel[$check] = array (
'uid' => $resArray['uid'],
'page' => 1,
'metadata' => $metadata,
'sorting' => $sorting,
'subparts' => $toplevel[$check]['subparts']
);
} else {
// Clear entry if there is no (accessible) toplevel document.
unset ($toplevel[$check]);
}
}
}
// Save list of documents.
$list = t3lib_div::makeInstance('tx_dlf_list');
$list->reset();
$list->add(array_values($toplevel));
// Set metadata for search.
$list->metadata = array (
'label' => '',
'description' => '',
'options' => array (
'source' => 'search',
'select' => $query,
'filter' => $this->filter,
'order' => 'relevance'
)
);
return $list;
}
/**
* This returns $this->numberOfHits via __get()
*
* @access protected
*
* @return integer Total number of hits for last search
*/
protected function _getNumberOfHits() {
return $this->numberOfHits;
}
/**
* This returns $this->ready via __get()
*
* @access protected
*
* @return boolean Is the search instantiated successfully?
*/
protected function _getReady() {
return $this->ready;
}
/**
* This returns $this->service via __get()
*
* @access protected
*
* @return Apache_Solr_Service Apache Solr service object
*/
protected function _getService() {
return $this->service;
}
/**
* This sets $this->cPid via __set()
*
* @access protected
*
* @param integer $value: The new PID for the metadata definitions
*
* @return void
*/
protected function _setCPid($value) {
$this->cPid = max(intval($value), 0);
}
/**
* This sets $this->filter via __set()
*
* @access protected
*
* @param array $value: The filter query
*
* @return void
*/
protected function _setFilter(array $value) {
$this->filter = $value;
}
/**
* This sets $this->limit via __set()
*
* @access protected
*
* @param integer $value: The max number of results
*
* @return void
*/
protected function _setLimit($value) {
$this->limit = max(intval($value), 0);
}
/**
* This magic method is called each time an invisible property is referenced from the object
*
* @access public
*
* @param string $var: Name of variable to get
*
* @return mixed Value of $this->$var
*/
public function __get($var) {
$method = '_get'.ucfirst($var);
if (!property_exists($this, $var) || !method_exists($this, $method)) {
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_solr->__get('.$var.')] There is no getter function for property "'.$var.'"', $this->extKey, SYSLOG_SEVERITY_WARNING);
}
return;
} else {
return $this->$method();
}
}
/**
* This magic method is called each time an invisible property is referenced from the object
*
* @access public
*
* @param string $var: Name of variable to set
* @param mixed $value: New value of variable
*
* @return void
*/
public function __set($var, $value) {
$method = '_set'.ucfirst($var);
if (!property_exists($this, $var) || !method_exists($this, $method)) {
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_solr->__set('.$var.', '.$value.')] There is no setter function for property "'.$var.'"', $this->extKey, SYSLOG_SEVERITY_WARNING);
}
} else {
$this->$method($value);
}
}
/**
* This is a singleton class, thus the constructor should be private/protected
*
* @access protected
*
* @param string $core: The name of the core to use
*
* @return void
*/
protected function __construct($core) {
// Load class.
if (!class_exists('Apache_Solr_Service')) {
@ -118,92 +658,33 @@ class tx_dlf_solr {
// Set port if not set.
$port = t3lib_div::intInRange($conf['solrPort'], 1, 65535, 8180);
// Get core name if UID is given.
if (t3lib_div::testInt($core)) {
$core = tx_dlf_helper::getIndexName($core, 'tx_dlf_solrcores');
if (empty($core)) {
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_solr->solrConnect('.$_core.')] Invalid UID "'.$_core.'" for Apache Solr core', $this->extKey, SYSLOG_SEVERITY_ERROR);
}
return;
}
}
// Append core name to path.
$path = trim($conf['solrPath'], '/').'/'.$core;
// Instantiate Apache_Solr_Service class.
$solr = t3lib_div::makeInstance('Apache_Solr_Service', $host, $port, $path);
$this->service = t3lib_div::makeInstance('Apache_Solr_Service', $host, $port, $path);
// Check if connection is established.
if ($solr->ping() !== FALSE) {
if ($this->service->ping() !== FALSE) {
// Do not collapse single value arrays.
$solr->setCollapseSingleValueArrays = FALSE;
$this->service->setCollapseSingleValueArrays = FALSE;
return $solr;
// Set core name.
$this->core = $core;
} else {
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_solr->solrConnect('.$_core.')] Could not connect to Apache Solr server with core "'.$core.'"', $this->extKey, SYSLOG_SEVERITY_ERROR);
}
return;
// Instantiation successful!
$this->ready = TRUE;
}
}
/**
* Get next unused Solr core number
*
* @access public
*
* @param integer $start: Number to start with
*
* @return integer First unused core number found
*/
public static function solrGetCoreNumber($start = 0) {
$start = max(intval($start), 0);
// Check if core already exists.
if (self::solrConnect('dlfCore'.$start) === NULL) {
return $start;
} else {
return self::solrGetCoreNumber($start + 1);
}
}
/**
* This is a static class, thus no instances should be created
*
* @access protected
*/
protected function __construct() {
}
}
/* No xclasses for static classes!
/* No xclasses allowed for singleton classes!
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_solr.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_solr.php']);
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/common/class.tx_dlf_solr.php']);
}
*/

15
dlf/common/locallang.xml Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3locallang>
<meta type="array">
<type>module</type>
<description>Common language labels for extension 'dlf'</description>
</meta>
<data type="array">
<languageKey index="default" type="array">
<label index="demo">demo</label>
</languageKey>
<languageKey index="de" type="array">
<label index="demo">demo</label>
</languageKey>
</data>
</T3locallang>

View File

@ -197,7 +197,7 @@ $TCA['tx_dlf_libraries'] = array (
);
// Register static typoscript.
t3lib_extMgm::addStaticFile($_EXTKEY, 'typoscript/', 'DLF (Base Configuration)');
t3lib_extMgm::addStaticFile($_EXTKEY, 'typoscript/', 'Basic Configuration');
// Register plugins.
t3lib_div::loadTCA('tt_content');
@ -272,6 +272,8 @@ $TCA['tt_content']['types']['list']['subtypes_addlist'][$_EXTKEY.'_search'] = 'p
t3lib_extMgm::addPlugin(array('LLL:EXT:dlf/locallang.xml:tt_content.dlf_search', $_EXTKEY.'_search'), 'list_type');
t3lib_extMgm::addStaticFile($_EXTKEY, 'plugins/search/', 'Search Facets');
t3lib_extMgm::addPiFlexFormValue($_EXTKEY.'_search', 'FILE:EXT:'.$_EXTKEY.'/plugins/search/flexform.xml');
// Plugin "statistics".

View File

@ -92,6 +92,61 @@ class tx_dlf_tceforms {
}
/**
* Helper to get flexform's items array for plugin "tx_dlf_search"
*
* @access public
*
* @param array &$params: An array with parameters
* @param t3lib_TCEforms &$pObj: The parent object
*
* @return void
*/
public function itemsProcFunc_facetsList(&$params, &$pObj) {
if ($params['row']['pi_flexform']) {
$pi_flexform = t3lib_div::xml2array($params['row']['pi_flexform']);
$pages = $pi_flexform['data']['sDEF']['lDEF']['pages']['vDEF'];
// There is a strange behavior where the uid from the flexform is prepended by the table's name and appended by its title.
// i.e. instead of "18" it reads "pages_18|Title"
if (!t3lib_div::testInt($pages)) {
$_parts = explode('|', $pages);
$pages = array_pop(explode('_', $_parts[0]));
}
if ($pages > 0) {
$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
'label,index_name',
'tx_dlf_metadata',
'is_facet=1 AND pid='.intval($pages).' AND (sys_language_uid IN (-1,0) OR l18n_parent=0)'.tx_dlf_helper::whereClause('tx_dlf_metadata'),
'',
'sorting',
''
);
if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) {
while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_row($result)) {
$params['items'][] = $resArray;
}
}
}
}
}
/**
* Helper to get flexform's items array for plugin "tx_dlf_oai"
*

View File

@ -263,12 +263,12 @@ class tx_dlf_tcemain {
if ($fieldArray['hidden']) {
// Establish Solr connection.
if ($solr = tx_dlf_solr::solrConnect($core)) {
if ($solr = tx_dlf_solr::getInstance($core)) {
// Delete Solr document.
$solr->deleteByQuery('uid:'.$id);
$solr->service->deleteByQuery('uid:'.$id);
$solr->commit();
$solr->service->commit();
}
@ -345,9 +345,9 @@ class tx_dlf_tcemain {
if ($solr = tx_dlf_solr::solrConnect($core)) {
// Delete Solr document.
$solr->deleteByQuery('uid:'.$id);
$solr->service->deleteByQuery('uid:'.$id);
$solr->commit();
$solr->service->commit();
if ($command == 'delete') {

View File

@ -258,7 +258,7 @@ class tx_dlf_collection extends tx_dlf_plugin {
// Get all documents in collection.
$result = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query(
'tx_dlf_collections.label AS collLabel,tx_dlf_collections.description AS collDesc,tx_dlf_documents.uid AS uid,tx_dlf_documents.metadata AS metadata,tx_dlf_documents.metadata_sorting AS metadata_sorting,tx_dlf_documents.volume_sorting AS volume_sorting,tx_dlf_documents.partof AS partof',
'tx_dlf_collections.index_name AS index_name,tx_dlf_collections.label AS collLabel,tx_dlf_collections.description AS collDesc,tx_dlf_documents.uid AS uid,tx_dlf_documents.metadata AS metadata,tx_dlf_documents.metadata_sorting AS metadata_sorting,tx_dlf_documents.volume_sorting AS volume_sorting,tx_dlf_documents.partof AS partof',
'tx_dlf_documents',
'tx_dlf_relations',
'tx_dlf_collections',
@ -283,6 +283,7 @@ class tx_dlf_collection extends tx_dlf_plugin {
'options' => array (
'source' => 'collection',
'select' => $id,
'filter' => array ('collection_faceting:"'.$resArray['index_name'].'"'),
'order' => 'title'
)
);

View File

@ -1,6 +1,6 @@
<?php
/***************************************************************
* Copyright notice
* Copyright notice
*
* (c) 2011 Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* All rights reserved
@ -79,14 +79,12 @@ class tx_dlf_search extends tx_dlf_plugin {
*
* @access protected
*
* @param integer $core: UID of the core
*
* @return string HTML input fields with encrypted core name and hash
*/
protected function addEncryptedCoreName($core) {
protected function addEncryptedCoreName() {
// Get core name.
$name = tx_dlf_helper::getIndexName($core, 'tx_dlf_solrcores');
$name = tx_dlf_helper::getIndexName($this->conf['solrcore'], 'tx_dlf_solrcores');
// Encrypt core name.
if (!empty($name)) {
@ -108,6 +106,129 @@ class tx_dlf_search extends tx_dlf_plugin {
}
/**
* Adds the facets menu to the search form
*
* @access protected
*
* @return string HTML output of facets menu
*/
protected function addFacetsMenu() {
// Check for typoscript configuration to prevent fatal error.
if (empty($this->conf['facetsConf.'])) {
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_search->addFacetsMenu()] Incomplete plugin configuration', $this->extKey, SYSLOG_SEVERITY_WARNING);
}
return '';
}
// Quit without doing anything if no facets are selected.
if (empty($this->conf['facets'])) {
return '';
}
// Get facets from plugin configuration.
$facets = array ();
foreach (t3lib_div::trimExplode(',', $this->conf['facets'], TRUE) as $facet) {
$facets[$facet] = tx_dlf_helper::translate($facet, 'tx_dlf_metadata', $this->conf['pages']);
}
// Render facets menu.
$TSconfig = array ();
$TSconfig['special'] = 'userfunction';
$TSconfig['special.']['userFunc'] = 'tx_dlf_search->makeFacetsMenuArray';
$TSconfig['special.']['facets'] = $facets;
$TSconfig = t3lib_div::array_merge_recursive_overrule($this->conf['facetsConf.'], $TSconfig);
return $this->cObj->HMENU($TSconfig);
}
/**
* Creates an array for a HMENU entry of a facet value.
*
* @param string $field: The facet's index_name
* @param string $value: The facet's value
* @param integer $count: Number of hits for this facet
* @param array $search: The parameters of the current search query
* @param string &$state: The state of the parent item
*
* @return array The array for the facet's menu entry
*/
protected function getFacetsMenuEntry($field, $value, $count, $search, &$state) {
$entryArray = array();
// Translate value.
if ($field == 'owner_faceting') {
// Translate name of holding library.
$entryArray['title'] = tx_dlf_helper::translate($value, 'tx_dlf_libraries', $this->conf['pages']);
} elseif ($field == 'type_faceting') {
// Translate document type.
$entryArray['title'] = tx_dlf_helper::translate($value, 'tx_dlf_structures', $this->conf['pages']);
} elseif ($field == 'language_faceting') {
// Translate ISO 639 language code.
$entryArray['title'] = tx_dlf_helper::getLanguageName($value);
} else {
$entryArray['title'] = $value;
}
$entryArray['count'] = $count;
$entryArray['doNotLinkIt'] = 0;
// Check if facet is already selected.
$index = array_search($field.':"'.$value.'"', $search['fq']);
if ($index !== FALSE) {
// Facet is selected, thus remove it from filter.
unset($search['fq'][$index]);
$search['fq'] = array_values($search['fq']);
$entryArray['ITEM_STATE'] = 'CUR';
$state = 'ACTIFSUB';
} else {
// Facet is not selected, thus add it to filter.
$search['fq'][] = $field.':"'.$value.'"';
$entryArray['ITEM_STATE'] = 'NO';
}
$entryArray['_OVERRIDE_HREF'] = $this->pi_linkTP_keepPIvars_url(array ('query' => $search['query'], 'fq' => $search['fq']));
return $entryArray;
}
/**
* The main method of the PlugIn
*
@ -138,7 +259,7 @@ class tx_dlf_search extends tx_dlf_plugin {
}
if (empty($this->piVars['query'])) {
if (!isset($this->piVars['query'])) {
// Add javascript for autocompletion if available.
$autocomplete = $this->addAutocompleteJS();
@ -172,241 +293,53 @@ class tx_dlf_search extends tx_dlf_plugin {
'###LABEL_SUBMIT###' => $this->pi_getLL('label.submit'),
'###FIELD_QUERY###' => $this->prefixId.'[query]',
'###QUERY###' => htmlspecialchars($lastQuery),
'###ADDITIONAL_INPUTS###' => '',
'###ADDITIONAL_INPUTS###' => $this->addEncryptedCoreName(),
'###FACETS_MENU###' => $this->addFacetsMenu()
);
// Encrypt Solr core name and add as hidden input field to the search form.
if ($autocomplete) {
$markerArray['###ADDITIONAL_INPUTS###'] = $this->addEncryptedCoreName($this->conf['solrcore']);
}
// Display search form.
$content .= $this->cObj->substituteMarkerArray($this->template, $markerArray);
return $this->pi_wrapInBaseClass($content);
} elseif (($solr = tx_dlf_solr::solrConnect($this->conf['solrcore'])) !== NULL) {
} else {
// Instantiate search object.
$solr = tx_dlf_solr::getInstance($this->conf['solrcore']);
if (!$solr->ready) {
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_search->main('.$content.', [data])] Apache Solr not available', $this->extKey, SYSLOG_SEVERITY_ERROR, $conf);
}
return $content;
}
// Set search parameters.
$solr->limit = $this->conf['limit'];
$solr->cPid = $this->conf['pages'];
if (!empty($this->piVars['fq'])) {
$solr->filter = $this->piVars['fq'];
}
// Perform search.
$query = $solr->search($this->piVars['query'], 0, $this->conf['limit'], array ());
$results = $solr->search($this->piVars['query']);
$numHits = count($query->response->docs);
$toplevel = array ();
$checks = array ();
// Get metadata configuration.
if ($numHits) {
$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
'tx_dlf_metadata.index_name AS index_name,tx_dlf_metadata.tokenized AS tokenized,tx_dlf_metadata.indexed AS indexed,tx_dlf_metadata.is_listed AS is_listed,tx_dlf_metadata.is_sortable AS is_sortable',
'tx_dlf_metadata',
'(tx_dlf_metadata.is_listed=1 OR tx_dlf_metadata.is_sortable=1) AND tx_dlf_metadata.pid='.intval($this->conf['pages']).tx_dlf_helper::whereClause('tx_dlf_metadata'),
'',
'tx_dlf_metadata.sorting ASC',
''
);
$metadata = array ();
$sorting = array ();
while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
if ($resArray['is_listed']) {
$metadata[$resArray['index_name']] = $resArray['index_name'].'_'.($resArray['tokenized'] ? 't' : 'u').'s'.($resArray['indexed'] ? 'i' : 'u');
}
if ($resArray['is_sortable']) {
$sorting[$resArray['index_name']] = $resArray['index_name'].'_sorting';
}
}
}
// Keep track of relevance.
$i = 0;
// Process results.
foreach ($query->response->docs as $doc) {
// Prepate document's metadata.
$docMeta = array ();
foreach ($metadata as $index_name => $solr_name) {
if (!empty($doc->$solr_name)) {
$docMeta[$index_name] = (is_array($doc->$solr_name) ? $doc->$solr_name : array ($doc->$solr_name));
}
}
// Prepate document's metadata for sorting.
$docSorting = array ();
foreach ($sorting as $index_name => $solr_name) {
if (!empty($doc->$solr_name)) {
$docSorting[$index_name] = (is_array($doc->$solr_name) ? $doc->$solr_name[0] : $doc->$solr_name);
}
}
// Add relevance to sorting values.
$docSorting['relevance'] = str_pad($i, 6, '0', STR_PAD_LEFT);
// Split toplevel documents from subparts.
if ($doc->toplevel == 1) {
$toplevel[$doc->uid] = array (
'uid' => $doc->uid,
'page' => $doc->page,
'metadata' => $docMeta,
'sorting' => $docSorting,
'subparts' => (!empty($toplevel[$doc->uid]['subparts']) ? $toplevel[$doc->uid]['subparts'] : array ())
);
} else {
$toplevel[$doc->uid]['subparts'][] = array (
'uid' => $doc->uid,
'page' => $doc->page,
'metadata' => $docMeta,
'sorting' => $docSorting
);
if (!in_array($doc->uid, $check)) {
$checks[] = $doc->uid;
}
}
$i++;
}
// Check if the toplevel documents have metadata.
foreach ($checks as $check) {
if (empty($toplevel[$check]['uid'])) {
// Get information for toplevel document.
$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
'tx_dlf_documents.uid AS uid,tx_dlf_documents.metadata AS metadata,tx_dlf_documents.metadata_sorting AS metadata_sorting',
'tx_dlf_documents',
'tx_dlf_documents.uid='.intval($check).tx_dlf_helper::whereClause('tx_dlf_documents'),
'',
'',
'1'
);
// Process results.
if ($GLOBALS['TYPO3_DB']->sql_num_rows($result)) {
$resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
// Prepare document's metadata.
$metadata = unserialize($resArray['metadata']);
if (!empty($metadata['type'][0]) && t3lib_div::testInt($metadata['type'][0])) {
$metadata['type'][0] = tx_dlf_helper::getIndexName($metadata['type'][0], 'tx_dlf_structures', $this->conf['pages']);
}
if (!empty($metadata['owner'][0]) && t3lib_div::testInt($metadata['owner'][0])) {
$metadata['owner'][0] = tx_dlf_helper::getIndexName($metadata['owner'][0], 'tx_dlf_libraries', $this->conf['pages']);
}
if (!empty($metadata['collection']) && is_array($metadata['collection'])) {
foreach ($metadata['collection'] as $i => $collection) {
if (t3lib_div::testInt($collection)) {
$metadata['collection'][$i] = tx_dlf_helper::getIndexName($metadata['collection'][$i], 'tx_dlf_collections', $this->conf['pages']);
}
}
}
// Prepare document's metadata for sorting.
$sorting = unserialize($resArray['metadata_sorting']);
if (!empty($sorting['type']) && t3lib_div::testInt($sorting['type'])) {
$sorting['type'] = tx_dlf_helper::getIndexName($sorting['type'], 'tx_dlf_structures', $this->conf['pages']);
}
if (!empty($sorting['owner']) && t3lib_div::testInt($sorting['owner'])) {
$sorting['owner'] = tx_dlf_helper::getIndexName($sorting['owner'], 'tx_dlf_libraries', $this->conf['pages']);
}
if (!empty($sorting['collection']) && t3lib_div::testInt($sorting['collection'])) {
$sorting['collection'] = tx_dlf_helper::getIndexName($sorting['collection'], 'tx_dlf_collections', $this->conf['pages']);
}
$toplevel[$check] = array (
'uid' => $resArray['uid'],
'page' => 1,
'metadata' => $metadata,
'sorting' => $sorting,
'subparts' => $toplevel[$check]['subparts']
);
} else {
// Clear entry if there is no (accessible) toplevel document.
unset ($toplevel[$check]);
}
}
}
// Save list of documents.
$list = t3lib_div::makeInstance('tx_dlf_list');
$list->reset();
$list->add(array_values($toplevel));
// Set metadata for search.
$list->metadata = array (
$results->metadata = array (
'label' => htmlspecialchars(sprintf($this->pi_getLL('searchfor', ''), $this->piVars['query'])),
'description' => '<p class="tx-dlf-search-numHits">'.htmlspecialchars(sprintf($this->pi_getLL('hits', ''), $numHits, count($toplevel))).'</p>',
'options' => array (
'source' => 'search',
'select' => $this->piVars['query'],
'order' => 'relevance'
)
'description' => '<p class="tx-dlf-search-numHits">'.htmlspecialchars(sprintf($this->pi_getLL('hits', ''), $solr->numHits, $results->count)).'</p>',
'options' => $results->metadata['options']
);
$list->save();
$results->save();
// Clean output buffer.
t3lib_div::cleanOutputBuffers();
@ -423,6 +356,127 @@ class tx_dlf_search extends tx_dlf_plugin {
}
/**
* This builds a menu array for HMENU
*
* @access public
*
* @param string $content: The PlugIn content
* @param array $conf: The PlugIn configuration
*
* @return array HMENU array
*/
public function makeFacetsMenuArray($content, $conf) {
$this->init($conf);
$menuArray = array ();
// Set default values for facet search.
$search = array (
'query' => '*',
'fq' => array ()
);
// Extract query and filter from last search.
$list = t3lib_div::makeInstance('tx_dlf_list');
if (!empty($list->metadata['options']['source'])) {
if ($list->metadata['options']['source'] == 'search') {
$search['query'] = $list->metadata['options']['select'];
}
$search['fq'] = $list->metadata['options']['filter'];
}
// Get applicable facets.
$solr = tx_dlf_solr::getInstance($this->conf['solrcore']);
if (!$solr->ready) {
if (TYPO3_DLOG) {
t3lib_div::devLog('[tx_dlf_search->makeFacetsMenuArray('.$content.', [data])] Apache Solr not available', $this->extKey, SYSLOG_SEVERITY_ERROR, $conf);
}
return array ();
}
$params = array (
'facet' => 'true',
'fq' => $search['fq'],
'facet.field' => array ()
);
foreach ($this->conf['facets'] as $field => $label) {
$params['facet.field'][] = $field.'_faceting';
}
// Perform search.
$results = $solr->service->search($search['query'], 0, $this->conf['limit'], $params);
// Process results.
foreach ($results->facet_counts->facet_fields as $field => $values) {
$hasValue = FALSE;
$entryArray = array ();
$entryArray['title'] = $this->conf['facets'][$field];
$entryArray['count'] = 0;
$entryArray['_OVERRIDE_HREF'] = '';
$entryArray['doNotLinkIt'] = 1;
$entryArray['ITEM_STATE'] = 'NO';
foreach ($values as $value => $count) {
if ($count > 0) {
$hasValue = TRUE;
$entryArray['count']++;
$entryArray['ITEM_STATE'] = 'IFSUB';
$entryArray['_SUB_MENU'][] = $this->getFacetsMenuEntry($field, $value, $count, $search, $entryArray['ITEM_STATE']);
}
}
if (!$hasValue) {
$entryArray['_SUB_MENU'][] = array (
'title' => $this->pi_getLL('noFacets', ''),
'count' => 0,
'_OVERRIDE_HREF' => '',
'doNotLinkIt' => 1,
'ITEM_STATE' => 'NO'
);
}
$menuArray[] = $entryArray;
}
return $menuArray;
}
}
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/dlf/plugins/search/class.tx_dlf_search.php']) {

View File

@ -53,6 +53,22 @@
</config>
</TCEforms>
</limit>
<facets>
<TCEforms>
<displayCond>FIELD:pages:REQ:true</displayCond>
<exclude>1</exclude>
<label>LLL:EXT:dlf/plugins/search/locallang.xml:tt_content.pi_flexform.facets</label>
<config>
<type>select</type>
<items type="array"></items>
<itemsProcFunc>tx_dlf_tceforms->itemsProcFunc_facetsList</itemsProcFunc>
<size>5</size>
<autoSizeMax>15</autoSizeMax>
<maxitems>1024</maxitems>
<minitems>0</minitems>
</config>
</TCEforms>
</facets>
<targetPid>
<TCEforms>
<exclude>1</exclude>

View File

@ -9,6 +9,7 @@
<label index="tt_content.pi_flexform.sheet_general">Options</label>
<label index="tt_content.pi_flexform.solrcore">Solr Core</label>
<label index="tt_content.pi_flexform.limit">Maximum results</label>
<label index="tt_content.pi_flexform.facets">Show these facets</label>
<label index="tt_content.pi_flexform.targetPid">Target page (with "DLF: List View" plugin)</label>
<label index="tt_content.pi_flexform.separator">Separator for metadata in TS array</label>
<label index="tt_content.pi_flexform.templateFile">Template file</label>
@ -16,11 +17,13 @@
<label index="label.submit">Search</label>
<label index="searchfor">Search for: "%s"</label>
<label index="hits">%d hits found in %d documents.</label>
<label index="noFacets">no facets</label>
</languageKey>
<languageKey index="de" type="array">
<label index="tt_content.pi_flexform.sheet_general">Einstellungen</label>
<label index="tt_content.pi_flexform.solrcore">Solr Kern</label>
<label index="tt_content.pi_flexform.limit">Maximale Ergebnismenge</label>
<label index="tt_content.pi_flexform.facets">Diese Facetten anzeigen</label>
<label index="tt_content.pi_flexform.targetPid">Zielseite (mit Plugin "DLF: Listenansicht")</label>
<label index="tt_content.pi_flexform.separator">Trennzeichen für Metadaten im TS-Array</label>
<label index="tt_content.pi_flexform.templateFile">HTML-Template</label>
@ -28,6 +31,7 @@
<label index="label.submit">Suchen</label>
<label index="searchfor">Suche nach: "%s"</label>
<label index="hits">Die Suche ergab %d Treffer in %d Dokumenten.</label>
<label index="noFacets">keine Einträge</label>
</languageKey>
</data>
</T3locallang>

View File

@ -0,0 +1,28 @@
plugin.tx_dlf_search.facetsConf {
expAll = 0
1 = TMENU
1 {
noBlur = 1
wrap = <ul>|</ul>
NO = 1
NO {
stdWrap {
wrap = <h2>|</h2>
crop = 55 | &nbsp;... | 1
append.fieldRequired = count
append = TEXT
append.field = count
append.wrap = &nbsp;(|)
}
doNotLinkIt.field = doNotLinkIt
wrapItemAndSub = <li>|</li>
}
ACT < .NO
ACT.wrapItemAndSub = <li class="tx-dlf-search-act">|</li>
}
2 < .1
2 {
NO.stdWrap.wrap >
ACT.stdWrap.wrap >
}
}

View File

@ -4,5 +4,6 @@
<input type="text" id="###FIELD_QUERY###" name="###FIELD_QUERY###" value="###QUERY###" class="tx-dlf-search-query" autocomplete="off" role="textbox" aria-autocomplete="list" aria-haspopup="true">
<input type="submit" value="###LABEL_SUBMIT###" />
###ADDITIONAL_INPUTS###
###FACETS_MENU###
</form>
<!-- ###TEMPLATE### -->

View File

@ -1,29 +1,37 @@
plugin.tx_dlf_toc.menuConf {
expAll = 0
1 = TMENU
1.noBlur = 1
1.wrap = <ul>|</ul>
1.NO = 1
1.NO.stdWrap.crop = 55 | &nbsp;... | 1
1.NO.stdWrap.ifEmpty.field = type
1.NO.stdWrap.ifEmpty.append.fieldRequired = volume
1.NO.stdWrap.ifEmpty.append = TEXT
1.NO.stdWrap.ifEmpty.append.field = volume
1.NO.stdWrap.ifEmpty.append.wrap = &nbsp;|
1.NO.stdWrap.dataWrap = <span class="tx-dlf-toc-title">|</span> <span class="tx-dlf-toc-pagination">{field:pagination}</span>
1.NO.doNotLinkIt.field = doNotLinkIt
1.NO.ATagTitle.field = type
1.NO.wrapItemAndSub = <li class="tx-dlf-toc-no">|</li>
1.IFSUB < .1.NO
1.IFSUB.wrapItemAndSub = <li class="tx-dlf-toc-no tx-dlf-toc-ifsub">|</li>
1.CUR < .1.NO
1.CUR.wrapItemAndSub = <li class="tx-dlf-toc-cur">|</li>
1.CURIFSUB < .1.NO
1.CURIFSUB.wrapItemAndSub = <li class="tx-dlf-toc-cur tx-dlf-toc-ifsub">|</li>
1.ACT < .1.NO
1.ACT.wrapItemAndSub = <li class="tx-dlf-toc-act">|</li>
1.ACTIFSUB < .1.NO
1.ACTIFSUB.wrapItemAndSub = <li class="tx-dlf-toc-act tx-dlf-toc-ifsub">|</li>
1 {
noBlur = 1
wrap = <ul>|</ul>
NO = 1
NO {
stdWrap {
crop = 55 | &nbsp;... | 1
ifEmpty {
field = type
append.fieldRequired = volume
append = TEXT
append.field = volume
append.wrap = &nbsp;|
}
dataWrap = <span class="tx-dlf-toc-title">|</span> <span class="tx-dlf-toc-pagination">{field:pagination}</span>
}
doNotLinkIt.field = doNotLinkIt
ATagTitle.field = type
wrapItemAndSub = <li class="tx-dlf-toc-no">|</li>
}
IFSUB < .NO
IFSUB.wrapItemAndSub = <li class="tx-dlf-toc-no tx-dlf-toc-ifsub">|</li>
CUR < .NO
CUR.wrapItemAndSub = <li class="tx-dlf-toc-cur">|</li>
CURIFSUB < .NO
CURIFSUB.wrapItemAndSub = <li class="tx-dlf-toc-cur tx-dlf-toc-ifsub">|</li>
ACT < .NO
ACT.wrapItemAndSub = <li class="tx-dlf-toc-act">|</li>
ACTIFSUB < .NO
ACTIFSUB.wrapItemAndSub = <li class="tx-dlf-toc-act tx-dlf-toc-ifsub">|</li>
}
2 < .1
3 < .2
4 < .3

View File

@ -681,7 +681,7 @@ $TCA['tx_dlf_formats'] = array (
'type' => 'input',
'size' => 30,
'max' => 1024,
'eval' => 'required,nospace,alphanum_x,unique',
'eval' => 'nospace,alphanum_x,unique',
),
),
),