kitodo-presentation/Classes/Hooks/DataHandler.php

380 lines
16 KiB
PHP

<?php
/**
* (c) Kitodo. Key to digital objects e.V. <contact@kitodo.org>
*
* This file is part of the Kitodo and TYPO3 projects.
*
* @license GNU General Public License version 3 or later.
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*/
namespace Kitodo\Dlf\Hooks;
use Kitodo\Dlf\Common\Document;
use Kitodo\Dlf\Common\Helper;
use Kitodo\Dlf\Common\Indexer;
use Kitodo\Dlf\Common\Solr;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Hooks and helper for \TYPO3\CMS\Core\DataHandling\DataHandler
*
* @author Sebastian Meyer <sebastian.meyer@slub-dresden.de>
* @package TYPO3
* @subpackage dlf
* @access public
*/
class DataHandler
{
/**
* Field post-processing hook for the process_datamap() method.
*
* @access public
*
* @param string $status: 'new' or 'update'
* @param string $table: The destination table
* @param int $id: The uid of the record
* @param array &$fieldArray: Array of field values
*
* @return void
*/
public function processDatamap_postProcessFieldArray($status, $table, $id, &$fieldArray)
{
if ($status == 'new') {
switch ($table) {
// Field post-processing for table "tx_dlf_documents".
case 'tx_dlf_documents':
// Set sorting field if empty.
if (
empty($fieldArray['title_sorting'])
&& !empty($fieldArray['title'])
) {
$fieldArray['title_sorting'] = $fieldArray['title'];
}
break;
// Field post-processing for table "tx_dlf_metadata".
case 'tx_dlf_metadata':
// Store field in index if it should appear in lists.
if (!empty($fieldArray['is_listed'])) {
$fieldArray['index_stored'] = 1;
}
// Index field in index if it should be used for auto-completion.
if (!empty($fieldArray['index_autocomplete'])) {
$fieldArray['index_indexed'] = 1;
}
// Field post-processing for tables "tx_dlf_metadata", "tx_dlf_collections", "tx_dlf_libraries" and "tx_dlf_structures".
case 'tx_dlf_collections':
case 'tx_dlf_libraries':
case 'tx_dlf_structures':
// Set label as index name if empty.
if (
empty($fieldArray['index_name'])
&& !empty($fieldArray['label'])
) {
$fieldArray['index_name'] = $fieldArray['label'];
}
// Set index name as label if empty.
if (
empty($fieldArray['label'])
&& !empty($fieldArray['index_name'])
) {
$fieldArray['label'] = $fieldArray['index_name'];
}
// Ensure that index names don't get mixed up with sorting values.
if (substr($fieldArray['index_name'], -8) == '_sorting') {
$fieldArray['index_name'] .= '0';
}
break;
// Field post-processing for table "tx_dlf_solrcores".
case 'tx_dlf_solrcores':
// 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 = [];
}
break;
}
} elseif ($status == 'update') {
switch ($table) {
// Field post-processing for table "tx_dlf_metadata".
case 'tx_dlf_metadata':
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($table);
// Store field in index if it should appear in lists.
if (!empty($fieldArray['is_listed'])) {
$fieldArray['index_stored'] = 1;
}
if (
isset($fieldArray['index_stored'])
&& $fieldArray['index_stored'] == 0
&& !isset($fieldArray['is_listed'])
) {
// Get current configuration.
$result = $queryBuilder
->select($table . '.is_listed AS is_listed')
->from($table)
->where(
$queryBuilder->expr()->eq($table . '.uid', intval($id)),
Helper::whereExpression($table)
)
->setMaxResults(1)
->execute();
if ($resArray = $result->fetch()) {
// Reset storing to current.
$fieldArray['index_stored'] = $resArray['is_listed'];
}
}
// Index field in index if it should be used for auto-completion.
if (!empty($fieldArray['index_autocomplete'])) {
$fieldArray['index_indexed'] = 1;
}
if (
isset($fieldArray['index_indexed'])
&& $fieldArray['index_indexed'] == 0
&& !isset($fieldArray['index_autocomplete'])
) {
// Get current configuration.
$result = $queryBuilder
->select($table . '.index_autocomplete AS index_autocomplete')
->from($table)
->where(
$queryBuilder->expr()->eq($table . '.uid', intval($id)),
Helper::whereExpression($table)
)
->setMaxResults(1)
->execute();
if ($resArray = $result->fetch()) {
// Reset indexing to current.
$fieldArray['index_indexed'] = $resArray['index_autocomplete'];
}
}
break;
}
}
}
/**
* After database operations hook for the process_datamap() method.
*
* @access public
*
* @param string $status: 'new' or 'update'
* @param string $table: The destination table
* @param int $id: The uid of the record
* @param array &$fieldArray: Array of field values
*
* @return void
*/
public function processDatamap_afterDatabaseOperations($status, $table, $id, &$fieldArray)
{
if ($status == 'update') {
switch ($table) {
// After database operations for table "tx_dlf_documents".
case 'tx_dlf_documents':
// Delete/reindex document in Solr if "hidden" status or collections have changed.
if (
isset($fieldArray['hidden'])
|| isset($fieldArray['collections'])
) {
// Get Solr-Core.
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_dlf_solrcores');
$result = $queryBuilder
->select(
'tx_dlf_solrcores.uid AS core',
'tx_dlf_solrcores.index_name',
'tx_dlf_documents_join.hidden AS hidden'
)
->innerJoin(
'tx_dlf_solrcores',
'tx_dlf_documents',
'tx_dlf_documents_join',
$queryBuilder->expr()->eq(
'tx_dlf_documents_join.solrcore',
'tx_dlf_solrcores.uid'
)
)
->from('tx_dlf_solrcores')
->where(
$queryBuilder->expr()->eq(
'tx_dlf_documents_join.uid',
intval($id)
)
)
->setMaxResults(1)
->execute();
$allResults = $result->fetchAll();
if (count($allResults) == 1) {
$resArray = $allResults[0];
if ($resArray['hidden']) {
// Establish Solr connection.
$solr = Solr::getInstance($resArray['core']);
if ($solr->ready) {
// Delete Solr document.
$updateQuery = $solr->service->createUpdate();
$updateQuery->addDeleteQuery('uid:' . $id);
$updateQuery->addCommit();
$solr->service->update($updateQuery);
}
} else {
// Reindex document.
$doc = Document::getInstance($id);
if ($doc->ready) {
Indexer::add($doc, $resArray['core']);
} else {
Helper::devLog('Failed to re-index document with UID ' . $id, DEVLOG_SEVERITY_ERROR);
}
}
}
}
break;
}
}
}
/**
* Post-processing hook for the process_cmdmap() method.
*
* @access public
*
* @param string $command: 'move', 'copy', 'localize', 'inlineLocalizeSynchronize', 'delete' or 'undelete'
* @param string $table: The destination table
* @param int $id: The uid of the record
*
* @return void
*/
public function processCmdmap_postProcess($command, $table, $id)
{
if (
in_array($command, ['move', 'delete', 'undelete'])
&& $table == 'tx_dlf_documents'
) {
// Get Solr core.
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_dlf_solrcores');
// Record in "tx_dlf_documents" is already deleted at this point.
$queryBuilder
->getRestrictions()
->removeByType(DeletedRestriction::class);
$result = $queryBuilder
->select(
'tx_dlf_solrcores.uid AS core'
)
->innerJoin(
'tx_dlf_solrcores',
'tx_dlf_documents',
'tx_dlf_documents_join',
$queryBuilder->expr()->eq(
'tx_dlf_documents_join.solrcore',
'tx_dlf_solrcores.uid'
)
)
->from('tx_dlf_solrcores')
->where(
$queryBuilder->expr()->eq(
'tx_dlf_documents_join.uid',
intval($id)
)
)
->setMaxResults(1)
->execute();
$allResults = $result->fetchAll();
if (count($allResults) == 1) {
$resArray = $allResults[0];
switch ($command) {
case 'move':
case 'delete':
// Establish Solr connection.
$solr = Solr::getInstance($resArray['core']);
if ($solr->ready) {
// Delete Solr document.
$updateQuery = $solr->service->createUpdate();
$updateQuery->addDeleteQuery('uid:' . $id);
$updateQuery->addCommit();
$solr->service->update($updateQuery);
if ($command == 'delete') {
break;
}
}
case 'undelete':
// Reindex document.
$doc = Document::getInstance($id);
if ($doc->ready) {
Indexer::add($doc, $resArray['core']);
} else {
Helper::devLog('Failed to re-index document with UID ' . $id, DEVLOG_SEVERITY_ERROR);
}
break;
}
}
}
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);
}
}
}
}
}