[FEATURE] Hook to modify the display results before FluidView assignment 48/54148/6
authorJoerg Boesche <typo3@joergboesche.de>
Fri, 15 Sep 2017 08:45:40 +0000 (10:45 +0200)
committerJigal van Hemert <jigal.van.hemert@typo3.org>
Fri, 17 Nov 2017 09:36:57 +0000 (10:36 +0100)
To modify the display result rows before data is assigned to the fluid
view there is a new hook inside the `getDisplayResults()` method
called `getDisplayResults_postProc`.

Resolves: #82488
Releases: master
Change-Id: I2f0ac073692fb28b9c71a18def027c71a418606f
Reviewed-on: https://review.typo3.org/54148
Reviewed-by: Jigal van Hemert <jigal.van.hemert@typo3.org>
Tested-by: Jigal van Hemert <jigal.van.hemert@typo3.org>
typo3/sysext/core/Documentation/Changelog/master/Feature-82488-HookToModifyResultsBeforeAssignToView.rst [new file with mode: 0644]
typo3/sysext/indexed_search/Classes/Controller/SearchController.php
typo3/sysext/indexed_search/Classes/Example/PluginHook.php
typo3/sysext/indexed_search/Tests/Unit/Classes/Example/PluginHookTest.php [new file with mode: 0644]

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-82488-HookToModifyResultsBeforeAssignToView.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-82488-HookToModifyResultsBeforeAssignToView.rst
new file mode 100644 (file)
index 0000000..98d4d50
--- /dev/null
@@ -0,0 +1,51 @@
+.. include:: ../../Includes.txt
+
+=======================================================================================
+Feature: #82488 - Possibility to modify the display results before FluidView assignment
+=======================================================================================
+
+See :issue:`82488`
+
+Description
+===========
+
+To manipulate the data of the search results prior to rendering them in the frontend a
+hook has been introduced at the end of the :php:`getDisplayResults()` method, called
+:php:`getDisplayResults_postProc`.
+The hook can modify all data just before it is passed to fluid.
+
+Basic Usage
+===========
+
+Registration of the new hook in :php:``ext_localconf.php`` of your custom extension.
+
+.. code-block:: php
+
+   $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['indexed_search']['pi1_hooks']['getDisplayResults_postProc'] = \Vendor\ExtensionName\Hooks\CustomHook::class;
+
+CustomHook class example :php:``\Vendor\ExtensionName\Hooks\CustomHook``
+
+.. code-block:: php
+
+   <?php
+   declare(strict_types=1);
+   namespace Vendor\ExtensionName\Hooks;
+
+   class CustomHook
+   {
+      /**
+      * @param array $result
+      * @return array
+      */
+       public function getDisplayResults_postProc(array $result): array
+       {
+           if ($result['count'] > 0) {
+               foreach($result['rows'] as $rowIndex => $row) {
+                   $result['rows'][$rowIndex]['description'] = \str_replace('foo', 'bar', $row['description']);
+               }
+           }
+           return $result;
+       }
+   }
+
+.. index:: ext:indexed_search, PHP-API
index e078f4f..5601278 100644 (file)
@@ -345,6 +345,11 @@ class SearchController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControlle
         if (substr($this->searchData['sections'], 0, 2) === 'rl') {
             $result['searchedInSectionInfo'] = LocalizationUtility::translate('result.inSection', 'IndexedSearch') . ' "' . $this->getPathFromPageId(substr($this->searchData['sections'], 4)) . '"';
         }
+
+        if ($hookObj = $this->hookRequest('getDisplayResults_postProc')) {
+            $result = $hookObj->getDisplayResults_postProc($result);
+        }
+
         return $result;
     }
 
index 926b1fd..4a9c4b5 100644 (file)
@@ -44,6 +44,25 @@ class PluginHook
     }
 
     /**
+     * Example of how the content displayed in the result rows can be extended or modified
+     * before the data is assigned to the fluid template as {resultsets}.
+     * The code example replaces all occurrences of the search string with the replacement
+     * string in the description of all rows in the result.
+     *
+     * @param array $result
+     * @return array
+     */
+    public function getDisplayResults_postProc(array $result): array
+    {
+        if ($result['count'] > 0) {
+            foreach ($result['rows'] as $rowIndex => $row) {
+                $result['rows'][$rowIndex]['description'] = \str_replace('foo', 'bar', $row['description']);
+            }
+        }
+        return $result;
+    }
+
+    /**
      * Providing an alternative search algorithm!
      *
      * @param array $sWArr Array of search words
diff --git a/typo3/sysext/indexed_search/Tests/Unit/Classes/Example/PluginHookTest.php b/typo3/sysext/indexed_search/Tests/Unit/Classes/Example/PluginHookTest.php
new file mode 100644 (file)
index 0000000..8c5e215
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+
+namespace TYPO3\CMS\IndexedSearch\Tests\Unit;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\IndexedSearch\Example\PluginHook;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+/**
+ * This class contains unit tests for the indexer
+ */
+class PluginHookTest extends UnitTestCase
+{
+    /**
+     * @var array A backup of registered singleton instances
+     */
+    protected $singletonInstances = [];
+
+    /**
+     * Indexer instance
+     *
+     * @var \TYPO3\CMS\IndexedSearch\Example\PluginHook
+     */
+    protected $subject;
+
+    /**
+     * Sets up the test
+     */
+    protected function setUp()
+    {
+        $this->singletonInstances = GeneralUtility::getSingletonInstances();
+        $this->subject = new PluginHook();
+    }
+
+    /**
+     * @test
+     */
+    public function getDisplayResults_postProcReturnsTheOriginalSearchResultBecauseOfMissingItems()
+    {
+        $searchResult = [
+            'count' => 0,
+            'rows' => []
+        ];
+
+        $result = $this->subject->getDisplayResults_postProc($searchResult);
+        self::assertSame($searchResult, $result);
+    }
+
+    /**
+     * @test
+     */
+    public function getDisplayResults_postProcModifiesTheDescriptionInARowOfSearchResult()
+    {
+        $searchResult = [
+            'count' => 2,
+            'rows' => [
+                ['description' => 'I am a description field with joe and foo.'],
+                ['description' => 'Description will be modified to two bar. foo, bar, joe. ']
+            ]
+        ];
+
+        $expected = [
+            'count' => 2,
+            'rows' => [
+                ['description' => 'I am a description field with joe and bar.'],
+                ['description' => 'Description will be modified to two bar. bar, bar, joe. ']
+            ]
+        ];
+
+        $result = $this->subject->getDisplayResults_postProc($searchResult);
+        self::assertSame($expected, $result);
+    }
+
+    /**
+     * Tear down the tests
+     */
+    protected function tearDown()
+    {
+        GeneralUtility::resetSingletonInstances($this->singletonInstances);
+        unset($this->subject);
+        parent::tearDown();
+    }
+}