diff --git a/Classes/Common/DocumentList.php b/Classes/Common/DocumentList.php
index e1afde15..1e1f84bb 100644
--- a/Classes/Common/DocumentList.php
+++ b/Classes/Common/DocumentList.php
@@ -565,7 +565,10 @@ class DocumentList implements \ArrayAccess, \Countable, \Iterator, \TYPO3\CMS\Co
// Get Solr instance.
if (!$this->solr) {
// Connect to Solr server.
- if ($this->solr = Solr::getInstance($this->metadata['options']['core'])) {
+ $solr = Solr::getInstance($this->metadata['options']['core']);
+ if ($solr->ready) {
+ $this->solr = $solr;
+ // Get indexed fields.
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_dlf_metadata');
diff --git a/Classes/Common/Indexer.php b/Classes/Common/Indexer.php
index 3187b559..6c0b7943 100644
--- a/Classes/Common/Indexer.php
+++ b/Classes/Common/Indexer.php
@@ -560,7 +560,9 @@ class Indexer
// Get Solr instance.
if (!self::$solr) {
// Connect to Solr server.
- if (self::$solr = Solr::getInstance($core)) {
+ $solr = Solr::getInstance($core);
+ if ($solr->ready) {
+ self::$solr = $solr;
// Load indexing configuration if needed.
if ($pid) {
self::loadIndexConf($pid);
diff --git a/Classes/Common/Solr.php b/Classes/Common/Solr.php
index 72fdc3f0..f73a8297 100644
--- a/Classes/Common/Solr.php
+++ b/Classes/Common/Solr.php
@@ -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
@@ -23,22 +25,31 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
* @package TYPO3
* @subpackage dlf
* @access public
+ * @property-read string|null $core This holds the core name for the current instance
* @property-write int $cPid This holds the PID for the configuration
* @property int $limit This holds the max results
* @property-read int $numberOfHits This holds the number of hits for last search
* @property-write array $params This holds the additional query parameters
- * @property-read bool $ready Is the search instantiated successfully?
+ * @property-read bool $ready Is the Solr service instantiated successfully?
* @property-read \Solarium\Client $service This holds the Solr service object
*/
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 +115,54 @@ 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 next available core name if none given.
+ if (empty($core)) {
+ $core = 'dlfCore' . self::getNextCoreNumber();
+ }
+ // Get Solr service instance.
+ $solr = self::getInstance($core);
+ // Create new core if core with given name doesn't exist.
+ if ($solr->ready) {
+ // Core already exists.
+ return $core;
+ } else {
+ // Core doesn't exist yet.
+ $solrAdmin = self::getInstance();
+ if ($solrAdmin->ready) {
+ $query = $solrAdmin->service->createCoreAdmin();
+ $action = $query->createCreate();
+ $action->setConfigSet('dlf');
+ $action->setCore($core);
+ $action->setDataDir('data');
+ $action->setInstanceDir($core);
+ $query->setAction($action);
+ try {
+ $response = $solrAdmin->service->coreAdmin($query);
+ if ($response->getWasSuccessful()) {
+ // Core successfully created.
+ return $core;
+ }
+ } catch (\Exception $e) {
+ // Nothing to do here.
+ }
+ } else {
+ Helper::devLog('Apache Solr not available', DEVLOG_SEVERITY_ERROR);
+ }
+ }
+ return '';
+ }
+
/**
* Escape all special characters in a query string
*
@@ -115,13 +174,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,11 +234,7 @@ class Solr
} else {
$query = self::escapeQuery($query);
}
- } elseif (
- !empty($query)
- && $query !== '*'
- ) {
- // Don't escape plain asterisk search.
+ } else {
$query = self::escapeQuery($query);
}
return $query;
@@ -190,93 +245,40 @@ class Solr
*
* @access public
*
- * @param mixed $core: Name or UID of the core to load
+ * @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)
+ public static function getInstance($core = null)
{
// Get core name if UID is given.
- if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($core)) {
+ if (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.
+ // Check if core is set or null.
if (
- is_object(self::$registry[$core])
- && self::$registry[$core] instanceof self
+ empty($core)
+ && $core !== null
) {
- // Return singleton instance if available.
- return self::$registry[$core];
+ Helper::devLog('Invalid core UID or name given for Apache Solr', DEVLOG_SEVERITY_ERROR);
+ }
+ 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) {
- self::$registry[$core] = $instance;
- // Return new instance.
- return $instance;
- } else {
- Helper::devLog('Could not connect to Apache Solr server', DEVLOG_SEVERITY_ERROR);
- return;
+ if (!empty($instance->core)) {
+ self::$registry[$instance->core] = $instance;
}
- }
-
- /**
- * 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;
+ return $instance;
}
/**
@@ -284,18 +286,53 @@ class Solr
*
* @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 getNextCoreNumber($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 (!$solr->ready) {
+ return $number;
} else {
- return self::solrGetCoreNumber($start + 1);
+ return self::getNextCoreNumber($number + 1);
+ }
+ }
+
+ /**
+ * 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($config['path'])) {
+ $config['path'] .= '/';
+ }
+ // Set connection timeout lower than PHP's max_execution_time.
+ $max_execution_time = intval(ini_get('max_execution_time')) ?: 30;
+ $config['timeout'] = MathUtility::forceIntegerInRange($conf['solrTimeout'], 1, $max_execution_time, 10);
+ $this->config = $config;
}
}
@@ -348,7 +385,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 +429,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 +447,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 +614,66 @@ 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)
{
- $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 ($core !== null) {
+ $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()) {
+ // Solr is reachable, but is the core as well?
+ if ($core !== null) {
+ $result = $response->getStatusResult();
+ if (
+ $result instanceof \Solarium\QueryType\Server\CoreAdmin\Result\StatusResult
+ && $result->getUptime() > 0
+ ) {
+ // Set core name.
+ $this->core = $core;
+ } else {
+ // Core not available.
+ return;
+ }
+ }
+ // Instantiation successful!
+ $this->ready = true;
+ }
} catch (\Exception $e) {
// Nothing to do here.
}
diff --git a/Classes/Hooks/ConfigurationForm.php b/Classes/Hooks/ConfigurationForm.php
index cf9ff613..63e84711 100644
--- a/Classes/Hooks/ConfigurationForm.php
+++ b/Classes/Hooks/ConfigurationForm.php
@@ -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();
}
diff --git a/Classes/Hooks/DataHandler.php b/Classes/Hooks/DataHandler.php
index 4f5e49ed..407fd973 100644
--- a/Classes/Hooks/DataHandler.php
+++ b/Classes/Hooks/DataHandler.php
@@ -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') {
@@ -286,7 +246,8 @@ class DataHandler
$resArray = $allResults[0];
if ($resArray['hidden']) {
// Establish Solr connection.
- if ($solr = Solr::getInstance($resArray['core'])) {
+ $solr = Solr::getInstance($resArray['core']);
+ if ($solr->ready) {
// Delete Solr document.
$updateQuery = $solr->service->createUpdate();
$updateQuery->addDeleteQuery('uid:' . $id);
@@ -326,10 +287,10 @@ class DataHandler
in_array($command, ['move', 'delete', 'undelete'])
&& $table == 'tx_dlf_documents'
) {
- // Get Solr-Core.
+ // Get Solr core.
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_dlf_solrcores');
- // tx_dlf_documents is already deleted at this point --> include deleted documents in query
+ // Record in "tx_dlf_documents" is already deleted at this point.
$queryBuilder
->getRestrictions()
->removeByType(DeletedRestriction::class);
@@ -365,7 +326,8 @@ class DataHandler
case 'move':
case 'delete':
// Establish Solr connection.
- if ($solr = Solr::getInstance($resArray['core'])) {
+ $solr = Solr::getInstance($resArray['core']);
+ if ($solr->ready) {
// Delete Solr document.
$updateQuery = $solr->service->createUpdate();
$updateQuery->addDeleteQuery('uid:' . $id);
@@ -387,5 +349,57 @@ class DataHandler
}
}
}
+ if (
+ $command === 'delete'
+ && $table == 'tx_dlf_solrcores'
+ ) {
+ // Is core deletion allowed in extension configuration?
+ $extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['dlf']);
+ if (!empty($extConf['solrAllowCoreDelete'])) {
+ // Delete core from Apache Solr as well.
+ $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+ ->getQueryBuilderForTable('tx_dlf_solrcores');
+ // Record in "tx_dlf_solrcores" is already deleted at this point.
+ $queryBuilder
+ ->getRestrictions()
+ ->removeByType(DeletedRestriction::class);
+
+ $result = $queryBuilder
+ ->select(
+ 'tx_dlf_solrcores.index_name AS core'
+ )
+ ->from('tx_dlf_solrcores')
+ ->where($queryBuilder->expr()->eq('tx_dlf_solrcores.uid', intval($id)))
+ ->setMaxResults(1)
+ ->execute();
+
+ $allResults = $result->fetchAll();
+
+ if (count($allResults) == 1) {
+ $resArray = $allResults[0];
+ // Establish Solr connection.
+ $solr = Solr::getInstance();
+ if ($solr->ready) {
+ // Delete Solr core.
+ $query = $solr->service->createCoreAdmin();
+ $action = $query->createUnload();
+ $action->setCore($resArray['core']);
+ $action->setDeleteDataDir(true);
+ $action->setDeleteIndex(true);
+ $action->setDeleteInstanceDir(true);
+ $query->setAction($action);
+ try {
+ $response = $solr->service->coreAdmin($query);
+ if ($response->getWasSuccessful()) {
+ return;
+ }
+ } catch (\Exception $e) {
+ // Nothing to do here.
+ }
+ }
+ Helper::devLog('Core ' . $resArray['core'] . ' could not be deleted from Apache Solr', DEVLOG_SEVERITY_WARNING);
+ }
+ }
+ }
}
}
diff --git a/Classes/Plugin/Collection.php b/Classes/Plugin/Collection.php
index 1812a26a..28dcfe52 100644
--- a/Classes/Plugin/Collection.php
+++ b/Classes/Plugin/Collection.php
@@ -142,6 +142,10 @@ class Collection extends \Kitodo\Dlf\Common\AbstractPlugin
$this->showSingleCollection(intval($resArray['uid']));
}
$solr = Solr::getInstance($this->conf['solrcore']);
+ if (!$solr->ready) {
+ Helper::devLog('Apache Solr not available', DEVLOG_SEVERITY_ERROR);
+ return $content;
+ }
// We only care about the UID and partOf in the results and want them sorted
$params['fields'] = 'uid,partof';
$params['sort'] = ['uid' => 'asc'];
diff --git a/Classes/Plugin/Eid/SearchInDocument.php b/Classes/Plugin/Eid/SearchInDocument.php
index 09a2bdfd..0d198d90 100644
--- a/Classes/Plugin/Eid/SearchInDocument.php
+++ b/Classes/Plugin/Eid/SearchInDocument.php
@@ -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;
@@ -38,29 +37,48 @@ 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) {
+ $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->setUseFastVectorHighlighter(true);
+ $results = $solr->service->select($query);
+ $output['numFound'] = $results->getNumFound();
+ $highlighting = $results->getHighlighting();
+ foreach ($results as $result) {
+ $snippet = $highlighting->getResult($result->id)->getField('fulltext');
+ $document = [
+ 'id' => $result->id,
+ 'uid' => $result->uid,
+ 'page' => $result->page,
+ 'snippet' => !empty($snippet) ? implode(' [...] ', $snippet) : ''
+ ];
+ $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;
}
}
diff --git a/Classes/Plugin/Eid/SearchSuggest.php b/Classes/Plugin/Eid/SearchSuggest.php
index 68cfba78..7ed86647 100644
--- a/Classes/Plugin/Eid/SearchSuggest.php
+++ b/Classes/Plugin/Eid/SearchSuggest.php
@@ -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,36 @@ 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) {
+ $query = $solr->service->createSelect();
+ $query->setHandler('suggest');
+ $query->setQuery(Solr::escapeQuery((string) $parameters['q']));
+ $query->setRows(0);
+ $results = $solr->service->select($query)->getResponse()->getBody();
+ $result = json_decode($results);
+ foreach ($result->spellcheck->suggestions as $suggestions) {
+ if (is_object($suggestions)) {
+ foreach ($suggestions->suggestion as $suggestion) {
+ $output[] = $suggestion;
+ }
+ }
+ }
}
-
- // 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;
}
}
diff --git a/Classes/Plugin/OaiPmh.php b/Classes/Plugin/OaiPmh.php
index 4d3f2740..0d1e5181 100644
--- a/Classes/Plugin/OaiPmh.php
+++ b/Classes/Plugin/OaiPmh.php
@@ -923,6 +923,10 @@ class OaiPmh extends \Kitodo\Dlf\Common\AbstractPlugin
$solr_query .= ' AND timestamp:[' . $from . ' TO ' . $until . ']';
$documentSet = [];
$solr = Solr::getInstance($this->conf['solrcore']);
+ if (!$solr->ready) {
+ Helper::devLog('Apache Solr not available', DEVLOG_SEVERITY_ERROR);
+ return $documentSet;
+ }
if (intval($this->conf['solr_limit']) > 0) {
$solr->limit = intval($this->conf['solr_limit']);
}
diff --git a/Resources/Private/Language/FlashMessages.xml b/Resources/Private/Language/FlashMessages.xml
index a6d5ad89..b79d3d03 100644
--- a/Resources/Private/Language/FlashMessages.xml
+++ b/Resources/Private/Language/FlashMessages.xml
@@ -76,9 +76,9 @@
-
+
-
+
@@ -148,9 +148,9 @@
-
+
-
+
diff --git a/Resources/Private/Language/Labels.xml b/Resources/Private/Language/Labels.xml
index 15ba9469..2effd1a4 100644
--- a/Resources/Private/Language/Labels.xml
+++ b/Resources/Private/Language/Labels.xml
@@ -190,13 +190,14 @@
-
+
+