[BUGFIX] Fix indexing of pages using route enhancers 83/58983/17
authorAlexander Grein <alexander.grein@gmail.com>
Thu, 29 Nov 2018 14:23:54 +0000 (15:23 +0100)
committerBenni Mack <benni@typo3.org>
Fri, 1 Mar 2019 19:25:22 +0000 (20:25 +0100)
Because of pages using route enhancers do not use cHash in most cases,
it is necessary to add the static arguments of the page to generate the
phash values used by indexed_search.

For administration of the indexed pages, the static arguments of the page
are stored in the index_phash table as well, which makes enhancing inevitable.

Resolves: #86994
Releases: master, 9.5
Change-Id: I2e0f09a782481b024ef3fdb6efd81c22fb2fddc3
Reviewed-on: https://review.typo3.org/c/58983
Tested-by: Alexander Grein <alexander.grein@gmail.com>
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Hendrik Helmken <h.helmken@atlantismedia.de>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Alexander Grein <alexander.grein@gmail.com>
Reviewed-by: Hendrik Helmken <h.helmken@atlantismedia.de>
Reviewed-by: Benni Mack <benni@typo3.org>
typo3/sysext/core/Documentation/Changelog/9.5.x/Important-86994-IndexedSearchWithRouteEnhancers.rst [new file with mode: 0644]
typo3/sysext/indexed_search/Classes/Controller/SearchController.php
typo3/sysext/indexed_search/Classes/Domain/Repository/AdministrationRepository.php
typo3/sysext/indexed_search/Classes/Indexer.php
typo3/sysext/indexed_search/Resources/Private/Language/locallang.xlf
typo3/sysext/indexed_search/Resources/Private/Templates/Administration/Pages.html
typo3/sysext/indexed_search/Resources/Private/Templates/Administration/Statistic.html
typo3/sysext/indexed_search/ext_tables.sql

diff --git a/typo3/sysext/core/Documentation/Changelog/9.5.x/Important-86994-IndexedSearchWithRouteEnhancers.rst b/typo3/sysext/core/Documentation/Changelog/9.5.x/Important-86994-IndexedSearchWithRouteEnhancers.rst
new file mode 100644 (file)
index 0000000..c68c965
--- /dev/null
@@ -0,0 +1,21 @@
+.. include:: ../../Includes.txt
+
+======================================================================
+Important: #86994 - Indexed Search indexes pages using route enhancers
+======================================================================
+
+See :issue:`86994`
+
+Description
+===========
+
+Because of pages that use route enhancers do not use `cHash` functionality in most cases, it is necessary to add the
+static arguments of the indexed page to generate the phash values used by `indexed_search`.
+
+For administration of the indexed pages, the static arguments of the page needs to be stored in the `index_phash`
+database table as well, which makes there enhancing inevitable.
+
+In order to make indexed search work with Site Handling, update database schema using the Database Analyzer in maintenance
+module to add the necessary database field. Once done, the search index needs to be rebuilt.
+
+.. index:: Backend, Database, Frontend, ext:indexed_search
index c2d30ab..f3e0491 100644 (file)
@@ -539,7 +539,8 @@ class SearchController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControlle
                     'cHashParams' => $row['cHashParams'],
                     'data_page_type' => $row['data_page_type'],
                     'data_page_mp' => $pathMP,
-                    'sys_language_uid' => $row['sys_language_uid']
+                    'sys_language_uid' => $row['sys_language_uid'],
+                    'static_page_arguments' => $row['static_page_arguments']
                 ]
             );
 
@@ -1330,6 +1331,9 @@ class SearchController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControlle
         $pageLanguage = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'contentId', 0);
         // Parameters for link
         $urlParameters = (array)unserialize($row['cHashParams']);
