Initial xentral_oss_20.3.c9ffacf
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch;
|
||||
|
||||
use Xentral\Core\DependencyInjection\ContainerInterface;
|
||||
use Xentral\Modules\SuperSearch\Factory\ProviderFactory;
|
||||
use Xentral\Modules\SuperSearch\Scheduler\SuperSearchDiffIndexTask;
|
||||
use Xentral\Modules\SuperSearch\Scheduler\SuperSearchFullIndexTask;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\AddressProvider;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\AppProvider;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\ArticleProvider;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\CreditNoteProvider;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\InvoiceProvider;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\OfferProvider;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\OrderProvider;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\DeliveryNoteProvider;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\TrackingNumberProvider;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\SearchIndexProviderInterface;
|
||||
use Xentral\Modules\SuperSearch\SystemHealth\SuperSearchHealthChecker;
|
||||
use Xentral\Modules\SuperSearch\Wrapper\CompanyConfigWrapper;
|
||||
|
||||
final class Bootstrap
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function registerServices()
|
||||
{
|
||||
return [
|
||||
'SuperSearchService' => 'onInitSuperSearchService',
|
||||
'SuperSearchIndexer' => 'onInitSuperSearchIndexer',
|
||||
'SuperSearchEngine' => 'onInitSuperSearchEngine',
|
||||
'SuperSearchProviderFactory' => 'onInitSuperSearchProviderFactory',
|
||||
'SuperSearchHealthChecker' => 'onInitSuperSearchHealthChecker',
|
||||
|
||||
// Cronjob-Tasks
|
||||
'SuperSearchFullIndexTask' => 'onInitSuperSearchFullIndexTask',
|
||||
'SuperSearchDiffIndexTask' => 'onInitSuperSearchDiffIndexTask',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return SuperSearchService
|
||||
*/
|
||||
public static function onInitSuperSearchService(ContainerInterface $container)
|
||||
{
|
||||
return new SuperSearchService($container->get('Database'), $container->get('SuperSearchIndexer'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return SuperSearchEngine
|
||||
*/
|
||||
public static function onInitSuperSearchEngine(ContainerInterface $container)
|
||||
{
|
||||
return new SuperSearchEngine($container->get('Database'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return SuperSearchIndexer
|
||||
*/
|
||||
public static function onInitSuperSearchIndexer(ContainerInterface $container)
|
||||
{
|
||||
$provider = self::createSearchIndexProvider($container);
|
||||
|
||||
return new SuperSearchIndexer($container->get('Database'), $provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return ProviderFactory
|
||||
*/
|
||||
public static function onInitSuperSearchProviderFactory(ContainerInterface $container)
|
||||
{
|
||||
$factory = new ProviderFactory($container->get('Database'));
|
||||
|
||||
$factory->registerProviderFactory(
|
||||
'addresses', static function (ContainerInterface $container) {
|
||||
return new AddressProvider($container->get('Database'));
|
||||
});
|
||||
$factory->registerProviderFactory(
|
||||
'articles', static function (ContainerInterface $container) {
|
||||
return new ArticleProvider($container->get('Database'));
|
||||
});
|
||||
$factory->registerProviderFactory(
|
||||
'creditnotes', static function (ContainerInterface $container) {
|
||||
return new CreditNoteProvider($container->get('Database'));
|
||||
});
|
||||
$factory->registerProviderFactory(
|
||||
'deliverynote', static function (ContainerInterface $container) {
|
||||
return new DeliveryNoteProvider($container->get('Database'));
|
||||
});
|
||||
$factory->registerProviderFactory(
|
||||
'invoices', static function (ContainerInterface $container) {
|
||||
return new InvoiceProvider($container->get('Database'));
|
||||
});
|
||||
$factory->registerProviderFactory(
|
||||
'offers', static function (ContainerInterface $container) {
|
||||
return new OfferProvider($container->get('Database'));
|
||||
});
|
||||
$factory->registerProviderFactory(
|
||||
'orders', static function (ContainerInterface $container) {
|
||||
return new OrderProvider($container->get('Database'));
|
||||
});
|
||||
$factory->registerProviderFactory(
|
||||
'trackingnumber', static function (ContainerInterface $container) {
|
||||
return new TrackingNumberProvider($container->get('Database'));
|
||||
});
|
||||
$factory->registerProviderFactory(
|
||||
'apps',
|
||||
static function (ContainerInterface $container) {
|
||||
/** @var \ApplicationCore $app */
|
||||
$app = $container->get('LegacyApplication');
|
||||
/** @var \Appstore $appstoreModule */
|
||||
$appstoreModule = $app->erp->LoadModul('appstore');
|
||||
|
||||
return new AppProvider($appstoreModule);
|
||||
}
|
||||
);
|
||||
|
||||
return $factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return SuperSearchHealthChecker
|
||||
*/
|
||||
public static function onInitSuperSearchHealthChecker(ContainerInterface $container)
|
||||
{
|
||||
return new SuperSearchHealthChecker($container->get('Database'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return SuperSearchFullIndexTask
|
||||
*/
|
||||
public static function onInitSuperSearchFullIndexTask(ContainerInterface $container)
|
||||
{
|
||||
/** @var SuperSearchService $service */
|
||||
$service = $container->get('SuperSearchService');
|
||||
|
||||
/** @var SuperSearchIndexer $factory */
|
||||
$indexer = $container->get('SuperSearchIndexer');
|
||||
|
||||
$config = self::onInitCompanyConfigWrapper($container);
|
||||
|
||||
return new SuperSearchFullIndexTask($service, $indexer, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return SuperSearchDiffIndexTask
|
||||
*/
|
||||
public static function onInitSuperSearchDiffIndexTask(ContainerInterface $container)
|
||||
{
|
||||
/** @var SuperSearchService $service */
|
||||
$service = $container->get('SuperSearchService');
|
||||
|
||||
/** @var SuperSearchIndexer $factory */
|
||||
$indexer = $container->get('SuperSearchIndexer');
|
||||
|
||||
$config = self::onInitCompanyConfigWrapper($container);
|
||||
|
||||
return new SuperSearchDiffIndexTask($service, $indexer, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return SearchIndexProviderInterface[]|array
|
||||
*/
|
||||
private static function createSearchIndexProvider(ContainerInterface $container)
|
||||
{
|
||||
/** @var ProviderFactory $factory */
|
||||
$factory = $container->get('SuperSearchProviderFactory');
|
||||
|
||||
return $factory->createActiveProviders($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return CompanyConfigWrapper
|
||||
*/
|
||||
private static function onInitCompanyConfigWrapper(ContainerInterface $container)
|
||||
{
|
||||
/** @var \ApplicationCore $app */
|
||||
$app = $container->get('LegacyApplication');
|
||||
|
||||
return new CompanyConfigWrapper($app->erp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class FormatterFailureException extends RuntimeException implements SuperSearchExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\Exception;
|
||||
|
||||
final class InvalidArgumentException extends \InvalidArgumentException implements SuperSearchExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\Exception;
|
||||
|
||||
use LogicException;
|
||||
|
||||
final class InvalidReturnTypeException extends LogicException implements SuperSearchExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class InvalidReturnValueException extends RuntimeException implements SuperSearchExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\Exception;
|
||||
|
||||
use LogicException;
|
||||
|
||||
final class ProviderIncompatibleException extends LogicException implements SuperSearchExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class ProviderMissingException extends RuntimeException implements SuperSearchExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\Exception;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class SchedulerTaskAlreadyRunningException extends RuntimeException implements SuperSearchExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\Exception;
|
||||
|
||||
interface SuperSearchExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\Factory;
|
||||
|
||||
use Xentral\Components\Database\Database;
|
||||
use Xentral\Core\DependencyInjection\ContainerInterface;
|
||||
use Xentral\Modules\SuperSearch\Exception\InvalidArgumentException;
|
||||
use Xentral\Modules\SuperSearch\Exception\InvalidReturnTypeException;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\SearchIndexProviderInterface;
|
||||
|
||||
final class ProviderFactory
|
||||
{
|
||||
/** @var Database $db */
|
||||
private $db;
|
||||
|
||||
/** @var array $callbacks */
|
||||
private $callbacks = [];
|
||||
|
||||
/**
|
||||
* @param Database $database
|
||||
*/
|
||||
public function __construct(Database $database)
|
||||
{
|
||||
$this->db = $database;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @return array|SearchIndexProviderInterface[]
|
||||
*/
|
||||
public function createActiveProviders(ContainerInterface $container)
|
||||
{
|
||||
// Grundsätzlich sind alle registrierten Provider aktiv
|
||||
$indexNames = array_keys($this->callbacks);
|
||||
|
||||
// Inaktiv markierte Provider aus Liste entfernen
|
||||
$sql = 'SELECT sig.name FROM `supersearch_index_group` AS `sig` WHERE sig.active = 0';
|
||||
$inactiveIndexes = $this->db->fetchCol($sql);
|
||||
foreach ($inactiveIndexes as $inactiveIndex) {
|
||||
$key = array_search($inactiveIndex, $indexNames, true);
|
||||
if ($key !== false) {
|
||||
unset($indexNames[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// Provider-Instanzen erzeugen
|
||||
$providers = [];
|
||||
foreach ($indexNames as $indexName) {
|
||||
$providers[] = $this->createProvider($indexName, $container);
|
||||
}
|
||||
|
||||
return $providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $indexName
|
||||
* @param callable $factoryMethod
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerProviderFactory($indexName, callable $factoryMethod)
|
||||
{
|
||||
if (!is_callable($factoryMethod, true)) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Factory method for class "%s" is not callable.', $indexName
|
||||
));
|
||||
}
|
||||
|
||||
$this->callbacks[$indexName] = $factoryMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function hasProviderFactory($className)
|
||||
{
|
||||
return isset($this->callbacks[$className]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param ContainerInterface $container
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* @throws InvalidReturnTypeException
|
||||
*
|
||||
* @return SearchIndexProviderInterface
|
||||
*/
|
||||
private function createProvider($className, ContainerInterface $container)
|
||||
{
|
||||
if (!$this->hasProviderFactory($className)) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Provider class "%s" does not exists.', $className
|
||||
));
|
||||
}
|
||||
$callback = $this->callbacks[$className];
|
||||
|
||||
$provider = $callback($container);
|
||||
if (!$provider instanceof SearchIndexProviderInterface) {
|
||||
throw new InvalidReturnTypeException(sprintf(
|
||||
'Factory method for class "%s" returned invalid type. Provider must implement "%s".',
|
||||
$className,
|
||||
SearchIndexProviderInterface::class
|
||||
));
|
||||
}
|
||||
|
||||
return $provider;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\Scheduler;
|
||||
|
||||
use Xentral\Modules\SuperSearch\SuperSearchIndexer;
|
||||
use Xentral\Modules\SuperSearch\SuperSearchService;
|
||||
use Xentral\Modules\SuperSearch\Wrapper\CompanyConfigWrapper;
|
||||
|
||||
final class SuperSearchDiffIndexTask
|
||||
{
|
||||
/** @var SuperSearchService $service */
|
||||
private $service;
|
||||
|
||||
/** @var SuperSearchIndexer $indexer */
|
||||
private $indexer;
|
||||
|
||||
/** @var CompanyConfigWrapper $config */
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @param SuperSearchService $service
|
||||
* @param SuperSearchIndexer $indexer
|
||||
* @param CompanyConfigWrapper $config
|
||||
*/
|
||||
public function __construct(SuperSearchService $service, SuperSearchIndexer $indexer, CompanyConfigWrapper $config)
|
||||
{
|
||||
$this->service = $service;
|
||||
$this->indexer = $indexer;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$fullIndexCronjobActive = (int)$this->config->get('supersearch_full_index_task_mutex');
|
||||
|
||||
// Diff-Index nur ausführen wenn Full-Index-Cronjob gerade nicht läuft
|
||||
if ($fullIndexCronjobActive === 0) {
|
||||
$this->updateIndexes();
|
||||
}
|
||||
|
||||
// Full-Index läuft gerade > Zähler erhöhen
|
||||
if ($fullIndexCronjobActive > 0) {
|
||||
$this->config->set('supersearch_full_index_task_mutex', (string)($fullIndexCronjobActive + 1));
|
||||
}
|
||||
|
||||
// Full-Index läuft schon sehr lange (eher ein Fehler) > Zähler zurücksetzen
|
||||
if ($fullIndexCronjobActive > 3) {
|
||||
$this->config->set('supersearch_full_index_task_mutex', '0');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function updateIndexes()
|
||||
{
|
||||
$meta = $this->indexer->getProviderMetaData();
|
||||
foreach ($meta as $row) {
|
||||
$indexName = $row['name'];
|
||||
$indexTitle = $row['title'];
|
||||
$moduleName = $row['module'];
|
||||
|
||||
// Sicherstellen dass die Indexe für die registrierten Provider vorhanden sind
|
||||
if (!$this->service->existsIndex($indexName)) {
|
||||
$this->service->createIndex($indexName, $indexTitle, $moduleName);
|
||||
}
|
||||
|
||||
/*
|
||||
* Such-Index befüllen
|
||||
*/
|
||||
|
||||
// Diff-Index wurde schon einmal ausgeführt > Diff-Index wieder ausführen
|
||||
$lastDiffIndexTime = $this->indexer->getLastDiffIndexTime($indexName);
|
||||
if ($lastDiffIndexTime !== null) {
|
||||
$this->indexer->updateIndexSince($indexName, $lastDiffIndexTime);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Diff-Index und Full-Index wurden noch nie ausgeführt => FullIndex ausführen
|
||||
$lastFullIndexTime = $this->indexer->getLastFullIndexTime($indexName);
|
||||
if ($lastDiffIndexTime === null && $lastFullIndexTime === null) {
|
||||
$this->indexer->updateIndexFull($indexName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function cleanup()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\Scheduler;
|
||||
|
||||
use Xentral\Modules\SuperSearch\Exception\SchedulerTaskAlreadyRunningException;
|
||||
use Xentral\Modules\SuperSearch\Exception\SuperSearchExceptionInterface;
|
||||
use Xentral\Modules\SuperSearch\SuperSearchIndexer;
|
||||
use Xentral\Modules\SuperSearch\SuperSearchService;
|
||||
use Xentral\Modules\SuperSearch\Wrapper\CompanyConfigWrapper;
|
||||
|
||||
final class SuperSearchFullIndexTask
|
||||
{
|
||||
/** @var SuperSearchService $service */
|
||||
private $service;
|
||||
|
||||
/** @var SuperSearchIndexer $indexer */
|
||||
private $indexer;
|
||||
|
||||
/** @var CompanyConfigWrapper $config */
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @param SuperSearchService $service
|
||||
* @param SuperSearchIndexer $indexer
|
||||
* @param CompanyConfigWrapper $config
|
||||
*/
|
||||
public function __construct(SuperSearchService $service, SuperSearchIndexer $indexer, CompanyConfigWrapper $config)
|
||||
{
|
||||
$this->service = $service;
|
||||
$this->indexer = $indexer;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws SuperSearchExceptionInterface
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
// Prüfen ob Full-Index-Cronjob bereits läuft > Mehrfachausführung verhindern
|
||||
$fullIndexActive = (int)$this->config->get('supersearch_full_index_task_mutex');
|
||||
if ($fullIndexActive > 0) {
|
||||
throw new SchedulerTaskAlreadyRunningException(
|
||||
'SuperSearch full index task is already running. Task can only run once at a time.'
|
||||
);
|
||||
}
|
||||
|
||||
// Full-Index-Cronjob als Aktiv markieren >
|
||||
// Diff-Index-Cronjob prüft den Wert und überspringt dann wenn Full-Index-Cronjob läuft.
|
||||
$this->config->set('supersearch_full_index_task_mutex', '1');
|
||||
$this->updateIndexes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function cleanup()
|
||||
{
|
||||
$this->config->set('supersearch_full_index_task_mutex', '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function updateIndexes()
|
||||
{
|
||||
$meta = $this->indexer->getProviderMetaData();
|
||||
foreach ($meta as $row) {
|
||||
$indexName = $row['name'];
|
||||
$indexTitle = $row['title'];
|
||||
$moduleName = $row['module'];
|
||||
|
||||
// Sicherstellen dass die Indexe für die registrierten Provider vorhanden sind
|
||||
if (!$this->service->existsIndex($indexName)) {
|
||||
$this->service->createIndex($indexName, $indexTitle, $moduleName);
|
||||
}
|
||||
|
||||
// Such-Index befüllen
|
||||
$this->indexer->updateIndexFull($indexName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchEngine;
|
||||
|
||||
use Xentral\Components\Util\StringUtil;
|
||||
|
||||
final class SearchTermParser
|
||||
{
|
||||
/**
|
||||
* @internal Operators in Boolean search mode: +, -, > <, ( ), ~, *, ", @distance
|
||||
*
|
||||
* @param string $searchTerm
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parse($searchTerm)
|
||||
{
|
||||
// Remove unused (not supported by us) search operators: *, > <, ( ), @distance
|
||||
$searchTerm = preg_replace('/[><()*@]+/', '', $searchTerm);
|
||||
|
||||
$searchWords = preg_split('/([\s]+)/um', $searchTerm, -1, PREG_SPLIT_NO_EMPTY);
|
||||
if ($searchWords === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
foreach ($searchWords as &$searchWord) {
|
||||
|
||||
if (strlen($searchWord) < 3) {
|
||||
$searchWord = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
$hasLeadingTilde = StringUtil::startsWith($searchWord, '~');
|
||||
$searchWord = ltrim($searchWord, '~');
|
||||
|
||||
$hasLeadingMinus = StringUtil::startsWith($searchWord, '-');
|
||||
$searchWord = trim($searchWord, '-'); // Trim both sides; InnoDB only supports leading minus signs
|
||||
|
||||
$hasLeadingPlus = StringUtil::startsWith($searchWord, '+');
|
||||
$searchWord = trim($searchWord, '+'); // Trim both sides; InnoDB only supports leading plus signs
|
||||
|
||||
$hasLeadingQuote = StringUtil::startsWith($searchWord, '"');
|
||||
$hasTrailingQuote = StringUtil::endsWith($searchWord, '"');
|
||||
$searchWord = trim($searchWord, '"');
|
||||
|
||||
// Operatoren innerhalb eines Suchworts entfernen
|
||||
$searchWord = preg_replace('/[+\-~\"]+/', '', $searchWord);
|
||||
|
||||
$searchWord = trim($searchWord);
|
||||
if (strlen($searchWord) < 3) {
|
||||
$searchWord = ''; // Zu kurze Suchwörter ignorieren
|
||||
continue;
|
||||
}
|
||||
|
||||
// Beispiel: `"foobar"`
|
||||
// Kombination mit Operatoren möglich: `+"foobar"` oder `-"foobar"` oder `~"foobar"`
|
||||
if ($hasLeadingQuote && $hasTrailingQuote) {
|
||||
$searchWord = '"' . $searchWord . '"';
|
||||
}
|
||||
|
||||
// Operatoren vorne anfügen
|
||||
if ($hasLeadingTilde) {
|
||||
$searchWord = '~' . $searchWord;
|
||||
}
|
||||
if ($hasLeadingMinus) {
|
||||
$searchWord = '-' . $searchWord;
|
||||
}
|
||||
if ($hasLeadingPlus) {
|
||||
$searchWord = '+' . $searchWord;
|
||||
}
|
||||
|
||||
// Default: Wildcard hinten, nur wenn keine Anführungszeichen
|
||||
if (!$hasLeadingQuote && !$hasTrailingQuote) {
|
||||
$searchWord .= '*';
|
||||
}
|
||||
}
|
||||
unset($searchWord);
|
||||
|
||||
return trim(implode(' ', $searchWords));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Collection;
|
||||
|
||||
use ArrayObject;
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Iterator;
|
||||
use IteratorAggregate;
|
||||
use Xentral\Modules\SuperSearch\Exception\InvalidArgumentException;
|
||||
use Xentral\Modules\SuperSearch\Exception\InvalidReturnTypeException;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
|
||||
final class ItemFormatterCollection implements Iterator
|
||||
{
|
||||
/** @var Iterator $data */
|
||||
private $data;
|
||||
|
||||
/** @var callable $callback */
|
||||
private $callback;
|
||||
|
||||
/**
|
||||
* @param array|Iterator $data
|
||||
* @param callable|Closure $callback
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct($data, $callback)
|
||||
{
|
||||
if (!is_callable($callback, false)) {
|
||||
throw new InvalidArgumentException('Callback is not callable');
|
||||
}
|
||||
$this->callback = $callback;
|
||||
|
||||
$type = gettype($data);
|
||||
if ($type === 'object') {
|
||||
$type = get_class($data);
|
||||
if ($data instanceof Iterator) {
|
||||
$type = 'Iterator';
|
||||
}
|
||||
if ($data instanceof IteratorAggregate) {
|
||||
$type = 'IteratorAggregate';
|
||||
}
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case 'array':
|
||||
$this->data = (new ArrayObject($data))->getIterator();
|
||||
break;
|
||||
|
||||
case 'Iterator':
|
||||
$this->data = $data;
|
||||
break;
|
||||
|
||||
case 'IteratorAggregate':
|
||||
try {
|
||||
$this->data = $data->getIterator();
|
||||
} catch (Exception $exception) {
|
||||
throw new InvalidArgumentException($exception->getMessage(), $exception->getCode(), $exception);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf('Unsupported type "%s".', $type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current element
|
||||
*
|
||||
* @throws InvalidReturnTypeException
|
||||
*
|
||||
* @return IndexItem
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
$result = call_user_func($this->callback, $this->data->current(), $this->data->key());
|
||||
if (!$result instanceof IndexItem) {
|
||||
throw new InvalidReturnTypeException(sprintf(
|
||||
'Formatter return type is invalid . Callable must return an object with type "%s".',
|
||||
IndexItem::class
|
||||
));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move forward to next element
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
$this->data->next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the key of the current element
|
||||
*
|
||||
* @return mixed scalar on success, or null on failure.
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return $this->data->key();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if current position is valid
|
||||
*
|
||||
* @return boolean Returns true on success or false on failure.
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return $this->data->valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind the Iterator to the first element
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
$this->data->rewind();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Data;
|
||||
|
||||
use Xentral\Modules\SuperSearch\Exception\InvalidArgumentException;
|
||||
|
||||
final class IndexData
|
||||
{
|
||||
/** @var int $projectId */
|
||||
private $projectId;
|
||||
|
||||
/** @var string $title */
|
||||
private $title;
|
||||
|
||||
/** @var string|null $subTitle */
|
||||
private $subTitle;
|
||||
|
||||
/** @var array|string[] $additionalInfos */
|
||||
private $additionalInfos;
|
||||
|
||||
/** @var string $link */
|
||||
private $link;
|
||||
|
||||
/** @var array $words */
|
||||
private $words;
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
* @param string $link
|
||||
* @param int $projectId
|
||||
* @param array $words
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct($title, $link, $projectId = 0, array $words = [])
|
||||
{
|
||||
if (empty($title)) {
|
||||
$title = 'empty';
|
||||
}
|
||||
if (empty($link)) {
|
||||
throw new InvalidArgumentException('Invalid argument value. $link parameter can not be empty.');
|
||||
}
|
||||
if (!is_int($projectId)) {
|
||||
throw new InvalidArgumentException('Invalid argument type. Parameter $projectId must be type integer.');
|
||||
}
|
||||
|
||||
$this->projectId = (int)$projectId;
|
||||
$this->title = (string)$title;
|
||||
$this->link = (string)$link;
|
||||
$this->addSearchWords($words);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $state
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function fromDbState(array $state)
|
||||
{
|
||||
return new self(
|
||||
(string)$state['title'],
|
||||
(string)$state['link'],
|
||||
(int)$state['project_id'],
|
||||
(array)$state['search_words']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $subTitle
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setSubTitle($subTitle)
|
||||
{
|
||||
$subTitle = trim($subTitle);
|
||||
if ($subTitle === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->subTitle = (string)$subTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $additionalInfo
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addAdditionalInfo($additionalInfo)
|
||||
{
|
||||
$additionalInfo = trim($additionalInfo);
|
||||
if ($additionalInfo === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->additionalInfos[] = (string)$additionalInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string[] $words
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addSearchWords(array $words)
|
||||
{
|
||||
foreach ($words as $word) {
|
||||
$this->addSearchWord($word);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $word
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addSearchWord($word)
|
||||
{
|
||||
$word = trim($word);
|
||||
if ($word === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->words[] = $word;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getSubTitle()
|
||||
{
|
||||
return $this->subTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|string[]
|
||||
*/
|
||||
public function getAdditionalInfos()
|
||||
{
|
||||
return $this->additionalInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLink()
|
||||
{
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getProjectId()
|
||||
{
|
||||
return $this->projectId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getWords()
|
||||
{
|
||||
return $this->words;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Data;
|
||||
|
||||
use Xentral\Modules\SuperSearch\Exception\InvalidArgumentException;
|
||||
|
||||
final class IndexIdentifier
|
||||
{
|
||||
/** @var string $name */
|
||||
private $name;
|
||||
|
||||
/** @var int $id */
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param int|string $id
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function __construct($name, $id)
|
||||
{
|
||||
if (empty($name)) {
|
||||
throw new InvalidArgumentException('Invalid argument value. $name parameter can not be empty.');
|
||||
}
|
||||
if (empty($id)) {
|
||||
throw new InvalidArgumentException('Invalid argument value. $id parameter can not be empty.');
|
||||
}
|
||||
if (strlen($name) > 16) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Invalid argument value "%s". Max length for $id is 16 characters.', $name
|
||||
));
|
||||
}
|
||||
if (strlen($id) > 38) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Invalid argument value "%s". Max length for $id is 38 characters.', $id
|
||||
));
|
||||
}
|
||||
if (preg_match('/[^a-z]+/', $name) === 1) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Invalid argument value "%s". Valid characters for $name parameter: a-z', $name
|
||||
));
|
||||
}
|
||||
|
||||
$this->name = (string)$name;
|
||||
$this->id = is_numeric($id) ? (int)$id : (string)$id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|string
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Data;
|
||||
|
||||
final class IndexItem
|
||||
{
|
||||
/** @var IndexIdentifier $identifier */
|
||||
public $identifier;
|
||||
|
||||
/** @var IndexData $data */
|
||||
public $data;
|
||||
|
||||
/** @var string|null $module */
|
||||
public $module;
|
||||
|
||||
/**
|
||||
* @param IndexIdentifier $identifier
|
||||
* @param IndexData $data
|
||||
* @param string|null $moduleName
|
||||
*/
|
||||
public function __construct(IndexIdentifier $identifier, IndexData $data, $moduleName = null)
|
||||
{
|
||||
$this->identifier = $identifier;
|
||||
$this->data = $data;
|
||||
$this->module = $moduleName;
|
||||
}
|
||||
}
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use Closure;
|
||||
use DateTimeInterface;
|
||||
use Exception;
|
||||
use Xentral\Components\Database\Database;
|
||||
use Xentral\Components\Database\SqlQuery\SelectQuery;
|
||||
use Xentral\Modules\SuperSearch\Exception\FormatterFailureException;
|
||||
use Xentral\Modules\SuperSearch\Exception\InvalidReturnTypeException;
|
||||
use Xentral\Modules\SuperSearch\Exception\SuperSearchExceptionInterface;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Collection\ItemFormatterCollection;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
|
||||
abstract class AbstractBulkIndexDatabaseProvider implements
|
||||
SearchIndexProviderInterface,
|
||||
BulkIndexProviderInterface,
|
||||
ItemIndexProviderInterface,
|
||||
DiffIndexProviderInterface
|
||||
{
|
||||
/** @var Database $db */
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* @param Database $database
|
||||
*/
|
||||
public function __construct(Database $database)
|
||||
{
|
||||
$this->db = $database;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SelectQuery $query
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract protected function configureBaseQuery(SelectQuery $query);
|
||||
|
||||
/**
|
||||
* @param SelectQuery $baseQuery
|
||||
* @param int|string $indexId
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract protected function configureItemQuery(SelectQuery $baseQuery, $indexId);
|
||||
|
||||
/**
|
||||
* @param SelectQuery $baseQuery
|
||||
* @param DateTimeInterface $since
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract protected function configureSinceQuery(SelectQuery $baseQuery, DateTimeInterface $since);
|
||||
|
||||
/**
|
||||
* @param SelectQuery $baseQuery
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract protected function configureCountQuery(SelectQuery $baseQuery);
|
||||
|
||||
/**
|
||||
* @return Closure
|
||||
*/
|
||||
abstract protected function getRowFormatter();
|
||||
|
||||
/**
|
||||
* @return int Anzahl der IndexItems die in einem Durchlauf geschrieben werden
|
||||
*/
|
||||
public function getBulkSize()
|
||||
{
|
||||
return 20000;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IndexIdentifier $identifier
|
||||
*
|
||||
* @throws InvalidReturnTypeException
|
||||
*
|
||||
* @return IndexItem|null
|
||||
*/
|
||||
public function getItem(IndexIdentifier $identifier)
|
||||
{
|
||||
$select = $this->db->select();
|
||||
$this->configureBaseQuery($select);
|
||||
$this->configureItemQuery($select, $identifier->getId());
|
||||
|
||||
$row = $this->db->fetchRow(
|
||||
$select->getStatement(),
|
||||
$select->getBindValues()
|
||||
);
|
||||
|
||||
if (empty($row)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// Formatter aufrufen
|
||||
$formatter = $this->getRowFormatter();
|
||||
$item = $formatter($row);
|
||||
} catch (SuperSearchExceptionInterface $exception) {
|
||||
throw new FormatterFailureException(
|
||||
sprintf('Formatter failed. Row data: %s', var_export($row, true)),
|
||||
$exception->getCode(),
|
||||
$exception
|
||||
);
|
||||
}
|
||||
|
||||
// Prüfen ob Formatter den richtigen Typ zurückliefert
|
||||
if (!$item instanceof IndexItem) {
|
||||
$itemType = gettype($item);
|
||||
if ($itemType === 'object') {
|
||||
$itemType = get_class($item);
|
||||
}
|
||||
throw new InvalidReturnTypeException(sprintf(
|
||||
'"%s::getRowFormatter()" returned invalid type. Required type "%s". Returned type "%s".',
|
||||
get_class($this),
|
||||
IndexItem::class,
|
||||
$itemType
|
||||
));
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getItemsSince(DateTimeInterface $since)
|
||||
{
|
||||
$select = $this->db->select();
|
||||
$this->configureBaseQuery($select);
|
||||
$this->configureSinceQuery($select, $since);
|
||||
|
||||
$callback = $this->getRowFormatter();
|
||||
$data = $this->db->fetchAll(
|
||||
$select->getStatement(),
|
||||
$select->getBindValues()
|
||||
);
|
||||
|
||||
return new ItemFormatterCollection($data, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getTotalCount()
|
||||
{
|
||||
$select = $this->db->select();
|
||||
$this->configureBaseQuery($select);
|
||||
$select->resetCols();
|
||||
$this->configureCountQuery($select);
|
||||
|
||||
return (int)$this->db->fetchValue(
|
||||
$select->getStatement(),
|
||||
$select->getBindValues()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
* @param int $count
|
||||
*
|
||||
* @throws InvalidReturnTypeException
|
||||
* @throws Exception
|
||||
*
|
||||
* @return ItemFormatterCollection
|
||||
*/
|
||||
public function getBulkItems($offset, $count)
|
||||
{
|
||||
$select = $this->db->select();
|
||||
$this->configureBaseQuery($select);
|
||||
|
||||
$select->offset($offset);
|
||||
$select->limit($count);
|
||||
|
||||
$callback = $this->getRowFormatter();
|
||||
$data = $this->db->fetchAll(
|
||||
$select->getStatement(),
|
||||
$select->getBindValues()
|
||||
);
|
||||
|
||||
return new ItemFormatterCollection($data, $callback);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Xentral\Components\Database\SqlQuery\SelectQuery;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexData;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
|
||||
final class AddressProvider extends AbstractBulkIndexDatabaseProvider
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getModuleName()
|
||||
{
|
||||
return 'adresse';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexName()
|
||||
{
|
||||
return 'addresses';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexTitle()
|
||||
{
|
||||
return 'Adressen';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureBaseQuery(SelectQuery $query)
|
||||
{
|
||||
$query
|
||||
->cols([
|
||||
'a.id',
|
||||
'a.projekt',
|
||||
'a.name',
|
||||
'a.abteilung',
|
||||
'a.unterabteilung',
|
||||
'a.ansprechpartner',
|
||||
'a.strasse',
|
||||
'a.ort',
|
||||
'a.plz',
|
||||
'a.adresszusatz',
|
||||
'a.telefon',
|
||||
'a.telefax',
|
||||
'a.mobil',
|
||||
'a.email',
|
||||
'a.ustid',
|
||||
'a.kundennummer',
|
||||
'a.lieferantennummer',
|
||||
'a.mitarbeiternummer',
|
||||
])
|
||||
->from('adresse AS a')
|
||||
->where('a.geloescht = ?', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureItemQuery(SelectQuery $baseQuery, $indexId)
|
||||
{
|
||||
$baseQuery->where('a.id = ?', (int)$indexId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureCountQuery(SelectQuery $baseQuery)
|
||||
{
|
||||
$baseQuery->cols(['COUNT(a.id)' => 'total_count']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureSinceQuery(SelectQuery $baseQuery, DateTimeInterface $since)
|
||||
{
|
||||
$baseQuery->where('a.logdatei > ?', $since->format('Y-m-d H:m:i'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getRowFormatter()
|
||||
{
|
||||
return static function (array $row) {
|
||||
|
||||
$projectId = (int)$row['projekt'];
|
||||
$title = $row['name'];
|
||||
$link = sprintf('index.php?module=adresse&action=edit&id=%d', $row['id']);
|
||||
$data = new IndexData($title, $link, $projectId);
|
||||
if (!empty($row['kundennummer'])) {
|
||||
$data->addAdditionalInfo(sprintf('Kunde %s', $row['kundennummer']));
|
||||
}
|
||||
if (!empty($row['lieferantennummer'])) {
|
||||
$data->addAdditionalInfo(sprintf('Lieferant %s', $row['lieferantennummer']));
|
||||
}
|
||||
if (!empty($row['mitarbeiternummer'])) {
|
||||
$data->addAdditionalInfo(sprintf('Mitarbeiter %s', $row['mitarbeiternummer']));
|
||||
}
|
||||
|
||||
$data->addSearchWord($row['name']);
|
||||
$data->addSearchWord($row['abteilung']);
|
||||
$data->addSearchWord($row['unterabteilung']);
|
||||
$data->addSearchWord($row['ansprechpartner']);
|
||||
$data->addSearchWord($row['strasse']);
|
||||
$data->addSearchWord($row['ort']);
|
||||
$data->addSearchWord($row['plz']);
|
||||
$data->addSearchWord($row['adresszusatz']);
|
||||
$data->addSearchWord($row['telefon']);
|
||||
$data->addSearchWord($row['telefax']);
|
||||
$data->addSearchWord($row['mobil']);
|
||||
$data->addSearchWord($row['email']);
|
||||
$data->addSearchWord($row['ustid']);
|
||||
$data->addSearchWord($row['kundennummer']);
|
||||
$data->addSearchWord($row['lieferantennummer']);
|
||||
$data->addSearchWord($row['mitarbeiternummer']);
|
||||
|
||||
$identifier = new IndexIdentifier('addresses', (int)$row['id']);
|
||||
|
||||
return new IndexItem($identifier, $data);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use Appstore;
|
||||
use Exception;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Collection\ItemFormatterCollection;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexData;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
|
||||
final class AppProvider implements FullIndexProviderInterface, ItemIndexProviderInterface
|
||||
{
|
||||
/** @var Appstore $appstore */
|
||||
private $appstore;
|
||||
|
||||
/**
|
||||
* @param Appstore $appstore
|
||||
*/
|
||||
public function __construct(Appstore $appstore)
|
||||
{
|
||||
$this->appstore = $appstore;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getModuleName()
|
||||
{
|
||||
return 'appstore';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexName()
|
||||
{
|
||||
return 'apps';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexTitle()
|
||||
{
|
||||
return 'Apps';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getItem(IndexIdentifier $identifier)
|
||||
{
|
||||
$moduleKey = $identifier->getId();
|
||||
$modules = $this->appstore->BuildModuleList();
|
||||
if (!isset($modules[$moduleKey])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$formatter = $this->getRowFormatter();
|
||||
|
||||
return $formatter($modules[$moduleKey]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getAllItems()
|
||||
{
|
||||
$callback = $this->getRowFormatter();
|
||||
|
||||
$modules = $this->appstore->BuildModuleList();
|
||||
unset($modules['appstore_extern']);
|
||||
|
||||
// Module ohne Link entfernen
|
||||
foreach ($modules as $moduleName => $moduleData) {
|
||||
if (empty($moduleData['module_link'])) {
|
||||
unset($modules[$moduleName]);
|
||||
}
|
||||
}
|
||||
|
||||
return new ItemFormatterCollection($modules, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getRowFormatter()
|
||||
{
|
||||
return static function (array $module) {
|
||||
$projectId = 0;
|
||||
$data = new IndexData($module['title'], $module['module_link'], $projectId);
|
||||
$data->addSearchWord($module['title']);
|
||||
$data->addSearchWord(html_entity_decode($module['title']));
|
||||
$data->addSearchWord($module['description']);
|
||||
$data->addSearchWord($module['category']);
|
||||
$identifier = new IndexIdentifier('apps', $module['key']);
|
||||
|
||||
return new IndexItem($identifier, $data);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Xentral\Components\Database\SqlQuery\SelectQuery;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexData;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
|
||||
final class ArticleProvider extends AbstractBulkIndexDatabaseProvider
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getModuleName()
|
||||
{
|
||||
return 'artikel';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexName()
|
||||
{
|
||||
return 'articles';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexTitle()
|
||||
{
|
||||
return 'Artikel';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureBaseQuery(SelectQuery $query)
|
||||
{
|
||||
$query
|
||||
->cols([
|
||||
'a.id',
|
||||
'a.projekt',
|
||||
'a.nummer',
|
||||
'a.name_de',
|
||||
'a.kurztext_de',
|
||||
'a.herstellernummer',
|
||||
'a.ean',
|
||||
])
|
||||
->from('artikel AS a')
|
||||
->where('a.geloescht = ?', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureItemQuery(SelectQuery $baseQuery, $indexId)
|
||||
{
|
||||
$baseQuery->where('a.id = ?', (int)$indexId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureCountQuery(SelectQuery $baseQuery)
|
||||
{
|
||||
$baseQuery->cols(['COUNT(a.id)' => 'total_count']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureSinceQuery(SelectQuery $baseQuery, DateTimeInterface $since)
|
||||
{
|
||||
$baseQuery->where('a.logdatei > ?', $since->format('Y-m-d H:m:i'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getRowFormatter()
|
||||
{
|
||||
return static function (array $row) {
|
||||
|
||||
$projectId = (int)$row['projekt'];
|
||||
$link = sprintf('index.php?module=artikel&action=edit&id=%d', $row['id']);
|
||||
|
||||
$data = new IndexData($row['nummer'], $link, $projectId);
|
||||
$data->setSubTitle($row['name_de']);
|
||||
$data->addSearchWord($row['nummer']);
|
||||
$data->addSearchWord($row['name_de']);
|
||||
$data->addSearchWord($row['kurztext_de']);
|
||||
$data->addSearchWord($row['herstellernummer']);
|
||||
$data->addSearchWord($row['ean']);
|
||||
|
||||
$identifier = new IndexIdentifier('articles', (int)$row['id']);
|
||||
|
||||
return new IndexItem($identifier, $data);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Collection\ItemFormatterCollection;
|
||||
|
||||
interface BulkIndexProviderInterface extends SearchIndexProviderInterface
|
||||
{
|
||||
/**
|
||||
* Returns a range of the index items
|
||||
*
|
||||
* @param int $start
|
||||
* @param int $limit
|
||||
*
|
||||
* @return ItemFormatterCollection
|
||||
*/
|
||||
public function getBulkItems($start, $limit);
|
||||
|
||||
/**
|
||||
* Returns the number of items to process in one transaction
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getBulkSize();
|
||||
|
||||
/**
|
||||
* Returns the total count for all items
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTotalCount();
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Xentral\Components\Database\SqlQuery\SelectQuery;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexData;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
|
||||
final class CreditNoteProvider extends AbstractBulkIndexDatabaseProvider
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getModuleName()
|
||||
{
|
||||
return 'gutschrift';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexName()
|
||||
{
|
||||
return 'creditnotes';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexTitle()
|
||||
{
|
||||
return 'Gutschriften';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureBaseQuery(SelectQuery $query)
|
||||
{
|
||||
$query
|
||||
->cols([
|
||||
'gs.id',
|
||||
'gs.projekt',
|
||||
'gs.status',
|
||||
'gs.datum',
|
||||
'gs.belegnr',
|
||||
'gs.rechnung',
|
||||
'gs.name',
|
||||
'gs.kundennummer',
|
||||
'gs.internebemerkung',
|
||||
'gs.ihrebestellnummer',
|
||||
'gs.soll',
|
||||
'gs.zahlungsstatus',
|
||||
'gs.waehrung',
|
||||
])
|
||||
->from('gutschrift AS gs')
|
||||
->where('gs.belegnr != ?', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureItemQuery(SelectQuery $baseQuery, $indexId)
|
||||
{
|
||||
$baseQuery->where('gs.id = ?', (int)$indexId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureCountQuery(SelectQuery $baseQuery)
|
||||
{
|
||||
$baseQuery->cols(['COUNT(gs.id)' => 'total_count']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureSinceQuery(SelectQuery $baseQuery, DateTimeInterface $since)
|
||||
{
|
||||
$baseQuery->where('gs.logdatei > ?', $since->format('Y-m-d H:m:i'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getRowFormatter()
|
||||
{
|
||||
return static function (array $row) {
|
||||
|
||||
$projectId = (int)$row['projekt'];
|
||||
$rechnungsDatum = date('d.m.Y', strtotime($row['datum']));
|
||||
$title = $row['belegnr'];
|
||||
$link = sprintf('index.php?module=gutschrift&action=edit&id=%d', $row['id']);
|
||||
|
||||
$data = new IndexData($title, $link, $projectId);
|
||||
$data->setSubTitle($row['name']);
|
||||
$data->addAdditionalInfo($rechnungsDatum);
|
||||
$data->addAdditionalInfo(ucfirst($row['status']));
|
||||
$data->addAdditionalInfo(sprintf('%s %s', number_format($row['soll'], 2, ',', '.'), $row['waehrung']));
|
||||
|
||||
$data->addSearchWord('gutschrift');
|
||||
$data->addSearchWord($row['belegnr']);
|
||||
$data->addSearchWord($row['rechnung']);
|
||||
$data->addSearchWord($row['status']);
|
||||
$data->addSearchWord($row['name']);
|
||||
$data->addSearchWord($row['kundennummer']);
|
||||
$data->addSearchWord($row['internebemerkung']);
|
||||
$data->addSearchWord($row['ihrebestellnummer']);
|
||||
|
||||
$identifier = new IndexIdentifier('creditnotes', (int)$row['id']);
|
||||
|
||||
return new IndexItem($identifier, $data);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Xentral\Components\Database\SqlQuery\SelectQuery;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexData;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
|
||||
final class DeliveryNoteProvider extends AbstractBulkIndexDatabaseProvider
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getModuleName()
|
||||
{
|
||||
return 'lieferschein';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexName()
|
||||
{
|
||||
return 'deliverynote';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexTitle()
|
||||
{
|
||||
return 'Lieferscheine';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureBaseQuery(SelectQuery $query)
|
||||
{
|
||||
$query
|
||||
->cols([
|
||||
'l.id',
|
||||
'l.projekt',
|
||||
'l.datum',
|
||||
'l.belegnr',
|
||||
'l.status',
|
||||
'l.name',
|
||||
'l.kundennummer',
|
||||
'l.internebezeichnung'
|
||||
])
|
||||
->from('lieferschein AS l')
|
||||
->where('l.belegnr != ?', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureItemQuery(SelectQuery $baseQuery, $indexId)
|
||||
{
|
||||
$baseQuery->where('l.id = ?', (int)$indexId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureCountQuery(SelectQuery $baseQuery)
|
||||
{
|
||||
$baseQuery->cols(['COUNT(l.id)' => 'total_count']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureSinceQuery(SelectQuery $baseQuery, DateTimeInterface $since)
|
||||
{
|
||||
$baseQuery->where('l.logdatei > ?', $since->format('Y-m-d H:m:i'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getRowFormatter()
|
||||
{
|
||||
return static function (array $row) {
|
||||
|
||||
$projectId = (int)$row['projekt'];
|
||||
$lieferscheinDatum = date('d.m.Y', strtotime($row['datum']));
|
||||
$title = $row['belegnr'];
|
||||
$link = sprintf('index.php?module=lieferschein&action=edit&id=%d', $row['id']);
|
||||
|
||||
$data = new IndexData($title, $link, $projectId);
|
||||
$data->addSearchWord('lieferschein');
|
||||
$data->addSearchWord($row['belegnr']);
|
||||
$data->addSearchWord($row['name']);
|
||||
$data->addSearchWord($row['kundennummer']);
|
||||
$data->addSearchWord($row['internebezeichnung']);
|
||||
|
||||
$data->setSubTitle($row['name']);
|
||||
|
||||
$data->addAdditionalInfo($lieferscheinDatum);
|
||||
$data->addAdditionalInfo($row['status']);
|
||||
|
||||
|
||||
$identifier = new IndexIdentifier('deliverynote', (int)$row['id']);
|
||||
|
||||
return new IndexItem($identifier, $data);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Collection\ItemFormatterCollection;
|
||||
|
||||
interface DiffIndexProviderInterface extends SearchIndexProviderInterface
|
||||
{
|
||||
/**
|
||||
* Returns index items that were changed or created since the passed date time
|
||||
*
|
||||
* @param DateTimeInterface $since
|
||||
*
|
||||
* @return ItemFormatterCollection
|
||||
*/
|
||||
public function getItemsSince(DateTimeInterface $since);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Collection\ItemFormatterCollection;
|
||||
|
||||
interface FullIndexProviderInterface extends SearchIndexProviderInterface
|
||||
{
|
||||
/**
|
||||
* Returns all items; No sectioning, just all items
|
||||
*
|
||||
* Use BulkIndexProviderInterface for large datasets instead
|
||||
*
|
||||
* @return ItemFormatterCollection
|
||||
*/
|
||||
public function getAllItems();
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Xentral\Components\Database\SqlQuery\SelectQuery;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexData;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
|
||||
final class InvoiceProvider extends AbstractBulkIndexDatabaseProvider
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getModuleName()
|
||||
{
|
||||
return 'rechnung';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexName()
|
||||
{
|
||||
return 'invoices';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexTitle()
|
||||
{
|
||||
return 'Rechnungen';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureBaseQuery(SelectQuery $query)
|
||||
{
|
||||
$query
|
||||
->cols([
|
||||
'r.id',
|
||||
'r.projekt',
|
||||
'r.datum',
|
||||
'r.belegnr',
|
||||
'r.auftrag',
|
||||
'r.name',
|
||||
'r.kundennummer',
|
||||
'r.internebemerkung',
|
||||
'r.ihrebestellnummer',
|
||||
'r.soll',
|
||||
'r.zahlungsstatus',
|
||||
'r.waehrung',
|
||||
])
|
||||
->from('rechnung AS r')
|
||||
->where('r.belegnr != ?', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureItemQuery(SelectQuery $baseQuery, $indexId)
|
||||
{
|
||||
$baseQuery->where('r.id = ?', (int)$indexId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureCountQuery(SelectQuery $baseQuery)
|
||||
{
|
||||
$baseQuery->cols(['COUNT(r.id)' => 'total_count']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureSinceQuery(SelectQuery $baseQuery, DateTimeInterface $since)
|
||||
{
|
||||
$baseQuery->where('r.logdatei > ?', $since->format('Y-m-d H:m:i'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getRowFormatter()
|
||||
{
|
||||
return static function (array $row) {
|
||||
|
||||
$projectId = (int)$row['projekt'];
|
||||
$rechnungsDatum = date('d.m.Y', strtotime($row['datum']));
|
||||
$title = $row['belegnr'];
|
||||
$link = sprintf('index.php?module=rechnung&action=edit&id=%d', $row['id']);
|
||||
|
||||
$data = new IndexData($title, $link, $projectId);
|
||||
$data->setSubTitle($row['name']);
|
||||
$data->addAdditionalInfo($rechnungsDatum);
|
||||
$data->addAdditionalInfo(ucfirst($row['zahlungsstatus']));
|
||||
$data->addAdditionalInfo(sprintf('%s %s', number_format($row['soll'], 2, ',', '.'), $row['waehrung']));
|
||||
|
||||
$data->addSearchWord('rechnung');
|
||||
$data->addSearchWord($row['belegnr']);
|
||||
$data->addSearchWord($row['auftrag']);
|
||||
$data->addSearchWord($row['name']);
|
||||
$data->addSearchWord($row['kundennummer']);
|
||||
$data->addSearchWord($row['internebemerkung']);
|
||||
$data->addSearchWord($row['ihrebestellnummer']);
|
||||
|
||||
$identifier = new IndexIdentifier('invoices', (int)$row['id']);
|
||||
|
||||
return new IndexItem($identifier, $data);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
|
||||
interface ItemIndexProviderInterface extends SearchIndexProviderInterface
|
||||
{
|
||||
/**
|
||||
* Returns a single item for writing into the search index
|
||||
*
|
||||
* @param IndexIdentifier $identifier
|
||||
*
|
||||
* @return IndexItem|null
|
||||
*/
|
||||
public function getItem(IndexIdentifier $identifier);
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Xentral\Components\Database\SqlQuery\SelectQuery;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexData;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
|
||||
final class OfferProvider extends AbstractBulkIndexDatabaseProvider
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getModuleName()
|
||||
{
|
||||
return 'angebot';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexName()
|
||||
{
|
||||
return 'offers';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexTitle()
|
||||
{
|
||||
return 'Angebote';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureBaseQuery(SelectQuery $query)
|
||||
{
|
||||
$query
|
||||
->cols([
|
||||
'a.id',
|
||||
'a.projekt',
|
||||
'a.datum',
|
||||
'a.belegnr',
|
||||
'a.auftrag', // Auftragsnummer
|
||||
'a.status',
|
||||
'a.name',
|
||||
'a.kundennummer',
|
||||
'a.internebezeichnung',
|
||||
'a.anfrage',
|
||||
'a.gesamtsumme',
|
||||
'a.waehrung',
|
||||
])
|
||||
->from('angebot AS a')
|
||||
->where('a.belegnr != ?', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureItemQuery(SelectQuery $baseQuery, $indexId)
|
||||
{
|
||||
$baseQuery->where('a.id = ?', (int)$indexId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureCountQuery(SelectQuery $baseQuery)
|
||||
{
|
||||
$baseQuery->cols(['COUNT(a.id)' => 'total_count']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureSinceQuery(SelectQuery $baseQuery, DateTimeInterface $since)
|
||||
{
|
||||
$baseQuery->where('a.logdatei > ?', $since->format('Y-m-d H:m:i'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getRowFormatter()
|
||||
{
|
||||
return static function (array $row) {
|
||||
|
||||
$projectId = (int)$row['projekt'];
|
||||
$documentDate = date('d.m.Y', strtotime($row['datum']));
|
||||
$title = $row['belegnr'];
|
||||
$link = sprintf('index.php?module=angebot&action=edit&id=%d', $row['id']);
|
||||
|
||||
$data = new IndexData($title, $link, $projectId);
|
||||
$data->setSubTitle($row['name']);
|
||||
$data->addAdditionalInfo($documentDate);
|
||||
$data->addAdditionalInfo(ucfirst($row['status']));
|
||||
$data->addAdditionalInfo(number_format($row['gesamtsumme'], 2, ',', '.') . ' ' . $row['waehrung']);
|
||||
$data->addSearchWord('angebot');
|
||||
$data->addSearchWord($row['belegnr']);
|
||||
$data->addSearchWord($row['auftrag']);
|
||||
$data->addSearchWord($row['name']);
|
||||
$data->addSearchWord($row['kundennummer']);
|
||||
$data->addSearchWord($row['internebezeichnung']);
|
||||
$data->addSearchWord($row['anfrage']);
|
||||
|
||||
$identifier = new IndexIdentifier('offers', (int)$row['id']);
|
||||
|
||||
return new IndexItem($identifier, $data);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Xentral\Components\Database\SqlQuery\SelectQuery;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexData;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
|
||||
final class OrderProvider extends AbstractBulkIndexDatabaseProvider
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getModuleName()
|
||||
{
|
||||
return 'auftrag';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexName()
|
||||
{
|
||||
return 'orders';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexTitle()
|
||||
{
|
||||
return 'Aufträge';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureBaseQuery(SelectQuery $query)
|
||||
{
|
||||
$query
|
||||
->cols([
|
||||
'a.id',
|
||||
'a.projekt',
|
||||
'a.datum',
|
||||
'a.belegnr',
|
||||
'a.internet',
|
||||
'a.angebot', // Angebotsnummer
|
||||
'a.status',
|
||||
'a.name',
|
||||
'a.kundennummer',
|
||||
'a.internebezeichnung',
|
||||
'a.ihrebestellnummer',
|
||||
'a.gesamtsumme',
|
||||
'a.waehrung',
|
||||
])
|
||||
->from('auftrag AS a')
|
||||
->where('a.belegnr != ?', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureItemQuery(SelectQuery $baseQuery, $indexId)
|
||||
{
|
||||
$baseQuery->where('a.id = ?', (int)$indexId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureCountQuery(SelectQuery $baseQuery)
|
||||
{
|
||||
$baseQuery->cols(['COUNT(a.id)' => 'total_count']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureSinceQuery(SelectQuery $baseQuery, DateTimeInterface $since)
|
||||
{
|
||||
$baseQuery->where('a.logdatei > ?', $since->format('Y-m-d H:m:i'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getRowFormatter()
|
||||
{
|
||||
return static function (array $row) {
|
||||
|
||||
$projectId = (int)$row['projekt'];
|
||||
$documentDate = date('d.m.Y', strtotime($row['datum']));
|
||||
$title = $row['belegnr'];
|
||||
$link = sprintf('index.php?module=auftrag&action=edit&id=%d', $row['id']);
|
||||
|
||||
$data = new IndexData($title, $link, $projectId);
|
||||
$data->setSubTitle($row['name']);
|
||||
$data->addAdditionalInfo($documentDate);
|
||||
$data->addAdditionalInfo(ucfirst($row['status']));
|
||||
$data->addAdditionalInfo(number_format($row['gesamtsumme'], 2, ',', '.') . ' ' . $row['waehrung']);
|
||||
$data->addSearchWord('auftrag');
|
||||
$data->addSearchWord($row['belegnr']);
|
||||
$data->addSearchWord($row['internet']);
|
||||
$data->addSearchWord($row['angebot']);
|
||||
$data->addSearchWord($row['name']);
|
||||
$data->addSearchWord($row['kundennummer']);
|
||||
$data->addSearchWord($row['internebezeichnung']);
|
||||
$data->addSearchWord($row['ihrebestellnummer']);
|
||||
|
||||
$identifier = new IndexIdentifier('orders', (int)$row['id']);
|
||||
|
||||
return new IndexItem($identifier, $data);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
interface SearchIndexProviderInterface
|
||||
{
|
||||
/**
|
||||
* @return string Nur Kleinbuchstaben erlaubt
|
||||
*/
|
||||
public function getIndexName();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIndexTitle();
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getModuleName();
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SearchIndex\Provider;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Xentral\Components\Database\SqlQuery\SelectQuery;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexData;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
|
||||
final class TrackingNumberProvider extends AbstractBulkIndexDatabaseProvider
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getModuleName()
|
||||
{
|
||||
return 'lieferschein';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexName()
|
||||
{
|
||||
return 'trackingnumber';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIndexTitle()
|
||||
{
|
||||
return 'Trackingnummer';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureBaseQuery(SelectQuery $query)
|
||||
{
|
||||
$query
|
||||
->cols([
|
||||
'v.id',
|
||||
'v.tracking',
|
||||
'v.lieferschein',
|
||||
'v.projekt',
|
||||
'v.versendet_am'
|
||||
])
|
||||
->from('versand AS v')
|
||||
->where('v.tracking != ?', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureItemQuery(SelectQuery $baseQuery, $indexId)
|
||||
{
|
||||
$baseQuery->where('v.id = ?', (int)$indexId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureCountQuery(SelectQuery $baseQuery)
|
||||
{
|
||||
$baseQuery->cols(['COUNT(v.id)' => 'total_count']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function configureSinceQuery(SelectQuery $baseQuery, DateTimeInterface $since)
|
||||
{
|
||||
$baseQuery->where('v.versendet_am > ?', $since->format('Y-m-d H:m:i'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getRowFormatter()
|
||||
{
|
||||
return static function (array $row) {
|
||||
|
||||
$projectId = (int)$row['projekt'];
|
||||
$versandDatum = date('d.m.Y', strtotime($row['versendet_am']));
|
||||
$title = $row['tracking'];
|
||||
$link = sprintf('index.php?module=lieferschein&action=edit&id=%d', $row['lieferschein']);
|
||||
|
||||
$data = new IndexData($title, $link, $projectId);
|
||||
$data->addSearchWord('trackingnummer');
|
||||
$data->addSearchWord($row['tracking']);
|
||||
|
||||
$data->setSubTitle('');
|
||||
|
||||
$data->addAdditionalInfo('Versendet: '.$versandDatum);
|
||||
|
||||
$identifier = new IndexIdentifier('trackingnumber', (int)$row['id']);
|
||||
|
||||
return new IndexItem($identifier, $data);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use Exception;
|
||||
use Xentral\Components\Database\Database;
|
||||
use Xentral\Modules\SuperSearch\Exception\InvalidArgumentException;
|
||||
use Xentral\Modules\SuperSearch\SearchEngine\SearchTermParser;
|
||||
use Xentral\Widgets\SuperSearch\Result\ResultCollection;
|
||||
use Xentral\Widgets\SuperSearch\Result\ResultGroup;
|
||||
use Xentral\Widgets\SuperSearch\Result\ResultItem;
|
||||
|
||||
final class SuperSearchEngine
|
||||
{
|
||||
/** @var Database $db */
|
||||
private $db;
|
||||
|
||||
/** @var SearchTermParser $searchTermParser */
|
||||
private $searchTermParser;
|
||||
|
||||
/**
|
||||
* @param Database $database
|
||||
*/
|
||||
public function __construct(Database $database)
|
||||
{
|
||||
$this->searchTermParser = new SearchTermParser();
|
||||
$this->db = $database;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $searchTerm
|
||||
* @param array|null $projectIds Projekt-IDs die der Benutzer aufrufen darf;
|
||||
* null = Keine Einschränkung (nur bei Admins)
|
||||
* @param array|null $moduleNames Module die der Benutzer aufrufen darf;
|
||||
* null = Keine Einschränkung (nur bei Admins)
|
||||
* @param int $resultLimit Anzahl der Ergebnisse
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return ResultCollection
|
||||
*/
|
||||
public function search($searchTerm, array $projectIds = null, array $moduleNames = null, $resultLimit = 30)
|
||||
{
|
||||
$resultLimit = (int)$resultLimit;
|
||||
if ($resultLimit < 1) {
|
||||
throw new InvalidArgumentException('Parameter value $resultLimit is invalid.');
|
||||
}
|
||||
|
||||
$searchTerm = $this->searchTermParser->parse($searchTerm);
|
||||
|
||||
// Ergebnisse mit Projekt-ID 0 immer anzeigen (z.b. Appstore-Ergebnisse)
|
||||
if (is_array($projectIds) && !in_array(0, $projectIds, true)) {
|
||||
$projectIds[] = 0;
|
||||
}
|
||||
if (is_array($moduleNames) && !in_array('appstore', $moduleNames, true)) {
|
||||
$moduleNames[] = 'appstore';
|
||||
}
|
||||
|
||||
$sqlProjects = '';
|
||||
$sqlModules = '';
|
||||
$bindValues = [
|
||||
'search_term' => $searchTerm,
|
||||
'result_limit' => $resultLimit,
|
||||
];
|
||||
if ($projectIds !== null) {
|
||||
$sqlProjects = ' AND sii.project_id IN (:project_ids) ';
|
||||
$bindValues['project_ids'] = (array)$projectIds;
|
||||
}
|
||||
if ($moduleNames !== null) {
|
||||
$sqlModules = ' AND (sig.module IN (:module_names) OR sig.module IS NULL) ';
|
||||
$bindValues['module_names'] = (array)$moduleNames;
|
||||
}
|
||||
|
||||
$sql =
|
||||
"SELECT
|
||||
sii.index_name, sii.index_id, sig.title AS `index_title`, sii.project_id,
|
||||
sii.title, sii.subtitle, sii.additional_infos, sii.link, sii.search_words
|
||||
FROM `supersearch_index_item` AS `sii`
|
||||
INNER JOIN `supersearch_index_group` AS `sig` ON sii.index_name = sig.name
|
||||
WHERE MATCH (sii.search_words) AGAINST (:search_term IN BOOLEAN MODE)
|
||||
{$sqlProjects}
|
||||
{$sqlModules}
|
||||
AND sii.outdated = 0 AND sig.active = 1
|
||||
LIMIT 0, :result_limit";
|
||||
$data = $this->db->fetchAll($sql, $bindValues);
|
||||
|
||||
return $this->buildResultCollection($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return ResultCollection
|
||||
*/
|
||||
private function buildResultCollection($data)
|
||||
{
|
||||
$lastIndexUpdate = $this->getRecentIndexTime();
|
||||
$results = new ResultCollection([], $lastIndexUpdate);
|
||||
|
||||
foreach ($data as $item) {
|
||||
if (!$results->hasGroup($item['index_name'])) {
|
||||
$results->addGroup(new ResultGroup($item['index_name'], $item['index_title']));
|
||||
}
|
||||
/** @var ResultGroup $group */
|
||||
$group = $results->getGroup($item['index_name']);
|
||||
$group->addItem(ResultItem::fromDbState($item));
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Liefert den Zeitpunkt wann der Index das letzte Mal aktualisiert wurde
|
||||
*
|
||||
* @return DateTimeInterface|null
|
||||
*/
|
||||
private function getRecentIndexTime()
|
||||
{
|
||||
$sql =
|
||||
'SELECT MAX(GREATEST(IFNULL(sig.last_full_update, 1), IFNULL(sig.last_diff_update, 1))) AS `last_update`
|
||||
FROM `supersearch_index_group` AS sig WHERE sig.active = 1';
|
||||
$value = $this->db->fetchValue($sql);
|
||||
|
||||
if (empty($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
$dateTime = new DateTimeImmutable($value);
|
||||
} catch (Exception $exception) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $dateTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,487 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use Exception;
|
||||
use Xentral\Components\Database\Database;
|
||||
use Xentral\Components\Database\Exception\DatabaseExceptionInterface;
|
||||
use Xentral\Modules\SuperSearch\Exception\InvalidReturnValueException;
|
||||
use Xentral\Modules\SuperSearch\Exception\ProviderIncompatibleException;
|
||||
use Xentral\Modules\SuperSearch\Exception\ProviderMissingException;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexIdentifier;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Data\IndexItem;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\BulkIndexProviderInterface;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\DiffIndexProviderInterface;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\FullIndexProviderInterface;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\ItemIndexProviderInterface;
|
||||
use Xentral\Modules\SuperSearch\SearchIndex\Provider\SearchIndexProviderInterface;
|
||||
|
||||
final class SuperSearchIndexer
|
||||
{
|
||||
/** @var Database $db */
|
||||
private $db;
|
||||
|
||||
/** @var array|SearchIndexProviderInterface[] $provider */
|
||||
private $provider;
|
||||
|
||||
/**
|
||||
* @param Database $database
|
||||
* @param SearchIndexProviderInterface[]|array $provider Nur aktive Provider übergeben!
|
||||
*/
|
||||
public function __construct(Database $database, array $provider = [])
|
||||
{
|
||||
$this->db = $database;
|
||||
$this->provider = $provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt Meta-Information zu den Providern zurück; nur von aktiven Providern
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getProviderMetaData()
|
||||
{
|
||||
$meta = [];
|
||||
foreach ($this->provider as $provider) {
|
||||
$meta[] = [
|
||||
'name' => $provider->getIndexName(),
|
||||
'title' => $provider->getIndexTitle(),
|
||||
'module' => $provider->getModuleName(),
|
||||
];
|
||||
}
|
||||
|
||||
return $meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tatsächliche Index-Größe ermitteln (gruppiert nach Index) (nur von aktiven Providern)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getProviderIndexSizesCurrent()
|
||||
{
|
||||
$sql =
|
||||
'SELECT sig.name, COUNT(sii.id) AS `index_size`
|
||||
FROM `supersearch_index_group` AS `sig`
|
||||
LEFT JOIN `supersearch_index_item` AS `sii` ON sig.name = sii.index_name AND sii.outdated = 0
|
||||
WHERE sig.active = 1
|
||||
GROUP BY sig.name';
|
||||
$indexSizes = $this->db->fetchPairs($sql);
|
||||
|
||||
// Fehlende Indexe ergänzen, falls Provider registriert ist aber noch nie gelaufen ist
|
||||
foreach ($this->provider as $provider) {
|
||||
$indexName = $provider->getIndexName();
|
||||
if (!isset($indexSizes[$indexName])) {
|
||||
$indexSizes[$indexName] = null;
|
||||
}
|
||||
}
|
||||
ksort($indexSizes);
|
||||
|
||||
return $indexSizes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Potentielle Index-Größe ermitteln (gruppiert nach Index) (nur von aktiven Providern)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getProviderIndexSizesPotential()
|
||||
{
|
||||
$indexSizes = [];
|
||||
foreach ($this->provider as $provider) {
|
||||
|
||||
// Möglich Index-Größe beim Provider erfragen
|
||||
$indexSizePotential = null;
|
||||
if ($provider instanceof BulkIndexProviderInterface) {
|
||||
$indexSizePotential = $provider->getTotalCount();
|
||||
}
|
||||
|
||||
$indexSizes[$provider->getIndexName()] = $indexSizePotential;
|
||||
}
|
||||
ksort($indexSizes);
|
||||
|
||||
return $indexSizes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name Index-Name
|
||||
*
|
||||
* @throws ProviderMissingException
|
||||
* @throws InvalidReturnValueException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function updateIndexFull($name)
|
||||
{
|
||||
/** @var FullIndexProviderInterface $provider */
|
||||
$provider = $this->tryGetProviderByIndexName($name);
|
||||
if ($provider === null) {
|
||||
throw new ProviderMissingException(sprintf('Provider for index "%s" is missing', $name));
|
||||
}
|
||||
|
||||
if ($provider instanceof BulkIndexProviderInterface) {
|
||||
|
||||
/** @var BulkIndexProviderInterface $provider */
|
||||
$totalCount = $provider->getTotalCount();
|
||||
if ($totalCount < 0) {
|
||||
throw new InvalidReturnValueException(sprintf(
|
||||
'Method %s::getTotalCount() returned an invalid value "%s". Total count must be a positive number.',
|
||||
get_class($provider),
|
||||
$totalCount
|
||||
));
|
||||
}
|
||||
|
||||
$itemsPerStep = $provider->getBulkSize();
|
||||
$currentOffset = 0;
|
||||
|
||||
// Alle Index-Einträge als "veraltet" markieren
|
||||
$this->markIndexAsOutdated($name);
|
||||
|
||||
do {
|
||||
$items = $provider->getBulkItems($currentOffset, $itemsPerStep);
|
||||
|
||||
$this->db->beginTransaction();
|
||||
foreach ($items as $item) {
|
||||
$this->saveItem($item);
|
||||
}
|
||||
unset($items);
|
||||
$this->db->commit();
|
||||
|
||||
$currentOffset += $itemsPerStep;
|
||||
|
||||
} while ($currentOffset < $totalCount);
|
||||
|
||||
// Full-Update-Zeitpunkt aktualisieren
|
||||
$this->updateLastFullUpdateTime($name);
|
||||
// Diff-Update-Zeitpunkt ebenfalls aktualisieren > Nächstes Diff-Update dann ab diesem Zeitpunkt
|
||||
$this->updateLastDiffUpdateTime($name);
|
||||
// Als "veraltet" markierte Index-Einträge löschen
|
||||
$this->deleteOutdatedIndexItems($name);
|
||||
}
|
||||
|
||||
if (
|
||||
$provider instanceof FullIndexProviderInterface &&
|
||||
!$provider instanceof BulkIndexProviderInterface
|
||||
) {
|
||||
$this->markIndexAsOutdated($name);
|
||||
|
||||
$items = $provider->getAllItems();
|
||||
$this->db->beginTransaction();
|
||||
foreach ($items as $item) {
|
||||
$this->saveItem($item);
|
||||
}
|
||||
$this->db->commit();
|
||||
|
||||
$this->updateLastFullUpdateTime($name);
|
||||
$this->deleteOutdatedIndexItems($name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name Index-Name
|
||||
* @param DateTimeInterface $since
|
||||
*
|
||||
* @throws ProviderMissingException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function updateIndexSince($name, DateTimeInterface $since)
|
||||
{
|
||||
/** @var DiffIndexProviderInterface $provider */
|
||||
$provider = $this->tryGetProviderByIndexName($name);
|
||||
if ($provider === null) {
|
||||
throw new ProviderMissingException(sprintf('Provider for index "%s" is missing', $name));
|
||||
}
|
||||
|
||||
if (!$provider instanceof DiffIndexProviderInterface) {
|
||||
return;
|
||||
}
|
||||
|
||||
$items = $provider->getItemsSince($since);
|
||||
$this->db->beginTransaction();
|
||||
foreach ($items as $item) {
|
||||
$this->saveItem($item);
|
||||
}
|
||||
$this->db->commit();
|
||||
|
||||
$this->updateLastDiffUpdateTime($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return DateTimeInterface|null
|
||||
*/
|
||||
public function getLastFullIndexTime($name)
|
||||
{
|
||||
$dateString = $this->db->fetchValue(
|
||||
'SELECT sig.last_full_update FROM `supersearch_index_group` AS `sig` WHERE sig.name = :index_name',
|
||||
['index_name' => (string)$name]
|
||||
);
|
||||
|
||||
try {
|
||||
if (!empty($dateString)) {
|
||||
return new DateTimeImmutable($dateString);
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
// nope - return null
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return DateTimeInterface|null
|
||||
*/
|
||||
public function getLastDiffIndexTime($name)
|
||||
{
|
||||
$dateString = $this->db->fetchValue(
|
||||
'SELECT sig.last_diff_update FROM `supersearch_index_group` AS `sig` WHERE sig.name = :index_name',
|
||||
['index_name' => (string)$name]
|
||||
);
|
||||
|
||||
try {
|
||||
if (!empty($dateString)) {
|
||||
return new DateTimeImmutable($dateString);
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
// nope - return null
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IndexIdentifier $identifier
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteIndexItem(IndexIdentifier $identifier)
|
||||
{
|
||||
$sql =
|
||||
'DELETE FROM `supersearch_index_item`
|
||||
WHERE `index_name` = :index_name AND `index_id` = :index_id
|
||||
LIMIT 1';
|
||||
$bindValues = [
|
||||
'index_name' => $identifier->getName(),
|
||||
'index_id' => $identifier->getId(),
|
||||
];
|
||||
|
||||
$this->db->perform($sql, $bindValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IndexIdentifier $identifier
|
||||
*
|
||||
* @throws ProviderMissingException
|
||||
* @throws ProviderIncompatibleException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function updateIndexItem(IndexIdentifier $identifier)
|
||||
{
|
||||
/** @var ItemIndexProviderInterface $provider */
|
||||
$provider = $this->tryGetProviderByIndexName($identifier->getName());
|
||||
if ($provider === null) {
|
||||
throw new ProviderMissingException(sprintf(
|
||||
'Provider for index "%s" is missing.', $identifier->getName()
|
||||
));
|
||||
}
|
||||
|
||||
if (!$provider instanceof ItemIndexProviderInterface) {
|
||||
throw new ProviderIncompatibleException(sprintf(
|
||||
'Provider for index "%s" is incompatible. Provider %s does not implement %s.',
|
||||
$identifier->getName(),
|
||||
get_class($provider),
|
||||
ItemIndexProviderInterface::class
|
||||
));
|
||||
}
|
||||
|
||||
$item = $provider->getItem($identifier);
|
||||
if ($item === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->saveItem($item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates or creates an index item
|
||||
*
|
||||
* @param IndexItem $item
|
||||
*
|
||||
* @throws ProviderMissingException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function saveItem(IndexItem $item)
|
||||
{
|
||||
$existingItemId = (int)$this->db->fetchValue(
|
||||
'SELECT sii.id
|
||||
FROM `supersearch_index_item` AS `sii`
|
||||
WHERE sii.index_name = :index_name AND sii.index_id = :index_id',
|
||||
[
|
||||
'index_name' => $item->identifier->getName(),
|
||||
'index_id' => $item->identifier->getId(),
|
||||
]
|
||||
);
|
||||
|
||||
if ($existingItemId > 0) {
|
||||
$this->updateItem($item);
|
||||
} else {
|
||||
$this->createItem($item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IndexItem $item
|
||||
*
|
||||
* @throws DatabaseExceptionInterface
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function updateItem(IndexItem $item)
|
||||
{
|
||||
$searchWords = '';
|
||||
if (!empty($item->data->getWords())) {
|
||||
$searchWords = implode(' | ', $item->data->getWords());
|
||||
}
|
||||
$additionalInfos = null;
|
||||
if (!empty($item->data->getAdditionalInfos())) {
|
||||
$additionalInfos = implode(' ## ', $item->data->getAdditionalInfos());
|
||||
}
|
||||
|
||||
$sql =
|
||||
'UPDATE `supersearch_index_item`
|
||||
SET
|
||||
`project_id` = :project_id,
|
||||
`title` = :title,
|
||||
`subtitle` = :subtitle,
|
||||
`additional_infos` = :additional_infos,
|
||||
`link` = :link,
|
||||
`search_words` = :search_words,
|
||||
`created_at` = `created_at`,
|
||||
`updated_at` = NOW(),
|
||||
`outdated` = 0
|
||||
WHERE `index_name` = :index_name AND `index_id` = :index_id
|
||||
LIMIT 1';
|
||||
|
||||
$bindValues = [
|
||||
'index_name' => $item->identifier->getName(),
|
||||
'index_id' => $item->identifier->getId(),
|
||||
'project_id' => $item->data->getProjectId(),
|
||||
'title' => $item->data->getTitle(),
|
||||
'link' => $item->data->getLink(),
|
||||
'subtitle' => $item->data->getSubTitle(),
|
||||
'search_words' => $searchWords,
|
||||
'additional_infos' => $additionalInfos,
|
||||
];
|
||||
|
||||
$this->db->perform($sql, $bindValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IndexItem $item
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function createItem(IndexItem $item)
|
||||
{
|
||||
$searchWords = '';
|
||||
if (!empty($item->data->getWords())) {
|
||||
$searchWords = implode(' | ', $item->data->getWords());
|
||||
}
|
||||
$additionalInfos = null;
|
||||
if (!empty($item->data->getAdditionalInfos())) {
|
||||
$additionalInfos = implode(' ## ', $item->data->getAdditionalInfos());
|
||||
}
|
||||
|
||||
$sql =
|
||||
'INSERT INTO `supersearch_index_item`
|
||||
(`index_name`, `index_id`, `project_id`, `title`, `subtitle`, `additional_infos`,
|
||||
`link`, `search_words`, `outdated`, `created_at`, `updated_at`)
|
||||
VALUES
|
||||
(:index_name, :index_id, :project_id, :title, :subtitle, :additional_infos,
|
||||
:link, :search_words, 0, NOW(), NULL)';
|
||||
$bindValues = [
|
||||
'index_name' => $item->identifier->getName(),
|
||||
'index_id' => $item->identifier->getId(),
|
||||
'project_id' => $item->data->getProjectId(),
|
||||
'title' => $item->data->getTitle(),
|
||||
'link' => $item->data->getLink(),
|
||||
'subtitle' => $item->data->getSubTitle(),
|
||||
'search_words' => $searchWords,
|
||||
'additional_infos' => $additionalInfos,
|
||||
];
|
||||
|
||||
$this->db->perform($sql, $bindValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alle Einträge als veraltet markieren
|
||||
*
|
||||
* Beim Update/Insert eines Eintrags wird dieser wieder auf ungelöscht gestellt bevor er wirklich gelöscht wird.
|
||||
*
|
||||
* @param string $indexName
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function markIndexAsOutdated($indexName)
|
||||
{
|
||||
$sql = 'UPDATE `supersearch_index_item` SET `outdated` = 1 WHERE `index_name` = :index_name';
|
||||
$this->db->perform($sql, ['index_name' => (string)$indexName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $indexName
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function deleteOutdatedIndexItems($indexName)
|
||||
{
|
||||
$sql = 'DELETE FROM `supersearch_index_item` WHERE `index_name` = :index_name AND `outdated` = 1';
|
||||
$this->db->perform($sql, ['index_name' => (string)$indexName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return SearchIndexProviderInterface|null
|
||||
*/
|
||||
private function tryGetProviderByIndexName($name)
|
||||
{
|
||||
foreach ($this->provider as $provider) {
|
||||
if ($name === $provider->getIndexName()) {
|
||||
return $provider;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function updateLastFullUpdateTime($name)
|
||||
{
|
||||
$sql = 'UPDATE `supersearch_index_group` SET `last_full_update` = NOW() WHERE `name` = :index_name LIMIT 1';
|
||||
$this->db->perform($sql, ['index_name' => (string)$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function updateLastDiffUpdateTime($name)
|
||||
{
|
||||
$sql = 'UPDATE `supersearch_index_group` SET `last_diff_update` = NOW() WHERE `name` = :index_name LIMIT 1';
|
||||
$this->db->perform($sql, ['index_name' => (string)$name]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch;
|
||||
|
||||
use Xentral\Components\Database\Database;
|
||||
use Xentral\Components\Database\Exception\DatabaseExceptionInterface;
|
||||
|
||||
final class SuperSearchService
|
||||
{
|
||||
/** @var Database $db */
|
||||
private $db;
|
||||
|
||||
/** @var SuperSearchIndexer $indexer */
|
||||
private $indexer;
|
||||
|
||||
/**
|
||||
* @param Database $database
|
||||
* @param SuperSearchIndexer $indexer
|
||||
*/
|
||||
public function __construct(Database $database, SuperSearchIndexer $indexer)
|
||||
{
|
||||
$this->db = $database;
|
||||
$this->indexer = $indexer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $indexName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function existsIndex($indexName)
|
||||
{
|
||||
$sql = 'SELECT sig.id FROM `supersearch_index_group` AS `sig` WHERE sig.name = :index_name';
|
||||
$check = (int)$this->db->fetchValue($sql, ['index_name' => (string)$indexName]);
|
||||
|
||||
return $check > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $indexName
|
||||
* @param string $indexTitle
|
||||
* @param string|null $moduleName
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function createIndex($indexName, $indexTitle, $moduleName = null)
|
||||
{
|
||||
$sql =
|
||||
'INSERT INTO `supersearch_index_group`
|
||||
(`id`, `name`, `title`, `module`, `active`, `last_full_update`, `last_diff_update`)
|
||||
VALUES
|
||||
(NULL, :index_name, :index_title, :module_name, 1, NULL, NULL)';
|
||||
$this->db->perform($sql, [
|
||||
'index_name' => (string)$indexName,
|
||||
'index_title' => (string)$indexTitle,
|
||||
'module_name' => $moduleName !== null ? (string)$moduleName : null,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $indexName
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteIndex($indexName)
|
||||
{
|
||||
$this->db->beginTransaction();
|
||||
|
||||
try {
|
||||
$sql = 'DELETE FROM `supersearch_index_group` WHERE `name` = :index_name LIMIT 1';
|
||||
$this->db->perform($sql, ['index_name' => (string)$indexName]);
|
||||
|
||||
$sql = 'DELETE FROM `supersearch_index_item` WHERE `index_name` = :index_name';
|
||||
$this->db->perform($sql, ['index_name' => (string)$indexName]);
|
||||
|
||||
$this->db->commit();
|
||||
} catch (DatabaseExceptionInterface $exception) {
|
||||
$this->db->rollBack();
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $indexName
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function activateIndex($indexName)
|
||||
{
|
||||
$sql = 'UPDATE `supersearch_index_group` SET `active` = 1 WHERE `name` = :index_name LIMIT 1';
|
||||
$this->db->perform($sql, ['index_name' => (string)$indexName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $indexName
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deactivateIndex($indexName)
|
||||
{
|
||||
$sql =
|
||||
'UPDATE `supersearch_index_group`
|
||||
SET `active` = 0, `last_full_update` = NULL, `last_diff_update` = NULL
|
||||
WHERE `name` = :index_name
|
||||
LIMIT 1';
|
||||
$this->db->perform($sql, ['index_name' => (string)$indexName]);
|
||||
|
||||
// Index leeren
|
||||
$sql = 'DELETE FROM `supersearch_index_item` WHERE `index_name` = :index_name';
|
||||
$this->db->perform($sql, ['index_name' => (string)$indexName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isIndexEmpty()
|
||||
{
|
||||
$sql = 'SELECT COUNT(sii.id) AS total_count FROM `supersearch_index_item` AS `sii` WHERE sii.outdated = 0';
|
||||
$check = (int)$this->db->fetchValue($sql);
|
||||
|
||||
return $check === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getIndexStats()
|
||||
{
|
||||
$sql =
|
||||
'SELECT sig.name, sig.title, sig.module, sig.active, sig.last_full_update, sig.last_diff_update
|
||||
FROM `supersearch_index_group` AS `sig`';
|
||||
$groups = $this->db->fetchAll($sql);
|
||||
|
||||
// Fehlende Provider hinzufügen (Provider die noch nie liefen)
|
||||
$groupNames = array_column($groups, 'name');
|
||||
$meta = $this->indexer->getProviderMetaData();
|
||||
foreach ($meta as $info) {
|
||||
if (!in_array($info['name'], $groupNames, true)) {
|
||||
$groups[] = [
|
||||
'name' => $info['name'],
|
||||
'title' => $info['title'],
|
||||
'module' => $info['module'],
|
||||
'active' => null,
|
||||
'last_full_update' => null,
|
||||
'last_diff_update' => null,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Index-Statistik hinzufügen
|
||||
$indexSizeCurrent = $this->indexer->getProviderIndexSizesCurrent();
|
||||
$indexSizePotential = $this->indexer->getProviderIndexSizesPotential();
|
||||
foreach ($groups as $indexName => &$group) {
|
||||
$indexName = $group['name'];
|
||||
$group['index_size_current'] = isset($indexSizeCurrent[$indexName]) ? $indexSizeCurrent[$indexName] : null;
|
||||
$group['index_size_potential'] = isset($indexSizePotential[$indexName]) ? $indexSizePotential[$indexName] : null;
|
||||
if ($group['active'] === 1) {
|
||||
$group['active'] = true;
|
||||
}
|
||||
if ($group['active'] === 0) {
|
||||
$group['active'] = false;
|
||||
}
|
||||
}
|
||||
unset($group);
|
||||
|
||||
return $groups;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\SystemHealth;
|
||||
|
||||
use DateInterval;
|
||||
use DateTime;
|
||||
use DateTimeImmutable;
|
||||
use Exception;
|
||||
use Xentral\Components\Database\Database;
|
||||
|
||||
final class SuperSearchHealthChecker
|
||||
{
|
||||
/** @var Database $db */
|
||||
private $db;
|
||||
|
||||
/**
|
||||
* @param Database $database
|
||||
*/
|
||||
public function __construct(Database $database)
|
||||
{
|
||||
$this->db = $database;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getHealthStatus()
|
||||
{
|
||||
$sql =
|
||||
'SELECT
|
||||
sig.id, sig.name, sig.title, sig.module,
|
||||
IFNULL(sig.last_diff_update, sig.last_full_update) AS `last_cron_run`,
|
||||
MIN(IFNULL(sii.updated_at, sii.created_at)) AS `oldest_index_item`
|
||||
FROM `supersearch_index_group` AS sig
|
||||
LEFT JOIN `supersearch_index_item` AS sii ON sig.name = sii.index_name AND sii.outdated = 0
|
||||
WHERE sig.active = 1
|
||||
GROUP BY sig.name';
|
||||
$indexes = $this->db->fetchAll($sql);
|
||||
|
||||
$outdatedTime = new DateTime('now');
|
||||
$outdatedTime->sub(new DateInterval('PT48H'));
|
||||
|
||||
foreach ($indexes as $index) {
|
||||
$lastCronRun = $this->tryCreateDateTimeObject($index['last_cron_run']);
|
||||
if ($lastCronRun === null) {
|
||||
// Prozessstarter ist für diesen Index nie gelaufen
|
||||
return $this->buildResultForNotRunningSheduler($index['name']);
|
||||
}
|
||||
if ($lastCronRun !== null) {
|
||||
if ($lastCronRun < $outdatedTime) {
|
||||
// Prozessstarter ist für diesen Index seit mehr als 48 Stunden nicht mehr gelaufen
|
||||
return $this->buildResultForOutdatedShedulerRunDate($index['name']);
|
||||
}
|
||||
}
|
||||
|
||||
$oldestIndexItem = $this->tryCreateDateTimeObject($index['oldest_index_item']);
|
||||
if ($oldestIndexItem !== null) {
|
||||
if ($oldestIndexItem < $outdatedTime) {
|
||||
// Such-Index enthält Einträge die seit mehr als 48 Stunden nicht mehr aktualisiert wurden
|
||||
return $this->buildResultForOutdatedIndexItem($index['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wenn Code bis hierhin gelauf ist, ist alles in Ordnung
|
||||
return [
|
||||
'type' => 'ok', // string [ok|warning|error]
|
||||
'message' => null, // string|null
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $indexName
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function buildResultForNotRunningSheduler($indexName)
|
||||
{
|
||||
return [
|
||||
'type' => 'error',
|
||||
'message' => sprintf(
|
||||
'Befüllung für Such-Index "%s" wurde noch nie ausgeführt.', $indexName
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $indexName
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function buildResultForOutdatedShedulerRunDate($indexName)
|
||||
{
|
||||
return [
|
||||
'type' => 'error',
|
||||
'message' => sprintf(
|
||||
'Befüllung des Such-Index "%s" wurde seit mehr als 48 Stunden nicht mehr ausgeführt.', $indexName
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $indexName
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function buildResultForOutdatedIndexItem($indexName)
|
||||
{
|
||||
return [
|
||||
'type' => 'warning',
|
||||
'message' => sprintf(
|
||||
'Der Such-Index "%s" enthält Einträge die seit mehr als 48 Stunden nicht mehr aktualisiert wurden.',
|
||||
$indexName
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $dateTimeString
|
||||
*
|
||||
* @return DateTimeImmutable|null
|
||||
*/
|
||||
private function tryCreateDateTimeObject($dateTimeString = null)
|
||||
{
|
||||
try {
|
||||
if (!empty($dateTimeString)) {
|
||||
return new DateTimeImmutable($dateTimeString);
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Xentral\Modules\SuperSearch\Wrapper;
|
||||
|
||||
use erpAPI;
|
||||
|
||||
/**
|
||||
* Anti-Corruption-Layer für erp::GetKonfiguration und erp::SetKonfigurationValue
|
||||
*/
|
||||
final class CompanyConfigWrapper
|
||||
{
|
||||
/** @var erpAPI $erp */
|
||||
private $erp;
|
||||
|
||||
/**
|
||||
* @param erpAPI $erp
|
||||
*/
|
||||
public function __construct(erpAPI $erp)
|
||||
{
|
||||
$this->erp = $erp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
return $this->erp->GetKonfiguration($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($name, $value)
|
||||
{
|
||||
$this->erp->SetKonfigurationValue($name, $value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
var SuperSearchUi = (function ($) {
|
||||
'use strict';
|
||||
|
||||
var me = {
|
||||
|
||||
init: function () {
|
||||
me.registerEvents();
|
||||
},
|
||||
|
||||
registerEvents: function () {
|
||||
$('#supersearch-fullindex-task-trigger').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
me.onClickExecuteFullIndexTask();
|
||||
});
|
||||
|
||||
$('.button-provider-activate').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
var indexName = $(this).data('indexName');
|
||||
me.onClickActivateProvider(indexName);
|
||||
});
|
||||
|
||||
$('.button-provider-deactivate').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
var indexName = $(this).data('indexName');
|
||||
me.onClickDeactivateProvider(indexName);
|
||||
});
|
||||
},
|
||||
|
||||
onClickExecuteFullIndexTask: function () {
|
||||
var $container = $('#supersearch-fullindex-task-wrapper');
|
||||
|
||||
$.ajax({
|
||||
url: 'index.php?module=supersearch&action=settings',
|
||||
data: {
|
||||
cmd: 'run-full-index-task'
|
||||
},
|
||||
method: 'post',
|
||||
dataType: 'json',
|
||||
beforeSend: function () {
|
||||
$container.loadingOverlay();
|
||||
},
|
||||
success: function () {
|
||||
var message = '<div class="success">Such-Index wurde erfolgreich neu aufgebaut.</div>';
|
||||
message += '<a class="button button-primary" href="index.php?module=supersearch&action=settings">';
|
||||
message += 'Seite neuladen</a>';
|
||||
$container.html(message);
|
||||
},
|
||||
error: function (jqXhr) {
|
||||
var errorMessage = 'Unbekannter Fehler';
|
||||
if (jqXhr.hasOwnProperty('responseJSON') && jqXhr.responseJSON.hasOwnProperty('error')) {
|
||||
errorMessage = jqXhr.responseJSON.error;
|
||||
}
|
||||
var message = '<div class="warning">';
|
||||
message += 'Fehler beim Aufbau des Such-Indexes: ';
|
||||
message += errorMessage;
|
||||
message += '</div>';
|
||||
$container.html(message);
|
||||
},
|
||||
complete: function () {
|
||||
$container.loadingOverlay('remove');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} indexName
|
||||
*/
|
||||
onClickActivateProvider: function (indexName) {
|
||||
$.ajax({
|
||||
url: 'index.php?module=supersearch&action=settings',
|
||||
data: {
|
||||
cmd: 'activate-provider',
|
||||
index_name: indexName
|
||||
},
|
||||
method: 'post',
|
||||
dataType: 'json',
|
||||
success: function () {
|
||||
window.location.reload();
|
||||
},
|
||||
error: function (jqXhr) {
|
||||
var errorMessage = 'Unbekannter Fehler';
|
||||
if (jqXhr.hasOwnProperty('responseJSON') && jqXhr.responseJSON.hasOwnProperty('error')) {
|
||||
errorMessage = jqXhr.responseJSON.error;
|
||||
}
|
||||
alert('Fehler beim Aktivieren des Providers: ' + errorMessage);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} indexName
|
||||
*/
|
||||
onClickDeactivateProvider: function (indexName) {
|
||||
$.ajax({
|
||||
url: 'index.php?module=supersearch&action=settings',
|
||||
data: {
|
||||
cmd: 'deactivate-provider',
|
||||
index_name: indexName
|
||||
},
|
||||
method: 'post',
|
||||
dataType: 'json',
|
||||
success: function () {
|
||||
window.location.reload();
|
||||
},
|
||||
error: function (jqXhr) {
|
||||
var errorMessage = 'Unbekannter Fehler';
|
||||
if (jqXhr.hasOwnProperty('responseJSON') && jqXhr.responseJSON.hasOwnProperty('error')) {
|
||||
errorMessage = jqXhr.responseJSON.error;
|
||||
}
|
||||
alert('Fehler beim Deaktivieren des Providers: ' + errorMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
init: me.init
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
|
||||
$(document).ready(function () {
|
||||
SuperSearchUi.init();
|
||||
});
|
||||
Reference in New Issue
Block a user