mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-26 14:40:29 +01:00
394 lines
14 KiB
PHP
394 lines
14 KiB
PHP
|
<?php
|
||
|
/*
|
||
|
**** COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
|
||
|
*
|
||
|
* Xentral (c) Xentral ERP Sorftware GmbH, Fuggerstrasse 11, D-86150 Augsburg, * Germany 2019
|
||
|
*
|
||
|
* This file is licensed under the Embedded Projects General Public License *Version 3.1.
|
||
|
*
|
||
|
* You should have received a copy of this license from your vendor and/or *along with this file; If not, please visit www.wawision.de/Lizenzhinweis
|
||
|
* to obtain the text of the corresponding license version.
|
||
|
*
|
||
|
**** END OF COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
|
||
|
*/
|
||
|
?>
|
||
|
<?php
|
||
|
|
||
|
use Xentral\Components\Http\JsonResponse;
|
||
|
use Xentral\Modules\SuperSearch\Scheduler\SuperSearchFullIndexTask;
|
||
|
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||
|
use Xentral\Modules\SuperSearch\SuperSearchEngine;
|
||
|
use Xentral\Modules\SuperSearch\SuperSearchIndexer;
|
||
|
use Xentral\Modules\SuperSearch\SuperSearchService;
|
||
|
use Xentral\Widgets\SuperSearch\Query\DetailQuery;
|
||
|
use Xentral\Widgets\SuperSearch\Result\ResultDetail;
|
||
|
|
||
|
class SuperSearch
|
||
|
{
|
||
|
/** @var string MODULE_NAME */
|
||
|
const MODULE_NAME = 'SuperSearch';
|
||
|
|
||
|
/** @var ApplicationCore $app */
|
||
|
public $app;
|
||
|
|
||
|
/** @var array $javascript */
|
||
|
public $javascript = [
|
||
|
'./classes/Modules/SuperSearch/www/js/supersearch_ui.js',
|
||
|
];
|
||
|
|
||
|
/**
|
||
|
* @param ApplicationCore $app
|
||
|
* @param bool $intern
|
||
|
*/
|
||
|
public function __construct($app, $intern = false)
|
||
|
{
|
||
|
$this->app = $app;
|
||
|
|
||
|
if($intern !== false){
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$this->app->ActionHandlerInit($this);
|
||
|
$this->app->DefaultActionHandler('settings');
|
||
|
$this->app->ActionHandler('settings', 'SuperSearchSettings');
|
||
|
$this->app->ActionHandler('ajax', 'SuperSearchAjax');
|
||
|
$this->app->ActionHandlerListen($app);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return void
|
||
|
*/
|
||
|
public function Install()
|
||
|
{
|
||
|
$this->app->erp->CheckTable('supersearch_index_item');
|
||
|
$this->app->erp->CheckColumn('id', 'INT(10) UNSIGNED', 'supersearch_index_item', 'NOT NULL AUTO_INCREMENT');
|
||
|
$this->app->erp->CheckColumn('index_name', 'VARCHAR(16)', 'supersearch_index_item', 'NOT NULL');
|
||
|
$this->app->erp->CheckColumn('index_id', 'VARCHAR(38)', 'supersearch_index_item', 'NOT NULL');
|
||
|
$this->app->erp->CheckColumn('project_id', 'INT(10) UNSIGNED', 'supersearch_index_item', 'NOT NULL DEFAULT 0');
|
||
|
$this->app->erp->CheckColumn('title', 'VARCHAR(128)', 'supersearch_index_item', 'NOT NULL');
|
||
|
$this->app->erp->CheckColumn('subtitle', 'VARCHAR(128)', 'supersearch_index_item', 'NULL DEFAULT NULL');
|
||
|
$this->app->erp->CheckColumn('additional_infos', 'VARCHAR(255)', 'supersearch_index_item', 'NULL DEFAULT NULL');
|
||
|
$this->app->erp->CheckColumn('link', 'VARCHAR(128)', 'supersearch_index_item', 'NOT NULL');
|
||
|
$this->app->erp->CheckColumn('search_words', 'TEXT', 'supersearch_index_item', "NOT NULL DEFAULT ''");
|
||
|
$this->app->erp->CheckColumn('outdated', 'TINYINT(1) UNSIGNED', 'supersearch_index_item', "NOT NULL DEFAULT '0'");
|
||
|
$this->app->erp->CheckColumn('created_at', 'TIMESTAMP', 'supersearch_index_item', 'NOT NULL DEFAULT CURRENT_TIMESTAMP');
|
||
|
$this->app->erp->CheckColumn('updated_at', 'TIMESTAMP', 'supersearch_index_item', 'NULL DEFAULT NULL');
|
||
|
$this->app->erp->CheckIndex('supersearch_index_item', 'project_id');
|
||
|
$this->app->erp->CheckFulltextIndex('supersearch_index_item', 'search_words');
|
||
|
$this->app->erp->CheckAlterTable('ALTER TABLE `supersearch_index_item` ADD UNIQUE KEY `index_identifier` (`index_name`, `index_id`)');
|
||
|
|
||
|
$this->app->erp->CheckTable('supersearch_index_group');
|
||
|
$this->app->erp->CheckColumn('id', 'INT(10) UNSIGNED', 'supersearch_index_group', 'NOT NULL AUTO_INCREMENT');
|
||
|
$this->app->erp->CheckColumn('name', 'VARCHAR(16)', 'supersearch_index_group', 'NOT NULL');
|
||
|
$this->app->erp->CheckColumn('title', 'VARCHAR(32)', 'supersearch_index_group', 'NOT NULL');
|
||
|
$this->app->erp->CheckColumn('module', 'VARCHAR(38)', 'supersearch_index_group', 'NULL DEFAULT NULL');
|
||
|
$this->app->erp->CheckColumn('active', 'TINYINT(1) UNSIGNED', 'supersearch_index_group', "NOT NULL DEFAULT '1'");
|
||
|
$this->app->erp->CheckColumn('last_full_update', 'TIMESTAMP', 'supersearch_index_group', 'NULL DEFAULT NULL');
|
||
|
$this->app->erp->CheckColumn('last_diff_update', 'TIMESTAMP', 'supersearch_index_group', 'NULL DEFAULT NULL');
|
||
|
$this->app->erp->CheckAlterTable('ALTER TABLE `supersearch_index_group` ADD UNIQUE KEY `name` (`name`)');
|
||
|
|
||
|
$this->app->erp->CheckProzessstarter('SuperSearch Index-Full', 'uhrzeit', '', '2017-01-01 02:30:00', 'cronjob', 'supersearch_index_full', 1);
|
||
|
$this->app->erp->CheckProzessstarter('SuperSearch Index-Diff', 'periodisch', '3600', '', 'cronjob', 'supersearch_index_diff', 1);
|
||
|
|
||
|
$this->app->erp->RegisterHook('article_delete', 'supersearch', 'SuperSearchOnArticleDelete');
|
||
|
$this->app->erp->RegisterHook('address_delete', 'supersearch', 'SuperSearchOnAddressDelete');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int $articleId
|
||
|
*/
|
||
|
public function SuperSearchOnArticleDelete($articleId)
|
||
|
{
|
||
|
/** @var SuperSearchIndexer $indexer */
|
||
|
$indexer = $this->app->Container->get('SuperSearchIndexer');
|
||
|
$identifier = new IndexIdentifier('articles', (int)$articleId);
|
||
|
$indexer->deleteIndexItem($identifier);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int $addressId
|
||
|
*/
|
||
|
public function SuperSearchOnAddressDelete($addressId)
|
||
|
{
|
||
|
/** @var SuperSearchIndexer $indexer */
|
||
|
$indexer = $this->app->Container->get('SuperSearchIndexer');
|
||
|
$identifier = new IndexIdentifier('addresses', (int)$addressId);
|
||
|
$indexer->deleteIndexItem($identifier);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return void
|
||
|
*/
|
||
|
public function SuperSearchMenu()
|
||
|
{
|
||
|
$this->app->erp->MenuEintrag('index.php?module=supersearch&action=settings', 'Übersicht');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return void
|
||
|
*/
|
||
|
public function SuperSearchSettings()
|
||
|
{
|
||
|
$cmd = $this->app->Secure->GetPOST('cmd');
|
||
|
switch ($cmd) {
|
||
|
|
||
|
case 'run-full-index-task':
|
||
|
// Full-Index-Task ausführen
|
||
|
$response = $this->HandleSuperSearchSettingsFullIndexTask();
|
||
|
$response->send();
|
||
|
$this->app->ExitXentral();
|
||
|
break;
|
||
|
|
||
|
case 'activate-provider':
|
||
|
$response = $this->HandleSuperSearchSettingsActivateProvider();
|
||
|
$response->send();
|
||
|
$this->app->ExitXentral();
|
||
|
break;
|
||
|
|
||
|
case 'deactivate-provider':
|
||
|
$response = $this->HandleSuperSearchSettingsDeactivateProvider();
|
||
|
$response->send();
|
||
|
$this->app->ExitXentral();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Prüfen ob beide Cronjobs aktiv sind
|
||
|
$this->app->erp->checkActiveCronjob('supersearch_index_full');
|
||
|
$this->app->erp->checkActiveCronjob('supersearch_index_diff');
|
||
|
|
||
|
/** @var SuperSearchService $searchService */
|
||
|
$searchService = $this->app->Container->get('SuperSearchService');
|
||
|
if ($searchService->isIndexEmpty()) {
|
||
|
$searchIndexEmptyMessage = 'Der Such-Index ist leer. Die Einstellungen stehen erst zur Verfügung wenn der Such-Index einmalig gefüllt wurde.';
|
||
|
$this->app->Tpl->Add('MESSAGE', sprintf('<div class="info">%s</div>', $searchIndexEmptyMessage));
|
||
|
}
|
||
|
|
||
|
// Tabelle mit Index-Statistik zusammenbauen
|
||
|
$table = '<table class="mkTable">';
|
||
|
$table .= '<tr><th align="left">Index</th>';
|
||
|
$table .= '<th>Index-Größe (aktuell)</th>';
|
||
|
$table .= '<th>Index-Größe (potentiell)</th>';
|
||
|
$table .= '<th>Letzes Index-Update</th>';
|
||
|
$table .= '<th>Provider-Status</th>';
|
||
|
$table .= '<th>Aktionen</th>';
|
||
|
$table .= '</tr>';
|
||
|
$stats = $searchService->getIndexStats();
|
||
|
foreach ($stats as $info) {
|
||
|
$lastUpdate = $this->getGreatestDateTime($info['last_full_update'], $info['last_diff_update']);
|
||
|
$table .= '<tr>';
|
||
|
$table .= '<td><label>' . $info['title'] . ' (' . $info['name'] .')</label></td>';
|
||
|
$table .= '<td>' . ($info['index_size_current'] !== null ? $info['index_size_current'] : '<em>Unbekannt</em>') . '</td>';
|
||
|
$table .= '<td>' . ($info['index_size_potential'] !== null ? $info['index_size_potential'] : '<em>Unbekannt</em>') . '</td>';
|
||
|
$table .= '<td>' . ($lastUpdate !== null ? $lastUpdate->format('d.m.Y H:i:s') : '<em>NULL</em>') . '</td>';
|
||
|
$table .= '<td>';
|
||
|
if ($info['active'] === true) { $table .= 'Aktiv'; }
|
||
|
if ($info['active'] === false) { $table .= 'Inaktiv'; }
|
||
|
if ($info['active'] === null) { $table .= '<em>Unbekannt</em>'; }
|
||
|
$table .= '</td>';
|
||
|
$buttonTemplate = '<td><button type="button" data-index-name="%s" class="button button-secondary %s">%s</button></td>';
|
||
|
if ($info['active'] === true){
|
||
|
$table .= sprintf($buttonTemplate, $info['name'], 'button-provider-deactivate', 'Such-Index deaktivieren');
|
||
|
}
|
||
|
if ($info['active'] === false) {
|
||
|
$table .= sprintf($buttonTemplate, $info['name'], 'button-provider-activate', 'Such-Index aktivieren');
|
||
|
}
|
||
|
if ($info['active'] === null) {
|
||
|
$table .= '<td></td>';
|
||
|
}
|
||
|
$table .= '</tr>';
|
||
|
}
|
||
|
$table .= '</table>';
|
||
|
// ENDE Tabelle mit Index-Statistik zusammenbauen
|
||
|
|
||
|
$this->SuperSearchMenu();
|
||
|
$this->app->Tpl->Set('UEBERSCHRIFT', 'SuperSearch');
|
||
|
$this->app->Tpl->Set('KURZUEBERSCHRIFT', 'SuperSearch');
|
||
|
$this->app->Tpl->Set('TABTEXT', 'SuperSearch');
|
||
|
|
||
|
$this->app->Tpl->Set('INDEXSTATSTABLE', $table);
|
||
|
$this->app->Tpl->Parse('PAGE', 'supersearch_settings.tpl');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return void
|
||
|
*/
|
||
|
public function SuperSearchAjax()
|
||
|
{
|
||
|
$cmd = $this->app->Secure->GetGET('cmd');
|
||
|
switch ($cmd) {
|
||
|
|
||
|
case 'search':
|
||
|
// Suchergebnisse ermitteln
|
||
|
$response = $this->HandleSuperSearchAjaxSearch();
|
||
|
break;
|
||
|
|
||
|
case 'detail':
|
||
|
// Detail-Informationen nachladen: Bei Klick auf ein einzelnes Ergebnis
|
||
|
$response = $this->HandleSuperSearchAjaxDetail();
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (!isset($response)) {
|
||
|
$response = new JsonResponse(
|
||
|
['success' => false, 'error' => 'Parameter \'cmd\' ungültig.'],
|
||
|
JsonResponse::HTTP_NOT_FOUND
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Ausgabe
|
||
|
$response->send();
|
||
|
$this->app->erp->ExitWawi();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return JsonResponse
|
||
|
*/
|
||
|
protected function HandleSuperSearchSettingsFullIndexTask()
|
||
|
{
|
||
|
/** @var SuperSearchFullIndexTask $indexTask */
|
||
|
$indexTask = $this->app->Container->get('SuperSearchFullIndexTask');
|
||
|
|
||
|
try {
|
||
|
$indexTask->execute();
|
||
|
$indexTask->cleanup();
|
||
|
} catch (Exception $exception) {
|
||
|
$indexTask->cleanup();
|
||
|
return new JsonResponse(
|
||
|
['success' => false, 'error' => $exception->getMessage()],
|
||
|
JsonResponse::HTTP_INTERNAL_SERVER_ERROR
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return new JsonResponse(['success' => true]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return JsonResponse
|
||
|
*/
|
||
|
protected function HandleSuperSearchSettingsActivateProvider()
|
||
|
{
|
||
|
$indexName = $this->app->Secure->GetPOST('index_name');
|
||
|
|
||
|
try {
|
||
|
/** @var SuperSearchService $searchService */
|
||
|
$searchService = $this->app->Container->get('SuperSearchService');
|
||
|
$searchService->activateIndex($indexName);
|
||
|
} catch (Exception $exception) {
|
||
|
return new JsonResponse(
|
||
|
['success' => false, 'error' => $exception->getMessage()],
|
||
|
JsonResponse::HTTP_INTERNAL_SERVER_ERROR
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return new JsonResponse(['success' => true]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return JsonResponse
|
||
|
*/
|
||
|
protected function HandleSuperSearchSettingsDeactivateProvider()
|
||
|
{
|
||
|
$indexName = $this->app->Secure->GetPOST('index_name');
|
||
|
|
||
|
try {
|
||
|
/** @var SuperSearchService $searchService */
|
||
|
$searchService = $this->app->Container->get('SuperSearchService');
|
||
|
$searchService->deactivateIndex($indexName);
|
||
|
} catch (Exception $exception) {
|
||
|
return new JsonResponse(
|
||
|
['success' => false, 'error' => $exception->getMessage()],
|
||
|
JsonResponse::HTTP_INTERNAL_SERVER_ERROR
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return new JsonResponse(['success' => true]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return JsonResponse
|
||
|
*/
|
||
|
protected function HandleSuperSearchAjaxSearch()
|
||
|
{
|
||
|
$searchTerm = stripslashes($this->app->Secure->GetPOST('search_query'));
|
||
|
if (strlen(trim($searchTerm)) >= 3) {
|
||
|
|
||
|
/** @var SuperSearchEngine $searchEngine */
|
||
|
$searchEngine = $this->app->Container->get('SuperSearchEngine');
|
||
|
$projectIds = $this->app->User->GetType() !== 'admin' ? $this->app->User->getUserProjects() : null;
|
||
|
$moduleNames = $this->app->User->GetType() !== 'admin' ? $this->app->erp->getUserModules() : null;
|
||
|
$searchResult = $searchEngine->search($searchTerm, $projectIds, $moduleNames);
|
||
|
|
||
|
// Ergebnis leer > Prüfen ob SuchIndex gefüllt
|
||
|
if ($searchResult->isEmpty() && $searchResult->getLastIndexUpdateTime() === null) {
|
||
|
return new JsonResponse(
|
||
|
[
|
||
|
'success' => false,
|
||
|
'error' =>
|
||
|
'<p>Such-Index ist nicht gefüllt. Bitte prüfen ob Prozessstarter aktiv sind.</p>'.
|
||
|
'<a class="button button-secondary" href="index.php?module=supersearch&action=settings">'.
|
||
|
'Zu den SuperSearch-Einstellungen'.
|
||
|
'</a>',
|
||
|
'data' => 'index-empty',
|
||
|
],
|
||
|
JsonResponse::HTTP_INTERNAL_SERVER_ERROR
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
return new JsonResponse(['success' => true, 'data' => $searchResult]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return JsonResponse
|
||
|
*/
|
||
|
protected function HandleSuperSearchAjaxDetail()
|
||
|
{
|
||
|
$detailGroup = $this->app->Secure->GetPOST('detail_group');
|
||
|
$detailIdentifier = $this->app->Secure->GetPOST('detail_identifier');
|
||
|
|
||
|
$detailQuery = new DetailQuery($detailGroup, $detailIdentifier);
|
||
|
$detailResult = new ResultDetail();
|
||
|
$this->app->erp->RunHook('supersearch_detail', 2, $detailQuery, $detailResult);
|
||
|
return new JsonResponse(['success' => true, 'data' => $detailResult]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param string|null $lastFullUpdate
|
||
|
* @param string|null $lastDiffUpdate
|
||
|
*
|
||
|
* @return DateTimeImmutable|null
|
||
|
*/
|
||
|
protected function getGreatestDateTime($lastFullUpdate = null, $lastDiffUpdate = null)
|
||
|
{
|
||
|
if (!empty($lastFullUpdate)){
|
||
|
try {
|
||
|
$lastFullUpdateTime = new \DateTimeImmutable($lastFullUpdate);
|
||
|
} catch (Exception $exception) {
|
||
|
}
|
||
|
}
|
||
|
if (!empty($lastDiffUpdate)) {
|
||
|
try {
|
||
|
$lastDiffUpdateTime = new \DateTimeImmutable($lastDiffUpdate);
|
||
|
} catch (Exception $exception) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (isset($lastFullUpdateTime) && !isset($lastDiffUpdateTime)) {
|
||
|
return $lastFullUpdateTime;
|
||
|
}
|
||
|
if (!isset($lastFullUpdateTime) && isset($lastDiffUpdateTime)) {
|
||
|
return $lastDiffUpdateTime;
|
||
|
}
|
||
|
if (isset($lastFullUpdateTime) && isset($lastDiffUpdateTime)) {
|
||
|
if ($lastFullUpdateTime > $lastDiffUpdateTime) {
|
||
|
return $lastFullUpdateTime;
|
||
|
} else {
|
||
|
return $lastDiffUpdateTime;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
}
|