+        if ($row['static_page_arguments'] !== null) {
+            $urlParameters = array_replace_recursive($urlParameters, json_decode($row['static_page_arguments'], true));
+        }
         // Add &type and &MP variable:
         if ($row['data_page_mp']) {
             $urlParameters['MP'] = $row['data_page_mp'];
index 0b5b455..ec8227b 100644 (file)
@@ -356,6 +356,7 @@ class AdministrationRepository
 
         while ($row = $res->fetch()) {
             $this->addAdditionalInformation($row);
+            $row['static_page_arguments'] = $row['static_page_arguments'] ? json_decode($row['static_page_arguments'], true) : null;
             $result[] = $row;
 
             if ($row['pcount'] > 1) {
@@ -445,6 +446,7 @@ class AdministrationRepository
     {
         $grListRec = $this->getGrlistRecord($row['phash']);
         $unserializedCHashParams = unserialize($row['cHashParams']);
+        $row['static_page_arguments'] = $row['static_page_arguments'] ? json_decode($row['static_page_arguments'], true) : null;
 
         $row['numberOfWords'] = $this->getNumberOfWords($row['phash']);
         $row['numberOfSections'] = $this->getNumberOfSections($row['phash']);
index c4b17cd..2b87b13 100644 (file)
@@ -14,12 +14,14 @@ namespace TYPO3\CMS\IndexedSearch;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
 use TYPO3\CMS\Core\Context\Context;
 use TYPO3\CMS\Core\Context\LanguageAspect;
 use TYPO3\CMS\Core\Core\Environment;
 use TYPO3\CMS\Core\Database\Connection;
 use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Routing\PageArguments;
 use TYPO3\CMS\Core\TimeTracker\TimeTracker;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\HttpUtility;
@@ -180,6 +182,8 @@ class Indexer
     public $indexExternalUrl_content = '';
 
     /**
+     * cHash params array
+     *
      * @var array
      */
     public $cHashParams = [];
@@ -284,9 +288,19 @@ class Indexer
                             // MP variable, if any (Mount Points)
                             // Group list
                             $this->conf['gr_list'] = implode(',', GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('frontend.user', 'groupIds', [0, -1]));
-                            $this->conf['cHash'] = $pObj->cHash;
                             // cHash string for additional parameters
+                            $this->conf['cHash'] = $pObj->cHash;
+                            // cHash array with additional parameters
                             $this->conf['cHash_array'] = $pObj->cHash_array;
+                            // page arguments array
+                            $this->conf['staticPageArguments'] = [];
+                            /** @var PageArguments $pageArguments */
+                            if ($GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
+                                $pageArguments = $GLOBALS['TYPO3_REQUEST']->getAttribute('routing', null);
+                                if ($pageArguments instanceof PageArguments) {
+                                    $this->conf['staticPageArguments'] = $pageArguments->getStaticArguments();
+                                }
+                            }
                             // Array of the additional parameters
                             $this->conf['crdate'] = $pObj->page['crdate'];
                             // The creation date of the TYPO3 page
@@ -1433,6 +1447,7 @@ class Indexer
             'phash' => $this->hash['phash'],
             'phash_grouping' => $this->hash['phash_grouping'],
             'cHashParams' => serialize($this->cHashParams),
+            'static_page_arguments' => json_encode($this->conf['staticPageArguments']),
             'contentHash' => $this->content_md5h,
             'data_page_id' => $this->conf['id'],
             'data_page_type' => $this->conf['type'],
@@ -2213,7 +2228,8 @@ class Indexer
             'type' => (int)$this->conf['type'],
             'sys_lang' => (int)$this->conf['sys_language_uid'],
             'MP' => (string)$this->conf['MP'],
-            'cHash' => $this->cHashParams
+            'cHash' => $this->cHashParams,
+            'staticPageArguments' => $this->conf['staticPageArguments'],
         ];
         // Set grouping hash (Identifies a "page" combined of id, type, language, mountpoint and cHash parameters):
         $this->hash['phash_grouping'] = IndexedSearchUtility::md5inthash(serialize($hArray));
index 8802020..c355337 100644 (file)
@@ -366,6 +366,9 @@ All search words are converted to lowercase.
                        <trans-unit id="field.cHash">
                                <source>Chash</source>
                        </trans-unit>
+                       <trans-unit id="field.staticPageArguments">
+                               <source>Static Page Arguments</source>
+                       </trans-unit>
                        <trans-unit id="field.count">
                                <source>Count</source>
                        </trans-unit>
index b0607ef..bdd2b93 100644 (file)
@@ -21,6 +21,7 @@
                                        <th><f:translate key="field.sub" /></th>
                                        <th><f:translate key="field.language" /></th>
                                        <th><f:translate key="field.cHash" /></th>
+                                       <th><f:translate key="field.staticPageArguments" /></th>
                                        <th><f:translate key="field.pHash" /></th>
                                </tr>
                        </thead>
                                                        </f:for>
                                                </f:if>
                                        </td>
+                                       <td>
+                                               <f:if condition="{data.static_page_arguments}">
+                                                       <f:for each="{data.static_page_arguments}" as="value" key="key">
+                                                               {key}={value}<br>
+                                                       </f:for>
+                                               </f:if>
+                                       </td>
                                        <td>{data.phash}</td>
                                </tr>
                        </f:for>
index 0fda46a..a19b18e 100644 (file)
                                                        <f:then>
                                                                <f:for each="{line.lines}" as="l" iteration="i">
                                                                        <tr>
-                                                                               <f:then>
-                                                                                       <td class="nowrap">
-                                                                                               {line.HTML -> f:format.raw()}
-                                                                                               <f:if condition="{i.index} == 0"> {line.row.title}</f:if>
-                                                                                       </td>
-                                                                                       <td>
-                                                                                               <a href="{f:uri.action(action:'deleteIndexedItem',arguments:'{id:l.phash,depth:depth,mode:mode}')}" title="{f:translate(key:'administration.removeEntry')}">
-                                                                                                       <core:icon identifier="actions-edit-delete" />
-                                                                                               </a>
-                                                                                       </td>
-                                                                                       <td>
-                                                                                               <f:image src="{l.icon}" />
-                                                                                               <f:link.action action="statisticDetails" arguments="{pageHash:l.phash}">{l.item_title}</f:link.action>
-                                                                                       </td>
-                                                                                       <f:switch expression="{mode}">
-                                                                                               <f:case value="content">
-                                                                                                       <td>
-                                                                                                               {l.fulltextData.fulltextdata}
-                                                                                                       </td>
-                                                                                                       <f:if condition="{extensionConfiguration.useMysqlFulltext} == false">
-                                                                                                               <td>
-                                                                                                                       <f:for each="{l.allWords}" as="w">
-                                                                                                                               {w}
-                                                                                                                       </f:for>
-                                                                                                                       <br><br>
-                                                                                                                       <em>{f:translate(key:'administration.statistics.count')}: {f:count(subject:l.allWords)}</em>
-                                                                                                               </td>
-                                                                                                       </f:if>
-                                                                                               </f:case>
-                                                                                               <f:defaultCase>
-                                                                                                       <f:if condition="{extensionConfiguration.useMysqlFulltext} == false">
-                                                                                                               <td>{l.wordCount}</td>
-                                                                                                       </f:if>
-                                                                                                       <td>
-                                                                                                               <f:format.bytes decimals="1">{l.item_size}</f:format.bytes>
-                                                                                                       </td>
+                                                                               <td class="nowrap">
+                                                                                       {line.HTML -> f:format.raw()}
+                                                                                       <f:if condition="{i.index} == 0"> {line.row.title}</f:if>
+                                                                               </td>
+                                                                               <td>
+                                                                                       <a href="{f:uri.action(action:'deleteIndexedItem',arguments:'{id:l.phash,depth:depth,mode:mode}')}" title="{f:translate(key:'administration.removeEntry')}">
+                                                                                               <core:icon identifier="actions-edit-delete" />
+                                                                                       </a>
+                                                                               </td>
+                                                                               <td>
+                                                                                       <f:image src="{l.icon}" />
+                                                                                       <f:link.action action="statisticDetails" arguments="{pageHash:l.phash}">{l.item_title}</f:link.action>
+                                                                               </td>
+                                                                               <f:switch expression="{mode}">
+                                                                                       <f:case value="content">
+                                                                                               <td>
+                                                                                                       {l.fulltextData.fulltextdata}
+                                                                                               </td>
+                                                                                               <f:if condition="{extensionConfiguration.useMysqlFulltext} == false">
                                                                                                        <td>
-                                                                                                               <is:format.dateTime>{l.tstamp}</is:format.dateTime>
+                                                                                                               <f:for each="{l.allWords}" as="w">
+                                                                                                                       {w}
+                                                                                                               </f:for>
+                                                                                                               <br><br>
+                                                                                                               <em>{f:translate(key:'administration.statistics.count')}: {f:count(subject:l.allWords)}</em>
                                                                                                        </td>
-                                                                                               </f:defaultCase>
-                                                                                       </f:switch>
-                                                                               </f:then>
+                                                                                               </f:if>
+                                                                                       </f:case>
+                                                                                       <f:defaultCase>
+                                                                                               <f:if condition="{extensionConfiguration.useMysqlFulltext} == false">
+                                                                                                       <td>{l.wordCount}</td>
+                                                                                               </f:if>
+                                                                                               <td>
+                                                                                                       <f:format.bytes decimals="1">{l.item_size}</f:format.bytes>
+                                                                                               </td>
+                                                                                               <td>
+                                                                                                       <is:format.dateTime>{l.tstamp}</is:format.dateTime>
+                                                                                               </td>
+                                                                                       </f:defaultCase>
+                                                                               </f:switch>
                                                                        </tr>
                                                                </f:for>
                                                        </f:then>
index 676da10..0b06b01 100644 (file)
@@ -6,6 +6,7 @@ CREATE TABLE index_phash (
   phash int(11) DEFAULT '0' NOT NULL,
   phash_grouping int(11) DEFAULT '0' NOT NULL,
   cHashParams blob,
+  static_page_arguments blob,
   data_filename varchar(1024) DEFAULT '' NOT NULL,
   data_page_id int(11) unsigned DEFAULT '0' NOT NULL,
   data_page_type int(11) unsigned DEFAULT '0' NOT NULL,