Update Solarium to 5.2.x

This commit is contained in:
Sebastian Meyer 2020-12-20 16:06:00 +01:00
parent 3f7054568f
commit b9ca493018
9 changed files with 346 additions and 333 deletions

View File

@ -12,8 +12,10 @@
namespace Kitodo\Dlf\Common;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
/**
* Solr class for the 'dlf' extension
@ -33,12 +35,20 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
class Solr
{
/**
* This holds the core name
* This holds the Solr configuration
*
* @var string
* @var array
* @access protected
*/
protected $core = '';
protected $config = [];
/**
* This holds the core name
*
* @var string|null
* @access protected
*/
protected $core = null;
/**
* This holds the PID for the configuration
@ -104,6 +114,52 @@ class Solr
*/
protected $service;
/**
* Add a new core to Apache Solr
*
* @access public
*
* @param string $core: The name of the new core. If empty, the next available core name is used.
*
* @return string The name of the new core
*/
public static function createCore($core = '')
{
// Get available core name if none given.
if (empty($core)) {
$core = 'dlfCore' . self::getCoreNumber();
}
// Get Solr service instance.
$solr = self::getInstance($core);
// Create new core if core with given name doesn't exist.
if ($solr->core === null) {
// Core doesn't exist yet.
$query = $solr->service->createCoreAdmin();
$action = $query->createCreate();
$action->setConfigSet('dlf');
$action->setCore($core);
$action->setDataDir('data');
$action->setInstanceDir($core);
$query->setAction($action);
try {
$response = $solr->service->coreAdmin($query);
if ($response->getWasSuccessful()) {
// Core successfully created.
return $core;
} else {
// Core creation failed.
return '';
}
} catch (\Exception $e) {
// Core creation failed.
return '';
}
} else {
// Core already exists.
return $core;
}
}
/**
* Escape all special characters in a query string
*
@ -115,13 +171,13 @@ class Solr
*/
public static function escapeQuery($query)
{
$helper = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\Solarium\Core\Query\Helper::class);
$helper = GeneralUtility::makeInstance(\Solarium\Core\Query\Helper::class);
// Escape query phrase or term.
if (preg_match('/^".*"$/', $query)) {
return $helper->escapePhrase(trim($query, '"'));
} else {
// Using a modified escape function here to retain whitespace, '*' and '?' for search truncation.
// @see https://github.com/solariumphp/solarium/blob/4.x/src/Core/Query/Helper.php#L68 for reference
// @see https://github.com/solariumphp/solarium/blob/5.x/src/Core/Query/Helper.php#L70 for reference
/* return $helper->escapeTerm($query); */
return preg_replace('/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|:|\/|\\\)/', '\\\$1', $query);
}
@ -175,127 +231,107 @@ class Solr
} else {
$query = self::escapeQuery($query);
}
} elseif (
!empty($query)
&& $query !== '*'
) {
// Don't escape plain asterisk search.
} else {
$query = self::escapeQuery($query);
}
return $query;
}
/**
* 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 \Kitodo\Dlf\Common\Solr Instance of this class
*/
public static function getInstance($core)
{
// Get core name if UID is given.
if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($core)) {
$core = Helper::getIndexNameFromUid($core, 'tx_dlf_solrcores');
}
// Check if core is set.
if (empty($core)) {
Helper::devLog('Invalid core name "' . $core . '" for Apache Solr', DEVLOG_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 {
Helper::devLog('Could not connect to Apache Solr server', DEVLOG_SEVERITY_ERROR);
return;
}
}
/**
* Returns the connection information for Solr
*
* @access public
*
* @return array The connection parameters for a specific Solr core
*/
public static function getSolrConnectionInfo()
{
$solrInfo = [];
// Extract extension configuration.
$conf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
// Derive Solr scheme
$solrInfo['scheme'] = empty($conf['solrHttps']) ? 'http' : 'https';
// Derive Solr host name.
$solrInfo['host'] = ($conf['solrHost'] ? $conf['solrHost'] : '127.0.0.1');
// Set username and password.
$solrInfo['username'] = $conf['solrUser'];
$solrInfo['password'] = $conf['solrPass'];
// Set port if not set.
$solrInfo['port'] = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($conf['solrPort'], 1, 65535, 8983);
// Trim path of slashes.
$solrInfo['path'] = trim($conf['solrPath'], '/');
// Timeout
$solrInfo['timeout'] = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($conf['solrTimeout'], 1, intval(ini_get('max_execution_time')), 10);
return $solrInfo;
}
/**
* Returns the request URL for a specific Solr core
*
* @access public
*
* @param string $core: Name of the core to load
*
* @return string The request URL for a specific Solr core
*/
public static function getSolrUrl($core = '')
{
// Get Solr connection information.
$solrInfo = self::getSolrConnectionInfo();
if (
$solrInfo['username']
&& $solrInfo['password']
) {
$host = $solrInfo['username'] . ':' . $solrInfo['password'] . '@' . $solrInfo['host'];
} else {
$host = $solrInfo['host'];
}
// Return entire request URL.
return $solrInfo['scheme'] . '://' . $host . ':' . $solrInfo['port'] . '/' . $solrInfo['path'] . '/solr/' . $core;
}
/**
* Get next unused Solr core number
*
* @access public
*
* @param int $start: Number to start with
* @param int $number: Number to start with
*
* @return int First unused core number found
*/
public static function solrGetCoreNumber($start = 0)
public static function getCoreNumber($number = 0)
{
$start = max(intval($start), 0);
$number = max(intval($number), 0);
// Check if core already exists.
if (self::getInstance('dlfCore' . $start) === null) {
return $start;
$solr = self::getInstance('dlfCore' . $number);
if (empty($solr->core)) {
return $number;
} else {
return self::solrGetCoreNumber($start + 1);
return self::solrGetCoreNumber($number + 1);
}
}
/**
* 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 or null to get core admin endpoint
*
* @return \Kitodo\Dlf\Common\Solr Instance of this class
*/
public static function getInstance($core = null)
{
// Get core name if UID is given.
if (MathUtility::canBeInterpretedAsInteger($core)) {
$core = Helper::getIndexNameFromUid($core, 'tx_dlf_solrcores');
}
// Check if core is set or null.
if (empty($core) && $core !== null) {
Helper::devLog('Invalid core UID or name given for Apache Solr', DEVLOG_SEVERITY_ERROR);
return;
}
if (!empty($core)) {
// 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
&& !empty($instance->core)
) {
self::$registry[$instance->core] = $instance;
} else {
Helper::devLog('Could not connect to Apache Solr service', DEVLOG_SEVERITY_ERROR);
}
return $instance;
}
/**
* Sets the connection information for Solr
*
* @access protected
*
* @return void
*/
protected function loadSolrConnectionInfo()
{
if (empty($this->config)) {
$config = [];
// Extract extension configuration.
$conf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
// Derive Solr scheme
$config['scheme'] = empty($conf['solrHttps']) ? 'http' : 'https';
// Derive Solr host name.
$config['host'] = ($conf['solrHost'] ? $conf['solrHost'] : '127.0.0.1');
// Set username and password.
$config['username'] = $conf['solrUser'];
$config['password'] = $conf['solrPass'];
// Set port if not set.
$config['port'] = MathUtility::forceIntegerInRange($conf['solrPort'], 1, 65535, 8983);
// Trim path of slashes and (re-)add trailing slash if path not empty.
$config['path'] = trim($conf['solrPath'], '/');
if (!empty($solrInfo['path'])) {
$config['path'] .= '/';
}
// Timeout
$config['timeout'] = MathUtility::forceIntegerInRange($conf['solrTimeout'], 1, intval(ini_get('max_execution_time')), 10);
$this->config = $config;
}
}
@ -348,7 +384,7 @@ class Solr
];
}
// Save list of documents.
$list = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(DocumentList::class);
$list = GeneralUtility::makeInstance(DocumentList::class);
$list->reset();
$list->add(array_values($toplevel));
// Set metadata for search.
@ -392,7 +428,7 @@ class Solr
// calculate cache identifier
$cacheIdentifier = hash('md5', print_r(array_merge($this->params, $parameters), 1));
$cache = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Cache\CacheManager::class)->getCache('tx_dlf_solr');
$cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('tx_dlf_solr');
$resultSet = [];
if (($entry = $cache->get($cacheIdentifier)) === false) {
@ -410,6 +446,18 @@ class Solr
return $resultSet;
}
/**
* This returns $this->core via __get()
*
* @access protected
*
* @return string|null The core name of the current query endpoint or null if core admin endpoint
*/
protected function _getCore()
{
return $this->core;
}
/**
* This returns $this->limit via __get()
*
@ -565,37 +613,63 @@ class Solr
*
* @access protected
*
* @param string $core: The name of the core to use
* @param string|null $core: The name of the core to use or null for core admin endpoint
*
* @return void
*/
protected function __construct($core)
protected function __construct($core = null)
{
$solrInfo = self::getSolrConnectionInfo();
// Get Solr connection parameters from configuration.
$this->loadSolrConnectionInfo();
// Configure connection adapter.
$adapter = GeneralUtility::makeInstance(\Solarium\Core\Client\Adapter\Http::class);
$adapter->setTimeout($this->config['timeout']);
// Configure event dispatcher.
// Todo: When updating to TYPO3 >=10.x and Solarium >=6.x
// we have to provide an PSR-14 Event Dispatcher instead of
// "null".
// $eventDispatcher = GeneralUtility::makeInstance(\TYPO3\CMS\Core\EventDispatcher\EventDispatcher::class);
$eventDispatcher = null;
// Configure endpoint.
$config = [
'endpoint' => [
'dlf' => [
'scheme' => $solrInfo['scheme'],
'host' => $solrInfo['host'],
'port' => $solrInfo['port'],
'path' => '/' . $solrInfo['path'] . '/',
'default' => [
'scheme' => $this->config['scheme'],
'host' => $this->config['host'],
'port' => $this->config['port'],
'path' => '/' . $this->config['path'],
'core' => $core,
'username' => $solrInfo['username'],
'password' => $solrInfo['password'],
'timeout' => $solrInfo['timeout']
'username' => $this->config['username'],
'password' => $this->config['password']
]
]
];
// Instantiate Solarium\Client class.
$this->service = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\Solarium\Client::class, $config);
$this->service = GeneralUtility::makeInstance(\Solarium\Client::class, $adapter, $eventDispatcher, $config);
// Check if connection is established.
$ping = $this->service->createPing();
$query = $this->service->createCoreAdmin();
$action = $query->createStatus();
if (!empty($core)) {
$action->setCore($core);
}
$query->setAction($action);
try {
$this->service->ping($ping);
// Set core name.
$this->core = $core;
// Instantiation successful!
$this->ready = true;
$response = $this->service->coreAdmin($query);
if ($response->getWasSuccessful()) {
// Instantiation successful!
$this->ready = true;
// Solr is reachable, but is the core as well?
if (!empty($core)) {
$result = $response->getStatusResultByCoreName($core);
if (
$result instanceof \Solarium\QueryType\Server\CoreAdmin\Result\StatusResult
&& $result->getUptime() > 0
) {
// Set core name.
$this->core = $core;
}
}
}
} catch (\Exception $e) {
// Nothing to do here.
}

View File

@ -46,43 +46,20 @@ class ConfigurationForm
*/
public function checkSolrConnection()
{
$solrInfo = Solr::getSolrConnectionInfo();
// Prepend username and password to hostname.
if (
!empty($solrInfo['username'])
&& !empty($solrInfo['password'])
) {
$host = $solrInfo['username'] . ':' . $solrInfo['password'] . '@' . $solrInfo['host'];
$solr = Solr::getInstance();
if ($solr->ready) {
Helper::addMessage(
htmlspecialchars($GLOBALS['LANG']->getLL('solr.status')),
htmlspecialchars($GLOBALS['LANG']->getLL('solr.connected')),
\TYPO3\CMS\Core\Messaging\FlashMessage::OK
);
} else {
$host = $solrInfo['host'];
Helper::addMessage(
htmlspecialchars($GLOBALS['LANG']->getLL('solr.error')),
htmlspecialchars($GLOBALS['LANG']->getLL('solr.notConnected')),
\TYPO3\CMS\Core\Messaging\FlashMessage::WARNING
);
}
// Build request URI.
$url = $solrInfo['scheme'] . '://' . $host . ':' . $solrInfo['port'] . '/' . $solrInfo['path'] . '/admin/cores?wt=xml';
$context = stream_context_create([
'http' => [
'method' => 'GET',
'user_agent' => (!empty($this->conf['useragent']) ? $this->conf['useragent'] : ini_get('user_agent'))
]
]);
// Try to connect to Solr server.
$response = @simplexml_load_string(file_get_contents($url, false, $context));
// Check status code.
if ($response) {
$status = $response->xpath('//lst[@name="responseHeader"]/int[@name="status"]');
if (is_array($status)) {
Helper::addMessage(
htmlspecialchars(sprintf($GLOBALS['LANG']->getLL('solr.status'), (string) $status[0])),
htmlspecialchars($GLOBALS['LANG']->getLL('solr.connected')),
($status[0] == 0 ? \TYPO3\CMS\Core\Messaging\FlashMessage::OK : \TYPO3\CMS\Core\Messaging\FlashMessage::WARNING)
);
return Helper::renderFlashMessages();
}
}
Helper::addMessage(
htmlspecialchars(sprintf($GLOBALS['LANG']->getLL('solr.error'), $url)),
htmlspecialchars($GLOBALS['LANG']->getLL('solr.notConnected')),
\TYPO3\CMS\Core\Messaging\FlashMessage::WARNING
);
return Helper::renderFlashMessages();
}

View File

@ -91,53 +91,13 @@ class DataHandler
break;
// Field post-processing for table "tx_dlf_solrcores".
case 'tx_dlf_solrcores':
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_dlf_solrcores');
// Get number of existing cores.
$result = $queryBuilder
->select('*')
->from('tx_dlf_solrcores')
->execute();
// Get first unused core number.
$coreNumber = Solr::solrGetCoreNumber(count($result->fetchAll()));
// Get Solr credentials.
$conf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['dlf']);
$solrInfo = Solr::getSolrConnectionInfo();
// Prepend username and password to hostname.
if (
$solrInfo['username']
&& $solrInfo['password']
) {
$host = $solrInfo['username'] . ':' . $solrInfo['password'] . '@' . $solrInfo['host'];
} else {
$host = $solrInfo['host'];
// Create new Solr core.
$fieldArray['index_name'] = Solr::createCore();
if (empty($fieldArray['index_name'])) {
Helper::devLog('Could not create new Apache Solr core', DEVLOG_SEVERITY_ERROR);
// Solr core could not be created, thus unset field array.
$fieldArray = [];
}
$context = stream_context_create([
'http' => [
'method' => 'GET',
'user_agent' => ($conf['useragent'] ? $conf['useragent'] : ini_get('user_agent'))
]
]);
// Build request for adding new Solr core.
// @see http://wiki.apache.org/solr/CoreAdmin
$url = $solrInfo['scheme'] . '://' . $host . ':' . $solrInfo['port'] . '/' . $solrInfo['path'] . '/admin/cores?wt=xml&action=CREATE&name=dlfCore' . $coreNumber . '&instanceDir=dlfCore' . $coreNumber . '&dataDir=data&configSet=dlf';
$response = @simplexml_load_string(file_get_contents($url, false, $context));
// Process response.
if ($response) {
$solrStatus = $response->xpath('//lst[@name="responseHeader"]/int[@name="status"]');
if (
is_array($solrStatus)
&& $solrStatus[0] == 0
) {
$fieldArray['index_name'] = 'dlfCore' . $coreNumber;
return;
}
}
Helper::devLog('Could not create new Apache Solr core "dlfCore' . $coreNumber . '"', DEVLOG_SEVERITY_ERROR);
// Solr core could not be created, thus unset field array.
$fieldArray = [];
break;
}
} elseif ($status == 'update') {

View File

@ -38,29 +38,51 @@ class SearchInDocument
*/
public function main(ServerRequestInterface $request)
{
$output = [
'documents' => [],
'numFound' => 0
];
// Get input parameters and decrypt core name.
$parameters = $request->getParsedBody();
$encrypted = (string)$parameters['encrypted'];
$hashed = (string)$parameters['hashed'];
$encrypted = (string) $parameters['encrypted'];
$hashed = (string) $parameters['hashed'];
$count = intval($parameters['start']);
if (empty($encrypted) || empty($hashed)) {
throw new \InvalidArgumentException('No valid parameter passed!', 1580585079);
}
$core = Helper::decrypt($encrypted, $hashed);
$output = '';
if (!empty($core)) {
$query = (string)$parameters['q'];
$uid = (string)$parameters['uid'];
$start = (string)$parameters['start'];
$url = trim(Solr::getSolrUrl($core), '/') . '/select?wt=json&q=fulltext:(' . Solr::escapeQuery($query) . ')%20AND%20uid:' . $uid
. '&hl=on&hl.fl=fulltext&fl=uid,id,page&hl.method=fastVector'
. '&start=' . $start . '&rows=20';
$output = GeneralUtility::getUrl($url);
// Perform Solr query.
$solr = Solr::getInstance($core);
if (
$solr->ready
&& $solr->core === $core
) {
$query = $solr->service->createSelect();
$query->setFields(['id', 'uid', 'page']);
$query->setQuery('fulltext:(' . Solr::escapeQuery((string) $parameters['q']) . ') AND uid:' . intval($parameters['uid']));
$query->setStart($count)->setRows(20);
$hl = $query->getHighlighting();
$hl->setFields('fulltext');
$hl->setMethod('fastVector');
$results = $solr->service->select($query);
$output['numFound'] = $results->getNumFound();
$highlighting = $results->getHighlighting();
foreach ($results as $result) {
$snippet = $highlighting->getResult($result->id);
$document = [
'id' => $result->id,
'uid' => $result->uid,
'page' => $result->page,
'snippet' => $snippet['fulltext']
];
$output['documents'][$count] = $document;
$count++;
}
}
// create response object
// Create response object.
/** @var Response $response */
$response = GeneralUtility::makeInstance(Response::class);
$response->getBody()->write($output);
$response->getBody()->write(json_encode($output));
return $response;
}
}

View File

@ -14,7 +14,6 @@ namespace Kitodo\Dlf\Plugin\Eid;
use Kitodo\Dlf\Common\Helper;
use Kitodo\Dlf\Common\Solr;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Http\Response;
@ -39,25 +38,34 @@ class SearchSuggest
*/
public function main(ServerRequestInterface $request)
{
$output = [];
// Get input parameters and decrypt core name.
$parameters = $request->getParsedBody();
$encrypted = (string)$parameters['encrypted'];
$hashed = (string)$parameters['hashed'];
$encrypted = (string) $parameters['encrypted'];
$hashed = (string) $parameters['hashed'];
if (empty($encrypted) || empty($hashed)) {
throw new \InvalidArgumentException('No valid parameter passed!', 1580585079);
}
$core = Helper::decrypt($encrypted, $hashed);
$output = '';
if (!empty($core)) {
$query = (string)$parameters['q'];
$url = trim(Solr::getSolrUrl($core), '/') . '/suggest/?wt=xml&q=' . Solr::escapeQuery($query);
$output = GeneralUtility::getUrl($url);
// Perform Solr query.
$solr = Solr::getInstance($core);
if (
$solr->ready
&& $solr->core === $core
) {
$query = $solr->service->createSuggester();
$query->setCount(10);
$query->setDictionary('suggest');
$query->setQuery(Solr::escapeQuery((string) $parameters['q']));
$results = $solr->service->suggester($query);
foreach ($results as $result) {
$output = array_merge($output, $result);
}
}
// create response object
// Create response object.
/** @var Response $response */
$response = GeneralUtility::makeInstance(Response::class);
$response->getBody()->write($output);
$response->getBody()->write(json_encode($output));
return $response;
}
}

View File

@ -76,9 +76,9 @@
<label index="update.documentSetFormatForOldEntriesOkay">...successfully completed!</label>
<label index="update.documentSetFormatForOldEntriesNotOkay">...incomplete! Please set missing tx_dlf_document.document_format values to 'METS'.</label>
<label index="solr.connected">Connection established!</label>
<label index="solr.status">The status code returned by Apache Solr is &lt;strong&gt;%s&lt;/strong&gt;.</label>
<label index="solr.status">Apache Solr is running and taking requests.</label>
<label index="solr.notConnected">Connection failed!</label>
<label index="solr.error">Apache Solr was not reachable under &lt;strong&gt;%s&lt;/strong&gt;.</label>
<label index="solr.error">Apache Solr not reachable with given configuration.</label>
<label index="metadataFormats.nsOkay">Default namespaces found!</label>
<label index="metadataFormats.nsOkayMsg">The namespace definitions for MODS, TEIHDR and ALTO do exist.</label>
<label index="metadataFormats.nsCreated">Default namespaces created successfully!</label>
@ -148,9 +148,9 @@
<label index="update.documentSetFormatForOldEntriesOkay">...erfolgreich beendet!</label>
<label index="update.documentSetFormatForOldEntriesNotOkay">...abgebrochen! Bitte in der Tabelle tx_dlf_document.document_format 'METS'.</label>
<label index="solr.connected">Verbindung hergestellt!</label>
<label index="solr.status">Apache Solr gibt den Statuscode &lt;strong&gt;%s&lt;/strong&gt; zurück.</label>
<label index="solr.status">Apache Solr ist verfügbar und nimmt Anfragen entgegen.</label>
<label index="solr.notConnected">Verbindung fehlgeschlagen!</label>
<label index="solr.error">Apache Solr ist unter &lt;strong&gt;%s&lt;/strong&gt; nicht erreichbar.</label>
<label index="solr.error">Apache Solr ist mit der gegebenen Konfiguration nicht erreichbar.</label>
<label index="metadataFormats.nsOkay">Standard-Namensräume gefunden!</label>
<label index="metadataFormats.nsOkayMsg">Die Standard-Namensräume für MODS, TEIHDR und ALTO sind definiert.</label>
<label index="metadataFormats.nsCreated">Standard-Namensräume erfolgreich angelegt!</label>

View File

@ -12,12 +12,11 @@
* This function increases the start parameter of the search form and submits
* the form.
*
* @param rows
* @returns void
*/
function nextResultPage(rows) {
function nextResultPage() {
var currentstart = $("#tx-dlf-search-in-document-form input[name='tx_dlf[start]']").val();
var newstart = parseInt(currentstart) + rows;
var newstart = parseInt(currentstart) + 20;
$("#tx-dlf-search-in-document-form input[name='tx_dlf[start]']").val(newstart);
$('#tx-dlf-search-in-document-form').submit();
};
@ -26,13 +25,11 @@ function nextResultPage(rows) {
* This function decreases the start parameter of the search form and submits
* the form.
*
* @param rows
* @returns void
*/
function previousResultPage(rows) {
function previousResultPage() {
var currentstart = $("#tx-dlf-search-in-document-form input[name='tx_dlf[start]']").val();
currentstart = parseInt(currentstart);
var newstart = (currentstart > rows) ? (currentstart - rows) : 0;
var newstart = (parseInt(currentstart) > 20) ? (parseInt(currentstart) - 20) : 0;
$("#tx-dlf-search-in-document-form input[name='tx_dlf[start]']").val(newstart);
$('#tx-dlf-search-in-document-form').submit();
};
@ -67,55 +64,60 @@ $(document).ready(function() {
hashed: $( "input[name='tx_dlf[hashed]']" ).val(),
},
function(data) {
var resultItems = [];
var resultList = '<div class="results-active-indicator"></div><ul>';
if (data.error) {
resultList += '<li class="error">' + data.error + '</li>';
} else {
for (var i=0; i < data.response.docs.length; i++) {
var resultItems = [];
var resultList = '<div class="results-active-indicator"></div><ul>';
var start = -1;
if (data.numFound > 0) {
// Take the workview baseUrl from the form action.
// The URL may be in the following form
// - http://example.com/index.php?id=14
// - http://example.com/workview (using slug on page with uid=14)
var baseUrl = $("form#tx-dlf-search-in-document-form").attr('action');
// Take the workview baseUrl from the form action.
// The URL may be in the following form
// - http://example.com/index.php?id=14
// - http://example.com/workview (using slug on page with uid=14)
var baseUrl = $("form#tx-dlf-search-in-document-form").attr('action');
if (baseUrl.indexOf('?')>0) {
if (baseUrl.indexOf('?') > 0) {
baseUrl += '&';
} else {
} else {
baseUrl += '?';
}
}
data.documents.forEach(function (element, i) {
if (start < 0) {
start = i;
}
var searchWord = element['snippet'];
searchWord = searchWord.substring(searchWord.indexOf('<em>') + 4, searchWord.indexOf('</em>'));
var searchHit = data.highlighting[data.response.docs[i].id].fulltext.toString();
searchHit = searchHit.substring(searchHit.indexOf('<em>')+4,searchHit.indexOf('</em>'));
var link = baseUrl
+ 'tx_dlf[id]=' + element['uid']
+ '&tx_dlf[highlight_word]=' + encodeURIComponent(searchWord)
+ '&tx_dlf[page]=' + element['page'];
var newlink = baseUrl
+ 'tx_dlf[id]=' + data.response.docs[i].uid
+ '&tx_dlf[highlight_word]=' + encodeURIComponent(searchHit)
+ '&tx_dlf[page]=' + data.response.docs[i].page;
if (data.highlighting[data.response.docs[i].id].fulltext) {
resultItems[data.response.docs[i].page] = '<span class="structure">' + $('#tx-dlf-search-in-document-label-page').text() + ' ' + data.response.docs[i].page + '</span><br /><span ="textsnippet"><a href=\"' + newlink + '\">' + data.highlighting[data.response.docs[i].id].fulltext + '</a></span>';
}
}
if (resultItems.length > 0) {
// sort by page as this cannot be done with current solr schema
resultItems.sort(function(a, b){return a-b});
resultItems.forEach(function(item, index){
if (element['snippet'].length > 0) {
resultItems[element['page']] = '<span class="structure">'
+ $('#tx-dlf-search-in-document-label-page').text() + ' ' + element['page']
+ '</span><br />'
+ '<span ="textsnippet">' +
+ '<a href=\"' + link + '\">' + element['snippet'] + '</a>'
+ '</span>';
}
});
// Sort result by page.
resultItems.sort(function (a, b) {
return a - b;
});
resultItems.forEach(function (item, index) {
resultList += '<li>' + item + '</li>';
});
} else {
resultList += '<li class="noresult">' + $('#tx-dlf-search-in-document-label-noresult').text() + '</li>';
}
}
resultList += '</ul>';
if (parseInt(data.response.start) > 0) {
resultList += '<input type="button" id="tx-dlf-search-in-document-button-previous" class="button-previous" onclick="previousResultPage(' + data.responseHeader.params.rows + ');" value="' + $('#tx-dlf-search-in-document-label-previous').text() + '" />';
}
if (parseInt(data.response.numFound) > (parseInt(data.response.start) + parseInt(data.responseHeader.params.rows))) {
resultList += '<input type="button" id="tx-dlf-search-in-document-button-next" class="button-next" onclick="nextResultPage(' + data.responseHeader.params.rows + ');" value="' + $('#tx-dlf-search-in-document-label-next').text() + '" />';
}
$('#tx-dlf-search-in-document-results').html(resultList);
resultList += '</ul>';
if (start > 0) {
resultList += '<input type="button" id="tx-dlf-search-in-document-button-previous" class="button-previous" onclick="previousResultPage();" value="' + $('#tx-dlf-search-in-document-label-previous').text() + '" />';
}
if (data.numFound > (start + 20)) {
resultList += '<input type="button" id="tx-dlf-search-in-document-button-next" class="button-next" onclick="nextResultPage();" value="' + $('#tx-dlf-search-in-document-label-next').text() + '" />';
}
$('#tx-dlf-search-in-document-results').html(resultList);
},
"json"
)

View File

@ -31,14 +31,14 @@ $(
function(data) {
var result = [];
var option = "";
$("arr[name='suggestion'] str", data).each(function(i) {
$.parseJSON(data).each(function(i) {
option = $(this).text();
option = option.replace(/(\?|!|:|\\)/g, "\\\$1");
result.push(option);
});
return response(result);
},
"xml");
"json");
},
minLength: 3,
appendTo: "#tx-dlf-search-suggest"

View File

@ -141,7 +141,7 @@ class ext_update
while ($resArray = $result->fetch()) {
// Instantiate search object.
$solr = Solr::getInstance($resArray['index_name']);
if (!$solr->ready) {
if ($solr->core !== $resArray['index_name']) {
return true;
}
}
@ -395,64 +395,34 @@ class ext_update
*/
protected function doSolariumSolrUpdate(): void
{
$error = false;
// Get all Solr cores that were not deleted.
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_dlf_solrcores');
$result = $queryBuilder
->select('index_name')
->from('tx_dlf_solrcores')
->where('1=1')
->execute();
while ($resArray = $result->fetch()) {
// Instantiate search object.
$solr = Solr::getInstance($resArray['index_name']);
if (!$solr->ready) {
$conf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['dlf']);
$solrInfo = Solr::getSolrConnectionInfo();
// Prepend username and password to hostname.
if (
$solrInfo['username']
&& $solrInfo['password']
) {
$host = $solrInfo['username'] . ':' . $solrInfo['password'] . '@' . $solrInfo['host'];
} else {
$host = $solrInfo['host'];
}
$context = stream_context_create([
'http' => [
'method' => 'GET',
'user_agent' => ($conf['useragent'] ? $conf['useragent'] : ini_get('user_agent'))
]
]);
// Build request for adding new Solr core.
// @see http://wiki.apache.org/solr/CoreAdmin
$url = $solrInfo['scheme'] . '://' . $host . ':' . $solrInfo['port'] . '/' . $solrInfo['path'] . '/admin/cores?wt=xml&action=CREATE&name=' . $resArray['index_name'] . '&instanceDir=' . $resArray['index_name'] . '&dataDir=data&configSet=dlf';
$response = @simplexml_load_string(file_get_contents($url, false, $context));
// Process response.
if ($response) {
$status = $response->xpath('//lst[@name="responseHeader"]/int[@name="status"]');
if (
$status !== false
&& $status[0] === 0
) {
continue;
}
}
// Create core if it doesn't exist.
if (Solr::createCore($resArray['index_name']) !== $resArray['index_name']) {
Helper::addMessage(
htmlspecialchars($GLOBALS['LANG']->getLL('update.solariumSolrUpdateNotOkay')),
htmlspecialchars(sprintf($GLOBALS['LANG']->getLL('update.solariumSolrUpdate'), $resArray['index_name'])),
\TYPO3\CMS\Core\Messaging\FlashMessage::ERROR
);
$this->content .= Helper::renderFlashMessages();
return;
$error = true;
}
}
Helper::addMessage(
htmlspecialchars($GLOBALS['LANG']->getLL('update.solariumSolrUpdateOkay')),
htmlspecialchars($GLOBALS['LANG']->getLL('update.solariumSolrUpdate')),
\TYPO3\CMS\Core\Messaging\FlashMessage::OK
);
$this->content .= Helper::renderFlashMessages();
if (!$error) {
Helper::addMessage(
htmlspecialchars($GLOBALS['LANG']->getLL('update.solariumSolrUpdateOkay')),
htmlspecialchars($GLOBALS['LANG']->getLL('update.solariumSolrUpdate')),
\TYPO3\CMS\Core\Messaging\FlashMessage::OK
);
$this->content .= Helper::renderFlashMessages();
}
}
/**