Update Solarium to 5.2.x
This commit is contained in:
parent
3f7054568f
commit
b9ca493018
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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') {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <strong>%s</strong>.</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 <strong>%s</strong>.</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 <strong>%s</strong> 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 <strong>%s</strong> 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>
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue