mirror of
https://github.com/Codappix/search_core.git
synced 2024-12-22 18:16:11 +01:00
FEATURE: Provide form finisher for integration into form extension
Provide a finisher, working as a proxy, to internal data handler, which is already used for Hooks in TYPO3 backend.
This commit is contained in:
parent
ea8eb8148e
commit
31202f8882
5 changed files with 278 additions and 0 deletions
71
Classes/Integration/Form/Finisher/DataHandlerFinisher.php
Normal file
71
Classes/Integration/Form/Finisher/DataHandlerFinisher.php
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
namespace Codappix\SearchCore\Integration\Form\Finisher;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 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\Form\Domain\Finishers\AbstractFinisher;
|
||||
use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException;
|
||||
|
||||
/**
|
||||
* Integrates search_core indexing into TYPO3 Form extension.
|
||||
*
|
||||
* Add this finisher AFTER all database operations, as search_core will fetch
|
||||
* information from database.
|
||||
*/
|
||||
class DataHandlerFinisher extends AbstractFinisher
|
||||
{
|
||||
/**
|
||||
* @var \Codappix\SearchCore\Domain\Service\DataHandler
|
||||
* @inject
|
||||
*/
|
||||
protected $dataHandler;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $defaultOptions = [
|
||||
'indexIdentifier' => null,
|
||||
'recordUid' => null,
|
||||
'action' => '',
|
||||
];
|
||||
|
||||
protected function executeInternal()
|
||||
{
|
||||
$action = $this->parseOption('action');
|
||||
$record = ['uid' => (int) $this->parseOption('recordUid')];
|
||||
$tableName = $this->parseOption('indexIdentifier');
|
||||
|
||||
if ($action === '' || $tableName === '' || !is_string($tableName) || $record['uid'] === 0) {
|
||||
throw new FinisherException('Not all necessary options were set.', 1510313095);
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'update':
|
||||
$this->dataHandler->update($tableName, $record);
|
||||
break;
|
||||
case 'add':
|
||||
$this->dataHandler->add($tableName, $record);
|
||||
break;
|
||||
case 'delete':
|
||||
$this->dataHandler->delete($tableName, $record['uid']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,8 @@ configuration needs. Still it's possible to configure the indexer.
|
|||
|
||||
Also custom classes can be used as indexers.
|
||||
|
||||
Furthermore a finisher for TYPO3 Form-Extension is provided to integrate indexing.
|
||||
|
||||
.. _features_search:
|
||||
|
||||
Searching
|
||||
|
|
|
@ -30,6 +30,34 @@ The tables have to be configured via :ref:`configuration_options_index`.
|
|||
|
||||
Not all hook operations are supported yet, see :issue:`27`.
|
||||
|
||||
.. _usage_form_finisher:
|
||||
|
||||
Form finisher
|
||||
-------------
|
||||
|
||||
A form finisher is provided to integrate indexing into form extension.
|
||||
|
||||
Add form finisher to your available finishers and configure it like:
|
||||
|
||||
.. code-block:: yaml
|
||||
:linenos:
|
||||
|
||||
-
|
||||
identifier: SearchCoreIndexer
|
||||
options:
|
||||
action: 'delete'
|
||||
indexIdentifier: 'fe_users'
|
||||
recordUid: '{FeUser.user.uid}'
|
||||
|
||||
All three options are necessary, where
|
||||
|
||||
``action``
|
||||
Is one of ``delete``, ``update`` or ``add``.
|
||||
``indexIdentifier``
|
||||
Is a configured index identifier.
|
||||
``recordUid``
|
||||
Has to be the uid of the record to index.
|
||||
|
||||
.. _usage_searching:
|
||||
|
||||
Searching / Frontend Plugin
|
||||
|
|
|
@ -21,13 +21,23 @@ namespace Codappix\SearchCore\Tests\Unit;
|
|||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Tests\UnitTestCase as CoreTestCase;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||
use TYPO3\CMS\Form\Service\TranslationService;
|
||||
|
||||
abstract class AbstractUnitTestCase extends CoreTestCase
|
||||
{
|
||||
/**
|
||||
* @var array A backup of registered singleton instances
|
||||
*/
|
||||
protected $singletonInstances = [];
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->singletonInstances = GeneralUtility::getSingletonInstances();
|
||||
|
||||
// Disable caching backends to make TYPO3 parts work in unit test mode.
|
||||
|
||||
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
|
||||
|
@ -39,6 +49,12 @@ abstract class AbstractUnitTestCase extends CoreTestCase
|
|||
]);
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
GeneralUtility::resetSingletonInstances($this->singletonInstances);
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \TYPO3\CMS\Core\Log\LogManager
|
||||
*/
|
||||
|
@ -58,4 +74,25 @@ abstract class AbstractUnitTestCase extends CoreTestCase
|
|||
|
||||
return $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure translation service mock for Form Finisher.
|
||||
*
|
||||
* This way parseOption will always return the configured value.
|
||||
*/
|
||||
protected function configureMockedTranslationService()
|
||||
{
|
||||
$translationService = $this->getMockBuilder(TranslationService::class)->getMock();
|
||||
$translationService->expects($this->any())
|
||||
->method('translateFinisherOption')
|
||||
->willReturnCallback(function ($formRuntime, $finisherIdentifier, $optionKey, $optionValue) {
|
||||
return $optionValue;
|
||||
});
|
||||
$objectManager = $this->getMockBuilder(ObjectManager::class)->getMock();
|
||||
$objectManager->expects($this->any())
|
||||
->method('get')
|
||||
->with(TranslationService::class)
|
||||
->willReturn($translationService);
|
||||
GeneralUtility::setSingletonInstance(ObjectManager::class, $objectManager);
|
||||
}
|
||||
}
|
||||
|
|
140
Tests/Unit/Integration/Form/Finisher/DataHandlerFinisherTest.php
Normal file
140
Tests/Unit/Integration/Form/Finisher/DataHandlerFinisherTest.php
Normal file
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
namespace Codappix\SearchCore\Tests\Unit\Integration\Form\Finisher;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 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 Codappix\SearchCore\Domain\Service\DataHandler;
|
||||
use Codappix\SearchCore\Integration\Form\Finisher\DataHandlerFinisher;
|
||||
use Codappix\SearchCore\Tests\Unit\AbstractUnitTestCase;
|
||||
use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException;
|
||||
use TYPO3\CMS\Form\Domain\Finishers\FinisherContext;
|
||||
|
||||
class DataHandlerFinisherTest extends AbstractUnitTestCase
|
||||
{
|
||||
/**
|
||||
* @var DataHandlerFinisher
|
||||
*/
|
||||
protected $subject;
|
||||
|
||||
/**
|
||||
* @var DataHandler
|
||||
*/
|
||||
protected $dataHandlerMock;
|
||||
|
||||
/**
|
||||
* @var FinisherContext
|
||||
*/
|
||||
protected $finisherContextMock;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->configureMockedTranslationService();
|
||||
$this->dataHandlerMock = $this->getMockBuilder(DataHandler::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->finisherContextMock = $this->getMockBuilder(FinisherContext::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->subject = new DataHandlerFinisher();
|
||||
$this->inject($this->subject, 'dataHandler', $this->dataHandlerMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider possibleFinisherSetup
|
||||
*/
|
||||
public function validConfiguration(string $action, array $nonCalledActions, $expectedSecondArgument)
|
||||
{
|
||||
$this->subject->setOptions([
|
||||
'indexIdentifier' => 'test_identifier',
|
||||
'recordUid' => '23',
|
||||
'action' => $action,
|
||||
]);
|
||||
|
||||
foreach ($nonCalledActions as $nonCalledAction) {
|
||||
$this->dataHandlerMock->expects($this->never())->method($nonCalledAction);
|
||||
}
|
||||
$this->dataHandlerMock->expects($this->once())->method($action)
|
||||
->with('test_identifier', $expectedSecondArgument);
|
||||
|
||||
$this->subject->execute($this->finisherContextMock);
|
||||
}
|
||||
|
||||
public function possibleFinisherSetup() : array
|
||||
{
|
||||
return [
|
||||
'valid add configuration' => [
|
||||
'action' => 'add',
|
||||
'nonCalledActions' => ['delete', 'update'],
|
||||
'expectedSecondArgument' => ['uid' => 23],
|
||||
],
|
||||
'valid update configuration' => [
|
||||
'action' => 'update',
|
||||
'nonCalledActions' => ['delete', 'add'],
|
||||
'expectedSecondArgument' => ['uid' => 23],
|
||||
],
|
||||
'valid delete configuration' => [
|
||||
'action' => 'delete',
|
||||
'nonCalledActions' => ['update', 'add'],
|
||||
'expectedSecondArgument' => 23,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider invalidFinisherSetup
|
||||
*/
|
||||
public function nothingHappensIfUnknownActionIsConfigured(array $options)
|
||||
{
|
||||
$this->subject->setOptions($options);
|
||||
|
||||
foreach (['add', 'update', 'delete'] as $nonCalledAction) {
|
||||
$this->dataHandlerMock->expects($this->never())->method($nonCalledAction);
|
||||
}
|
||||
|
||||
$this->expectException(FinisherException::class);
|
||||
$this->subject->execute($this->finisherContextMock);
|
||||
}
|
||||
|
||||
public function invalidFinisherSetup() : array
|
||||
{
|
||||
return [
|
||||
'missing options' => [
|
||||
'options' => [],
|
||||
],
|
||||
'missing action option' => [
|
||||
'options' => [
|
||||
'indexIdentifier' => 'identifier',
|
||||
'recordUid' => '20',
|
||||
],
|
||||
],
|
||||
'missing record uid option' => [
|
||||
'options' => [
|
||||
'indexIdentifier' => 'identifier',
|
||||
'action' => 'update',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue