mirror of
https://github.com/Codappix/search_core.git
synced 2024-11-24 14:16:13 +01:00
TASK: Migrate existing code (#2)
This commit is contained in:
parent
d89e616a4f
commit
b079dd8125
28 changed files with 1355 additions and 30 deletions
|
@ -20,6 +20,7 @@ namespace Leonmrni\SearchCore\Command;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Leonmrni\SearchCore\Domain\Index\IndexerFactory;
|
||||||
use TYPO3\CMS\Extbase\Mvc\Controller\CommandController;
|
use TYPO3\CMS\Extbase\Mvc\Controller\CommandController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,6 +28,19 @@ use TYPO3\CMS\Extbase\Mvc\Controller\CommandController;
|
||||||
*/
|
*/
|
||||||
class IndexCommandController extends CommandController
|
class IndexCommandController extends CommandController
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var IndexerFactory
|
||||||
|
*/
|
||||||
|
protected $indexerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param IndexerFactory $factory
|
||||||
|
*/
|
||||||
|
public function injectIndexerFactory(IndexerFactory $factory)
|
||||||
|
{
|
||||||
|
$this->indexerFactory = $factory;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will index the given table or everything.
|
* Will index the given table or everything.
|
||||||
*
|
*
|
||||||
|
@ -36,5 +50,6 @@ class IndexCommandController extends CommandController
|
||||||
{
|
{
|
||||||
// TODO: Allow to index multiple tables at once?
|
// TODO: Allow to index multiple tables at once?
|
||||||
// TODO: Also allow to index everything?
|
// TODO: Also allow to index everything?
|
||||||
|
$this->indexerFactory->getIndexer($table)->index();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
75
Classes/Connection/ConnectionInterface.php
Normal file
75
Classes/Connection/ConnectionInterface.php
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Connection;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines interface for connections to storage backend for interacting with documents.
|
||||||
|
*/
|
||||||
|
interface ConnectionInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Will add a new document, based on his identifier and record type.
|
||||||
|
*
|
||||||
|
* @param string $recordType
|
||||||
|
* @param int $identifier
|
||||||
|
* @param array $record
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public function add($recordType, $identifier, array $record);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given records.
|
||||||
|
*
|
||||||
|
* @param string $recordType
|
||||||
|
* @param array $records
|
||||||
|
*/
|
||||||
|
public function addDocuments($recordType, array $records);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will update an existing document, based on his identifier and record type.
|
||||||
|
*
|
||||||
|
* @param string $recordType
|
||||||
|
* @param int $identifier
|
||||||
|
* @param array $record
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public function update($recordType, $identifier, array $record);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will remove an existing document, based on his identifier and record type.
|
||||||
|
*
|
||||||
|
* @param string $recordType
|
||||||
|
* @param int $identifier
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public function delete($recordType, $identifier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search by given request and return result.
|
||||||
|
*
|
||||||
|
* @param SearchRequestInterface $searchRequest
|
||||||
|
* @return SearchResultInterface
|
||||||
|
*/
|
||||||
|
public function search(SearchRequestInterface $searchRequest);
|
||||||
|
}
|
140
Classes/Connection/Elasticsearch.php
Normal file
140
Classes/Connection/Elasticsearch.php
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Connection;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outer wrapper to elasticsearch.
|
||||||
|
*/
|
||||||
|
class Elasticsearch implements Singleton, ConnectionInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Elasticsearch\Connection
|
||||||
|
*/
|
||||||
|
protected $connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var IndexFactory
|
||||||
|
*/
|
||||||
|
protected $indexFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var TypeFactory
|
||||||
|
*/
|
||||||
|
protected $typeFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var DocumentFactory
|
||||||
|
*/
|
||||||
|
protected $documentFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject log manager to get concrete logger from it.
|
||||||
|
*
|
||||||
|
* @param \TYPO3\CMS\Core\Log\LogManager $logManager
|
||||||
|
*/
|
||||||
|
public function injectLogger(\TYPO3\CMS\Core\Log\LogManager $logManager)
|
||||||
|
{
|
||||||
|
$this->logger = $logManager->getLogger(__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Elasticsearch\Connection $connection
|
||||||
|
* @param Elasticsearch\IndexFactory $indexFactory
|
||||||
|
* @param Elasticsearch\TypeFactory $typeFactory
|
||||||
|
* @param Elasticsearch\DocumentFactory $documentFactory
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
Elasticsearch\Connection $connection,
|
||||||
|
Elasticsearch\IndexFactory $indexFactory,
|
||||||
|
Elasticsearch\TypeFactory $typeFactory,
|
||||||
|
Elasticsearch\DocumentFactory $documentFactory
|
||||||
|
) {
|
||||||
|
$this->connection = $connection;
|
||||||
|
$this->indexFactory = $indexFactory;
|
||||||
|
$this->typeFactory = $typeFactory;
|
||||||
|
$this->documentFactory = $documentFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function add($recordType, $identifier, array $record)
|
||||||
|
{
|
||||||
|
throw new \Exception('Implement', 1481190734);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete($recordType, $identifier)
|
||||||
|
{
|
||||||
|
throw new \Exception('Implement', 1481190734);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update($tableName, $identifier, array $record)
|
||||||
|
{
|
||||||
|
$this->addDocument($tableName, $identifier, $record);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addDocument($tableName, $identifier, array $record)
|
||||||
|
{
|
||||||
|
throw new \Exception('Implement', 1481192791);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given records to elasticsearch.
|
||||||
|
*
|
||||||
|
* @param string $tableName
|
||||||
|
* @param array $records
|
||||||
|
*/
|
||||||
|
public function addDocuments($tableName, array $records)
|
||||||
|
{
|
||||||
|
$type = $this->typeFactory->getType(
|
||||||
|
$this->indexFactory->getIndex(
|
||||||
|
$this->connection,
|
||||||
|
$tableName
|
||||||
|
),
|
||||||
|
$tableName
|
||||||
|
);
|
||||||
|
|
||||||
|
$type->addDocuments(
|
||||||
|
$this->documentFactory->getDocuments($tableName, $records)
|
||||||
|
);
|
||||||
|
|
||||||
|
$type->getIndex()->refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SearchRequestInterface $searchRequest
|
||||||
|
* @return SearchResultInterface
|
||||||
|
*/
|
||||||
|
public function search(SearchRequestInterface $searchRequest)
|
||||||
|
{
|
||||||
|
$this->logger->debug('Search for', [$searchRequest->getSearchTerm()]);
|
||||||
|
|
||||||
|
$search = new \Elastica\Search($this->connection->getClient());
|
||||||
|
$search->addIndex('typo3content');
|
||||||
|
|
||||||
|
// TODO: Return wrapped result to implement our interface.
|
||||||
|
return $search->search($searchRequest->getSearchTerm());
|
||||||
|
}
|
||||||
|
}
|
95
Classes/Connection/Elasticsearch/Connection.php
Normal file
95
Classes/Connection/Elasticsearch/Connection.php
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current connection to elasticsearch.
|
||||||
|
*
|
||||||
|
* Wrapper for Elastica\Client.
|
||||||
|
*/
|
||||||
|
class Connection implements Singleton
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \Elastica\Client
|
||||||
|
*/
|
||||||
|
protected $elasticaClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Elastica\Client $elasticaClient
|
||||||
|
*/
|
||||||
|
public function __construct(\Elastica\Client $elasticaClient = null)
|
||||||
|
{
|
||||||
|
$this->elasticaClient = $elasticaClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject news settings via ConfigurationManager.
|
||||||
|
*
|
||||||
|
* TODO: Refactor to configuration object to have a singleton holding the
|
||||||
|
* settings with validation and propper getter?
|
||||||
|
*
|
||||||
|
* @param \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface $configurationManager
|
||||||
|
*/
|
||||||
|
public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
|
||||||
|
{
|
||||||
|
$this->settings = $configurationManager->getConfiguration(
|
||||||
|
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
|
||||||
|
'SearchCore',
|
||||||
|
'search'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to configure elasticaClient if no one was injected. Will use
|
||||||
|
* injected settings for configuration.
|
||||||
|
*/
|
||||||
|
public function initializeObject()
|
||||||
|
{
|
||||||
|
if ($this->elasticaClient === null) {
|
||||||
|
$this->elasticaClient = new \Elastica\Client([
|
||||||
|
'host' => $this->settings['host'],
|
||||||
|
'port' => $this->settings['port'],
|
||||||
|
// TODO: Make configurable
|
||||||
|
// 'log' => 'file',
|
||||||
|
]);
|
||||||
|
// TODO: Make configurable.
|
||||||
|
// new \Elastica\Log($this->elasticaClient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the concrete client for internal usage!
|
||||||
|
*
|
||||||
|
* @return \Elastica\Client
|
||||||
|
*/
|
||||||
|
public function getClient()
|
||||||
|
{
|
||||||
|
return $this->elasticaClient;
|
||||||
|
}
|
||||||
|
}
|
82
Classes/Connection/Elasticsearch/DocumentFactory.php
Normal file
82
Classes/Connection/Elasticsearch/DocumentFactory.php
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory to create documents to index in Elasticsearch.
|
||||||
|
*/
|
||||||
|
class DocumentFactory implements Singleton
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject log manager to get concrete logger from it.
|
||||||
|
*
|
||||||
|
* @param \TYPO3\CMS\Core\Log\LogManager $logManager
|
||||||
|
*/
|
||||||
|
public function injectLogger(\TYPO3\CMS\Core\Log\LogManager $logManager)
|
||||||
|
{
|
||||||
|
$this->logger = $logManager->getLogger(__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates document from record.
|
||||||
|
*
|
||||||
|
* @param string $tableName
|
||||||
|
* @param array $record
|
||||||
|
*
|
||||||
|
* @return \Elastica\Document
|
||||||
|
*/
|
||||||
|
public function getDocument($tableName, array $record)
|
||||||
|
{
|
||||||
|
if (!isset($record['search_identifier'])) {
|
||||||
|
throw new \Exception('No search_identifier provided for record.', 1481194385);
|
||||||
|
}
|
||||||
|
|
||||||
|
$identifier = $record['search_identifier'];
|
||||||
|
unset($record['search_identifier']);
|
||||||
|
|
||||||
|
$this->logger->debug('Convert record to document', [$identifier, $record]);
|
||||||
|
return new \Elastica\Document($identifier, $record);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates documents based on records.
|
||||||
|
*
|
||||||
|
* @param string $tableName
|
||||||
|
* @param array $records
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getDocuments($tableName, array $records)
|
||||||
|
{
|
||||||
|
foreach ($records as &$record) {
|
||||||
|
$record = $this->getDocument($tableName, $record);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $records;
|
||||||
|
}
|
||||||
|
}
|
58
Classes/Connection/Elasticsearch/IndexFactory.php
Normal file
58
Classes/Connection/Elasticsearch/IndexFactory.php
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory to get indexes.
|
||||||
|
*
|
||||||
|
* The factory will take care of configuration and creation of index if necessary.
|
||||||
|
*/
|
||||||
|
class IndexFactory implements Singleton
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get an index bases on TYPO3 table name.
|
||||||
|
*
|
||||||
|
* @param Connection $connection
|
||||||
|
* @param string $tableName
|
||||||
|
*
|
||||||
|
* @return \Elastica\Index
|
||||||
|
*/
|
||||||
|
public function getIndex(Connection $connection, $tableName)
|
||||||
|
{
|
||||||
|
// TODO: Fetch index name from configuration, based on $tableName.
|
||||||
|
$index = $connection->getClient()->getIndex('typo3content');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// TODO: Provide configuration?!
|
||||||
|
// http://elastica.io/getting-started/storing-and-indexing-documents.html#section-analysis
|
||||||
|
$index->create();
|
||||||
|
} catch (\Elastica\Exception\ResponseException $exception) {
|
||||||
|
if (stripos($exception->getMessage(), 'already exists') === false) {
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $index;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Leonmrni\SearchCore\Tests\Fakes;
|
namespace Leonmrni\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 Daniel Siepmann <daniel.siepmann@typo3.org>
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -20,20 +20,12 @@ namespace Leonmrni\SearchCore\Tests\Fakes;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use TYPO3\CMS\Core\Log\LogManager;
|
use Leonmrni\SearchCore\Connection\SearchResultInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fakes the LogManager to prevent dependencies and logging during tests.
|
*
|
||||||
*/
|
*/
|
||||||
class FakeLogManager extends LogManager
|
class SearchResult extends \Elastica\SearchResult implements SearchResultInterface
|
||||||
{
|
{
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->loggers['fake'] = new Logger('fake');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLogger($name = '')
|
|
||||||
{
|
|
||||||
return $this->loggers['fake'];
|
|
||||||
}
|
|
||||||
}
|
}
|
45
Classes/Connection/Elasticsearch/TypeFactory.php
Normal file
45
Classes/Connection/Elasticsearch/TypeFactory.php
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Connection\Elasticsearch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||||
|
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory to get indexes.
|
||||||
|
*
|
||||||
|
* The factory will take care of configuration and creation of index if necessary.
|
||||||
|
*/
|
||||||
|
class TypeFactory implements Singleton
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get an index bases on TYPO3 table name.
|
||||||
|
*
|
||||||
|
* @param \Elastica\Index $index
|
||||||
|
* @param string $tableName
|
||||||
|
*
|
||||||
|
* @return \Elastica\Type
|
||||||
|
*/
|
||||||
|
public function getType(\Elastica\Index $index, $tableName)
|
||||||
|
{
|
||||||
|
return $index->getType($tableName);
|
||||||
|
}
|
||||||
|
}
|
34
Classes/Connection/SearchRequestInterface.php
Normal file
34
Classes/Connection/SearchRequestInterface.php
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Connection;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
interface SearchRequestInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the actual string the user searched for.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSearchTerm();
|
||||||
|
}
|
29
Classes/Connection/SearchResultInterface.php
Normal file
29
Classes/Connection/SearchResultInterface.php
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Connection;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
interface SearchResultInterface extends \Iterator, \Countable, \ArrayAccess
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
64
Classes/Controller/SearchController.php
Normal file
64
Classes/Controller/SearchController.php
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Controller;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Leonmrni\SearchCore\Domain\Model\SearchRequest;
|
||||||
|
use Leonmrni\SearchCore\Domain\Search\SearchService;
|
||||||
|
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handling search logic in TYPO3 Frontend.
|
||||||
|
*/
|
||||||
|
class SearchController extends ActionController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var SearchService
|
||||||
|
*/
|
||||||
|
protected $searchService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SearchService $searchService
|
||||||
|
*/
|
||||||
|
public function __construct(SearchService $searchService)
|
||||||
|
{
|
||||||
|
$this->searchService = $searchService;
|
||||||
|
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a search and deliver original request and result to view.
|
||||||
|
*
|
||||||
|
* @param SearchRequest $searchRequest
|
||||||
|
*/
|
||||||
|
public function searchAction(SearchRequest $searchRequest = null)
|
||||||
|
{
|
||||||
|
$searchResult = null;
|
||||||
|
if ($searchRequest !== null) {
|
||||||
|
$searchResult = $this->searchService->search($searchRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->assignMultiple([
|
||||||
|
'searchRequest' => $searchRequest,
|
||||||
|
'searchResult' => $searchResult,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
60
Classes/Domain/Index/IndexerFactory.php
Normal file
60
Classes/Domain/Index/IndexerFactory.php
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Domain\Index;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory to get configured indexer based on configuration.
|
||||||
|
*/
|
||||||
|
class IndexerFactory implements Singleton
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ObjectManager
|
||||||
|
*/
|
||||||
|
protected $objectManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ObjectManagerInterface $objectManager
|
||||||
|
*/
|
||||||
|
public function __construct(ObjectManagerInterface $objectManager)
|
||||||
|
{
|
||||||
|
$this->objectManager = $objectManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $tableName
|
||||||
|
*
|
||||||
|
* @return IndexerInterface
|
||||||
|
*/
|
||||||
|
public function getIndexer($tableName)
|
||||||
|
{
|
||||||
|
// This is the place to use configuration to return different indexer.
|
||||||
|
return $this->objectManager->get(
|
||||||
|
TcaIndexer::Class,
|
||||||
|
$this->objectManager->get(
|
||||||
|
TcaIndexer\TcaTableService::class,
|
||||||
|
$tableName
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
32
Classes/Domain/Index/IndexerInterface.php
Normal file
32
Classes/Domain/Index/IndexerInterface.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Domain\Index;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface that all indexer should implement.
|
||||||
|
*/
|
||||||
|
interface IndexerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Index the index.
|
||||||
|
*/
|
||||||
|
public function index();
|
||||||
|
}
|
29
Classes/Domain/Index/IndexingException.php
Normal file
29
Classes/Domain/Index/IndexingException.php
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Domain\Index;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown on errors while indexing.
|
||||||
|
*/
|
||||||
|
class IndexingException extends \Exception
|
||||||
|
{
|
||||||
|
const CODE_UNKOWN_TCA_TABLE = 1481190283;
|
||||||
|
}
|
117
Classes/Domain/Index/TcaIndexer.php
Normal file
117
Classes/Domain/Index/TcaIndexer.php
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Domain\Index;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||||
|
use Leonmrni\SearchCore\Connection\ConnectionInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will index the given table using configuration from TCA.
|
||||||
|
*/
|
||||||
|
class TcaIndexer implements IndexerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ConnectionInterface
|
||||||
|
*/
|
||||||
|
protected $connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var TcaIndexer\TcaTableService
|
||||||
|
*/
|
||||||
|
protected $tcaTableService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject log manager to get concrete logger from it.
|
||||||
|
*
|
||||||
|
* @param \TYPO3\CMS\Core\Log\LogManager $logManager
|
||||||
|
*/
|
||||||
|
public function injectLogger(\TYPO3\CMS\Core\Log\LogManager $logManager)
|
||||||
|
{
|
||||||
|
$this->logger = $logManager->getLogger(__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $tableName
|
||||||
|
* @param ConnectionInterface $connection
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
TcaIndexer\TcaTableService $tcaTableService,
|
||||||
|
ConnectionInterface $connection
|
||||||
|
) {
|
||||||
|
$this->tcaTableService = $tcaTableService;
|
||||||
|
$this->connection = $connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$this->logger->info('Start indexing');
|
||||||
|
foreach ($this->getRecordGenerator() as $records) {
|
||||||
|
$this->logger->debug('Index records.', [$records]);
|
||||||
|
$this->connection->addDocuments($this->tcaTableService->getTableName(), $records);
|
||||||
|
}
|
||||||
|
$this->logger->info('Finish indexing');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Iterator
|
||||||
|
*/
|
||||||
|
protected function getRecordGenerator()
|
||||||
|
{
|
||||||
|
$offset = 0;
|
||||||
|
// TODO: Make configurable.
|
||||||
|
$limit = 50;
|
||||||
|
|
||||||
|
while (($records = $this->getRecords($offset, $limit)) !== []) {
|
||||||
|
yield $records;
|
||||||
|
$offset += $limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $offset
|
||||||
|
* @param int $limit
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getRecords($offset, $limit)
|
||||||
|
{
|
||||||
|
$records = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
|
||||||
|
$this->tcaTableService->getFields(),
|
||||||
|
$this->tcaTableService->getTableName(),
|
||||||
|
$this->tcaTableService->getWhereClause(),
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
(int) $offset . ',' . (int) $limit
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($records as &$record) {
|
||||||
|
$this->tcaTableService->prepareRecord($record);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Ignore records from sys folder?
|
||||||
|
|
||||||
|
return $records;
|
||||||
|
}
|
||||||
|
}
|
167
Classes/Domain/Index/TcaIndexer/TcaTableService.php
Normal file
167
Classes/Domain/Index/TcaIndexer/TcaTableService.php
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Domain\Index\TcaIndexer;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||||
|
use Leonmrni\SearchCore\Domain\Index\IndexingException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulate logik related to tca configuration.
|
||||||
|
*/
|
||||||
|
class TcaTableService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* TCA for current table.
|
||||||
|
* !REFERENCE! To save memory.
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $tca;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $tableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject log manager to get concrete logger from it.
|
||||||
|
*
|
||||||
|
* @param \TYPO3\CMS\Core\Log\LogManager $logManager
|
||||||
|
*/
|
||||||
|
public function injectLogger(\TYPO3\CMS\Core\Log\LogManager $logManager)
|
||||||
|
{
|
||||||
|
$this->logger = $logManager->getLogger(__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __construct($tableName)
|
||||||
|
{
|
||||||
|
if (!isset($GLOBALS['TCA'][$tableName])) {
|
||||||
|
throw new IndexingException(
|
||||||
|
'Table "' . $tableName . '" is not configured in TCA.',
|
||||||
|
IndexingException::CODE_UNKOWN_TCA_TABLE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->tableName = $tableName;
|
||||||
|
$this->tca = &$GLOBALS['TCA'][$this->tableName];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTableName()
|
||||||
|
{
|
||||||
|
return $this->tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust record accordingly to configuration.
|
||||||
|
* @param array &$record
|
||||||
|
*/
|
||||||
|
public function prepareRecord(array &$record)
|
||||||
|
{
|
||||||
|
// TODO: Resolve values from 'items' like static select, radio or checkbox.
|
||||||
|
|
||||||
|
if (isset($record['uid']) && !isset($record['search_identifier'])) {
|
||||||
|
$record['search_identifier'] = $record['uid'];
|
||||||
|
}
|
||||||
|
if (isset($record[$this->tca['ctrl']['label']]) && !isset($record['search_title'])) {
|
||||||
|
$record['search_title'] = $record[$this->tca['ctrl']['label']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getWhereClause()
|
||||||
|
{
|
||||||
|
$whereClause = '1=1 '
|
||||||
|
. BackendUtility::BEenableFields($this->tableName)
|
||||||
|
. BackendUtility::deleteClause($this->tableName)
|
||||||
|
;
|
||||||
|
|
||||||
|
$this->logger->debug('Generated where clause.', [$this->tableName, $whereClause]);
|
||||||
|
return $whereClause;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getFields()
|
||||||
|
{
|
||||||
|
$fields = 'uid,pid,' . implode(
|
||||||
|
',',
|
||||||
|
array_filter(
|
||||||
|
array_keys($this->tca['columns']),
|
||||||
|
function ($columnName) {
|
||||||
|
$columnConfig = $this->tca['columns'][$columnName]['config'];
|
||||||
|
return !$this->isRelation($columnConfig) && !$this->isSystemField($columnName);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->logger->debug('Generated fields.', [$this->tableName, $fields]);
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isRelation(array &$columnConfig)
|
||||||
|
{
|
||||||
|
if (isset($columnConfig['foreign_table'])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isSystemField($columnName)
|
||||||
|
{
|
||||||
|
$systemFields = [
|
||||||
|
// Versioning fields,
|
||||||
|
// https://docs.typo3.org/typo3cms/TCAReference/Reference/Ctrl/Index.html#versioningws
|
||||||
|
't3ver_oid', 't3ver_id', 't3ver_label', 't3ver_wsid',
|
||||||
|
't3ver_state', 't3ver_stage', 't3ver_count', 't3ver_tstamp',
|
||||||
|
't3ver_move_id', 't3ver_swapmode',
|
||||||
|
$this->tca['ctrl']['transOrigDiffSourceField'],
|
||||||
|
$this->tca['ctrl']['cruser_id'],
|
||||||
|
$this->tca['ctrl']['fe_cruser_id'],
|
||||||
|
$this->tca['ctrl']['fe_crgroup_id'],
|
||||||
|
$this->tca['ctrl']['languageField'],
|
||||||
|
$this->tca['ctrl']['origUid'],
|
||||||
|
];
|
||||||
|
if (in_array($columnName, $systemFields)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
60
Classes/Domain/Model/SearchRequest.php
Normal file
60
Classes/Domain/Model/SearchRequest.php
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Domain\Model;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Leonmrni\SearchCore\Connection\SearchRequestInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a search request used to process an actual search.
|
||||||
|
*/
|
||||||
|
class SearchRequest implements SearchRequestInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The search string provided by the user, the actual term to search for.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $query;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $query
|
||||||
|
*/
|
||||||
|
public function __construct($query)
|
||||||
|
{
|
||||||
|
$this->query = $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getQuery()
|
||||||
|
{
|
||||||
|
return $this->query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSearchTerm()
|
||||||
|
{
|
||||||
|
return '"' . $this->query . '"';
|
||||||
|
}
|
||||||
|
}
|
69
Classes/Domain/Search/SearchService.php
Normal file
69
Classes/Domain/Search/SearchService.php
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Domain\Search;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Leonmrni\SearchCore\Connection\ConnectionInterface;
|
||||||
|
use Leonmrni\SearchCore\Connection\SearchRequestInterface;
|
||||||
|
use Leonmrni\SearchCore\Connection\SearchResultInterface;
|
||||||
|
use Leonmrni\SearchCore\Domain\Model\SearchRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service to process a search request.
|
||||||
|
*/
|
||||||
|
class SearchService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ConnectionInterface
|
||||||
|
*/
|
||||||
|
protected $connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject log manager to get concrete logger from it.
|
||||||
|
*
|
||||||
|
* @param \TYPO3\CMS\Core\Log\LogManager $logManager
|
||||||
|
*/
|
||||||
|
public function injectLogger(\TYPO3\CMS\Core\Log\LogManager $logManager)
|
||||||
|
{
|
||||||
|
$this->logger = $logManager->getLogger(__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ConnectionInterface $connection
|
||||||
|
*/
|
||||||
|
public function __construct(ConnectionInterface $connection)
|
||||||
|
{
|
||||||
|
$this->connection = $connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SearchRequestInterface $searchRequest
|
||||||
|
* @return SearchResultInterface
|
||||||
|
*/
|
||||||
|
public function search(SearchRequestInterface $searchRequest)
|
||||||
|
{
|
||||||
|
return $this->connection->search($searchRequest);
|
||||||
|
}
|
||||||
|
}
|
84
Classes/Domain/Service/DataHandler.php
Normal file
84
Classes/Domain/Service/DataHandler.php
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
namespace Leonmrni\SearchCore\Domain\Service;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles all data related things like updates, deletes and inserts.
|
||||||
|
*
|
||||||
|
* This is the place to add mappings of further parts to adjust the data before
|
||||||
|
* sending ot to connection.
|
||||||
|
*/
|
||||||
|
class DataHandler implements Singleton
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \Leonmrni\SearchCore\Connection\ConnectionInterface
|
||||||
|
* @inject
|
||||||
|
*/
|
||||||
|
protected $connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \TYPO3\CMS\Core\Log\Logger
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject log manager to get concrete logger from it.
|
||||||
|
*
|
||||||
|
* @param \TYPO3\CMS\Core\Log\LogManager $logManager
|
||||||
|
*/
|
||||||
|
public function injectLogger(\TYPO3\CMS\Core\Log\LogManager $logManager)
|
||||||
|
{
|
||||||
|
$this->logger = $logManager->getLogger(__CLASS__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $table
|
||||||
|
* @param int $identifier
|
||||||
|
*/
|
||||||
|
public function delete($table, $identifier)
|
||||||
|
{
|
||||||
|
$this->logger->debug('Record received for delete.', [$table, $identifier]);
|
||||||
|
$this->connection->delete($table, $identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $table
|
||||||
|
* @param int $identifier
|
||||||
|
* @param array $record
|
||||||
|
*/
|
||||||
|
public function add($table, $identifier, array $record)
|
||||||
|
{
|
||||||
|
$this->logger->debug('Record received for add.', [$table, $identifier, $record]);
|
||||||
|
$this->connection->add($table, $identifier, $record);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $table
|
||||||
|
* @param int $identifier
|
||||||
|
*/
|
||||||
|
public function update($table, $identifier, array $record)
|
||||||
|
{
|
||||||
|
$this->logger->debug('Record received for update.', [$table, $identifier, $record]);
|
||||||
|
$this->connection->update($table, $identifier, $record);
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,7 @@ use TYPO3\CMS\Core\Log\Logger;
|
||||||
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
use TYPO3\CMS\Core\SingletonInterface as Singleton;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||||
use Leonmrni\SearchCore\Service\DataHandler as OwnDataHandler;
|
use Leonmrni\SearchCore\Domain\Service\DataHandler as OwnDataHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for TYPO3 Hooks to internal API.
|
* Wrapper for TYPO3 Hooks to internal API.
|
||||||
|
|
0
Configuration/TypoScript/constants.txt
Normal file
0
Configuration/TypoScript/constants.txt
Normal file
12
Configuration/TypoScript/setup.txt
Normal file
12
Configuration/TypoScript/setup.txt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
plugin {
|
||||||
|
tx_searchcore {
|
||||||
|
settings {
|
||||||
|
connection {
|
||||||
|
host = localhost
|
||||||
|
port = 9200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.tx_searchcore < plugin.tx_searchcore
|
13
Resources/Private/Templates/Search/Search.html
Normal file
13
Resources/Private/Templates/Search/Search.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<f:form name="searchRequest" object="{searchRequest}">
|
||||||
|
|
||||||
|
<f:form.textfield property="query" />
|
||||||
|
<f:form.submit value="search" />
|
||||||
|
|
||||||
|
</f:form>
|
||||||
|
|
||||||
|
<f:for each="{searchResult}" as="result">
|
||||||
|
<f:link.page pageUid="{result.hit._source.pid}">
|
||||||
|
{result.id} [{result.type}] - {result.hit._source.search_title}
|
||||||
|
</f:link.page>
|
||||||
|
<br>
|
||||||
|
</f:for>
|
|
@ -20,12 +20,10 @@ namespace Leonmrni\SearchCore\Tests\Unit\Hook;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Leonmrni\SearchCore\Hook\DataHandler as Hook;
|
|
||||||
use Leonmrni\SearchCore\Service\DataHandler;
|
|
||||||
use Leonmrni\SearchCore\Tests\Fakes\FakeLogManager;
|
|
||||||
use TYPO3\CMS\Core\DataHandling\DataHandler as CoreDataHandler;
|
use TYPO3\CMS\Core\DataHandling\DataHandler as CoreDataHandler;
|
||||||
use TYPO3\CMS\Core\Log\LogManager;
|
|
||||||
use TYPO3\CMS\Core\Tests\UnitTestCase;
|
use TYPO3\CMS\Core\Tests\UnitTestCase;
|
||||||
|
use Leonmrni\SearchCore\Domain\Service\DataHandler;
|
||||||
|
use Leonmrni\SearchCore\Hook\DataHandler as Hook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -47,9 +45,6 @@ class DataHandlerTest extends UnitTestCase
|
||||||
*/
|
*/
|
||||||
protected function setUp()
|
protected function setUp()
|
||||||
{
|
{
|
||||||
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\Container\Container')
|
|
||||||
->registerImplementation(LogManager::class, FakeLogManager::class);
|
|
||||||
|
|
||||||
$this->subject = $this->getAccessibleMock(DataHandler::class);
|
$this->subject = $this->getAccessibleMock(DataHandler::class);
|
||||||
$this->hook = $this->getAccessibleMock(
|
$this->hook = $this->getAccessibleMock(
|
||||||
Hook::class,
|
Hook::class,
|
||||||
|
@ -57,9 +52,7 @@ class DataHandlerTest extends UnitTestCase
|
||||||
'getTablesToProcess',
|
'getTablesToProcess',
|
||||||
'getRecord'
|
'getRecord'
|
||||||
],
|
],
|
||||||
[
|
[$this->subject]
|
||||||
$this->subject,
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->hook->method('getTablesToProcess')
|
$this->hook->method('getTablesToProcess')
|
||||||
|
@ -82,7 +75,7 @@ class DataHandlerTest extends UnitTestCase
|
||||||
$this->subject->expects($this->exactly(0))->method('add');
|
$this->subject->expects($this->exactly(0))->method('add');
|
||||||
$this->subject->expects($this->exactly(0))->method('update');
|
$this->subject->expects($this->exactly(0))->method('update');
|
||||||
|
|
||||||
$dataHandler = $this->getAccessibleMock(CoreDataHandler::class, [], [], '', false);
|
$dataHandler = new CoreDataHandler();
|
||||||
$dataHandler->substNEWwithIDs = ['NEW34' => $recordUid];
|
$dataHandler->substNEWwithIDs = ['NEW34' => $recordUid];
|
||||||
|
|
||||||
$this->hook->processCmdmap_deleteAction($table, $recordUid, [], false, $dataHandler);
|
$this->hook->processCmdmap_deleteAction($table, $recordUid, [], false, $dataHandler);
|
||||||
|
@ -101,7 +94,7 @@ class DataHandlerTest extends UnitTestCase
|
||||||
$this->subject->expects($this->once())->method('add');
|
$this->subject->expects($this->once())->method('add');
|
||||||
$this->subject->expects($this->once())->method('update');
|
$this->subject->expects($this->once())->method('update');
|
||||||
|
|
||||||
$dataHandler = $this->getAccessibleMock(CoreDataHandler::class, [], [], '', false);
|
$dataHandler = new CoreDataHandler();
|
||||||
$dataHandler->substNEWwithIDs = ['NEW34' => $recordUid];
|
$dataHandler->substNEWwithIDs = ['NEW34' => $recordUid];
|
||||||
|
|
||||||
$this->hook->processCmdmap_deleteAction($table, $recordUid, [], false, $dataHandler);
|
$this->hook->processCmdmap_deleteAction($table, $recordUid, [], false, $dataHandler);
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
"TYPO3\\CMS\\Core\\Tests\\": ".Build/vendor/typo3/cms/typo3/sysext/core/Tests/"
|
"TYPO3\\CMS\\Core\\Tests\\": ".Build/vendor/typo3/cms/typo3/sysext/core/Tests/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"require" : {
|
"require" : {
|
||||||
"php": ">=5.6.0",
|
"php": ">=5.6.0",
|
||||||
"typo3/cms": ">=6.2.0"
|
"typo3/cms": ">=6.2.0"
|
||||||
|
|
|
@ -6,8 +6,8 @@ $EM_CONF[$_EXTKEY] = [
|
||||||
'category' => 'be',
|
'category' => 'be',
|
||||||
'constraints' => [
|
'constraints' => [
|
||||||
'depends' => [
|
'depends' => [
|
||||||
'typo3' => '6.2.0-8.99.99',
|
'typo3' => '7.6.2-8.99.99',
|
||||||
'php' => '5.6.0-7.99.99'
|
'php' => '7.0.0-7.99.99'
|
||||||
],
|
],
|
||||||
'conflicts' => [],
|
'conflicts' => [],
|
||||||
],
|
],
|
||||||
|
|
48
ext_localconf.php
Normal file
48
ext_localconf.php
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
call_user_func(
|
||||||
|
function ($extensionKey) {
|
||||||
|
// TODO: Add hook for Extbase -> to handle records modified through
|
||||||
|
// Frontend and backend modules not using datahandler
|
||||||
|
|
||||||
|
$GLOBALS['TYPO3_CONF_VARS'] = TYPO3\CMS\Extbase\Utility\ArrayUtility::arrayMergeRecursiveOverrule(
|
||||||
|
$GLOBALS['TYPO3_CONF_VARS'],
|
||||||
|
[
|
||||||
|
'SC_OPTIONS' => [
|
||||||
|
'extbase' => [
|
||||||
|
'commandControllers' => [
|
||||||
|
Leonmrni\SearchCore\Command\IndexCommandController::class,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
// Not yet, first finish whole indexing through command controller as it's more important.
|
||||||
|
// 't3lib/class.t3lib_tcemain.php' => [
|
||||||
|
// 'processCmdmapClass' => [
|
||||||
|
// $extensionKey => \Leonmrni\SearchCore\Hook\DataHandler::class,
|
||||||
|
// ],
|
||||||
|
// 'processDatamapClass' => [
|
||||||
|
// $extensionKey => \Leonmrni\SearchCore\Hook\DataHandler::class,
|
||||||
|
// ],
|
||||||
|
// ],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
|
||||||
|
'Leonmrni.' . $extensionKey,
|
||||||
|
'search',
|
||||||
|
[
|
||||||
|
'Search' => 'search'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Search' => 'search' // TODO: Enable caching. But submitting form results in previous result?!
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\Container\Container')
|
||||||
|
->registerImplementation(
|
||||||
|
'Leonmrni\SearchCore\Connection\ConnectionInterface',
|
||||||
|
'Leonmrni\SearchCore\Connection\Elasticsearch'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
$_EXTKEY
|
||||||
|
);
|
13
ext_tables.php
Normal file
13
ext_tables.php
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile(
|
||||||
|
$_EXTKEY,
|
||||||
|
'Configuration/TypoScript/',
|
||||||
|
'Search Core'
|
||||||
|
);
|
||||||
|
|
||||||
|
TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin(
|
||||||
|
'Leonmrni.' . $_EXTKEY,
|
||||||
|
'search',
|
||||||
|
'Search Core'
|
||||||
|
);
|
Loading…
Reference in a new issue