Issues (216)

Classes/ViewHelpers/SearchFormViewHelper.php (4 issues)

1
<?php
2
namespace ApacheSolrForTypo3\Solr\ViewHelpers;
3
4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
 * It is free software; you can redistribute it and/or modify it under
8
 * the terms of the GNU General Public License, either version 2
9
 * of the License, or any later version.
10
 *
11
 * For the full copyright and license information, please read the
12
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
 * The TYPO3 project - inspiring people to share!
15
 */
16
17
use ApacheSolrForTypo3\Solr\System\Url\UrlHelper;
18
use ApacheSolrForTypo3\Solr\System\Util\SiteUtility;
19
use ApacheSolrForTypo3\Solr\Util;
20
use TYPO3\CMS\Core\Utility\GeneralUtility;
21
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
22
23
24
/**
25
 * Class SearchFormViewHelper
26
 *
27
 * @author Frans Saris <[email protected]>
28
 * @author Timo Hund <[email protected]>
29
 */
30
class SearchFormViewHelper extends AbstractSolrFrontendTagBasedViewHelper
31
{
32
33
    /**
34
     * @var string
35
     */
36
    protected $tagName = 'form';
37
38
    /**
39
     * @var TypoScriptFrontendController
40
     */
41
    protected $frontendController;
42
43
    /**
44
     * @var bool
45
     */
46
    protected $escapeChildren = true;
47
48
    /**
49
     * @var bool
50
     */
51
    protected $escapeOutput = false;
52
53 39
    /**
54
     * Constructor
55 39
     */
56 39
    public function __construct()
57 39
    {
58
        parent::__construct();
59
        $this->frontendController = $GLOBALS['TSFE'];
60
    }
61
62
    /**
63
     * Initialize arguments.
64 36
     *
65
     * @return void
66 36
     */
67 36
    public function initializeArguments()
68 36
    {
69 36
        parent::initializeArguments();
70 36
        $this->registerTagAttribute('enctype', 'string', 'MIME type with which the form is submitted');
71 36
        $this->registerTagAttribute('method', 'string', 'Transfer type (GET or POST)', false, 'get');
72 36
        $this->registerTagAttribute('name', 'string', 'Name of form');
73
        $this->registerTagAttribute('onreset', 'string', 'JavaScript: On reset of the form');
74 36
        $this->registerTagAttribute('onsubmit', 'string', 'JavaScript: On submit of the form');
75 36
        $this->registerUniversalTagAttributes();
76 36
77 36
        $this->registerArgument('pageUid', 'integer', 'When not set current page is used', false);
78
        $this->registerArgument('additionalFilters', 'array', 'Additional filters', false);
79 36
        $this->registerArgument('additionalParams', 'array', 'Query parameters to be attached to the resulting URI', false, []);
80 36
        $this->registerArgument('pageType', 'integer', 'Type of the target page. See typolink.parameter', false, 0);
81 36
82 36
        $this->registerArgument('noCache', 'boolean', 'Set this to disable caching for the target page. You should not need this.', false, false);
83 36
        $this->registerArgument('noCacheHash', 'boolean', 'Set this to supress the cHash query parameter created by TypoLink. You should not need this.', false, false);
84 36
        $this->registerArgument('section', 'string', 'The anchor to be added to the action URI (only active if $actionUri is not set)', false, '');
85 36
        $this->registerArgument('absolute', 'boolean', 'If set, the URI of the rendered link is absolute', false, false);
86 36
        $this->registerArgument('addQueryString', 'boolean', 'If set, the current query parameters will be kept in the URI', false, false);
87 36
        $this->registerArgument('argumentsToBeExcludedFromQueryString', 'array', 'arguments to be removed from the URI. Only active if $addQueryString = TRUE', false, []);
88 36
        $this->registerArgument('addQueryStringMethod', 'string', 'Set which parameters will be kept. Only active if $addQueryString = TRUE', false);
89
        $this->registerArgument('addSuggestUrl', 'boolean', 'Indicates if suggestUrl should be rendered or not', false, true);
90 36
        $this->registerArgument('suggestHeader', 'string', 'The header for the top results', false, 'Top Results');
91
        $this->registerArgument('suggestPageType', 'integer', 'The page type that should be used for the suggest', false, 7384);
92
93
    }
94
95
    /**
96
     * Render search form tag
97 39
     *
98
     * @return string
99 39
     */
100 39
    public function render()
101 37
    {
102
        $pageUid = $this->arguments['pageUid'];
103
        if ($pageUid === null && !empty($this->getTypoScriptConfiguration()->getSearchTargetPage())) {
104 39
            $pageUid = $this->getTypoScriptConfiguration()->getSearchTargetPage();
105
        }
106 39
107 39
        $uri = $this->buildUriFromPageUidAndArguments($pageUid);
108 36
109
        $this->tag->addAttribute('action', trim($uri));
110 39
        if ($this->arguments['addSuggestUrl']) {
111 39
            $this->tag->addAttribute('data-suggest', $this->getSuggestUrl($this->arguments['additionalFilters'], $pageUid));
112
        }
113
        $this->tag->addAttribute('data-suggest-header', htmlspecialchars($this->arguments['suggestHeader']));
114 39
        $this->tag->addAttribute('accept-charset', $this->frontendController->metaCharset);
115 39
116 39
        // Get search term
117 39
        // @extensionScannerIgnoreLine
118 39
        $this->getTemplateVariableContainer()->add('q', $this->getQueryString());
119 39
        // @extensionScannerIgnoreLine
120 39
        $this->getTemplateVariableContainer()->add('pageUid', $pageUid);
121
        // @extensionScannerIgnoreLine
122 39
        $this->getTemplateVariableContainer()->add('languageUid', Util::getLanguageUid());
123
        // @extensionScannerIgnoreLine
124 39
        $this->getTemplateVariableContainer()->add('existingParameters', $this->getExistingSearchParameters());
125
        // @extensionScannerIgnoreLine
126
        $this->getTemplateVariableContainer()->add('addPageAndLanguageId', !$this->getIsSiteManagedSite($pageUid));
127
        $formContent = $this->renderChildren();
128
        // @extensionScannerIgnoreLine
129
        $this->getTemplateVariableContainer()->remove('addPageAndLanguageId');
130 36
        // @extensionScannerIgnoreLine
131
        $this->getTemplateVariableContainer()->remove('q');
132 36
        // @extensionScannerIgnoreLine
133
        $this->getTemplateVariableContainer()->remove('pageUid');
134
        // @extensionScannerIgnoreLine
135
        $this->getTemplateVariableContainer()->remove('languageUid');
136
        // @extensionScannerIgnoreLine
137
        $this->getTemplateVariableContainer()->remove('existingParameters');
138 39
139
        $this->tag->setContent($formContent);
140 39
141 39
        return $this->tag->render();
142 5
    }
143
144 34
    /**
145
     * Get the existing search parameters in an array
146
     * Returns an empty array if search.keepExistingParametersForNewSearches is not set
147
     *
148
     * @return array
149
     */
150
    protected function getExistingSearchParameters()
151
    {
152 36
        $searchParameters = [];
153
        if ($this->getTypoScriptConfiguration()->getSearchKeepExistingParametersForNewSearches()) {
154 36
            $arguments = GeneralUtility::_GPmerged('tx_solr');
155 36
            unset($arguments['q'], $arguments['id'], $arguments['L']);
156 36
            $searchParameters = $this->translateSearchParametersToInputTagAttributes($arguments);
157 36
        }
158
        return $searchParameters;
159
    }
160
161
    /**
162
     * Translate the multi-dimensional array of existing arguments into a flat array of name-value pairs for the input tags
163
     *
164 39
     * @param $arguments
165
     * @param string $nameAttributePrefix
166 39
     * @return array
167 39
     */
168 39
    protected function translateSearchParametersToInputTagAttributes($arguments, $nameAttributePrefix = '')
169
    {
170
        $attributes = [];
171
        foreach ($arguments as $key => $value) {
172
            $name = $nameAttributePrefix . '[' . $key . ']';
173
            if (is_array($value)) {
174
                $attributes = array_merge(
175
                    $attributes,
176
                    $this->translateSearchParametersToInputTagAttributes($value, $name)
177
                );
178
            } else {
179
                $attributes[$name] = $value;
180
            }
181
        }
182
        return $attributes;
183
    }
184
185
    /**
186
     * When a site is managed with site management the language and the id are encoded in the path segment of the url.
187
     * When no speaking urls are active (e.g. with TYPO3 8 and no realurl) this information is passed as query parameter
188
     * and would get lost when it is only part of the query arguments in the action parameter of the form.
189
     *
190
     * @return boolean
191
     */
192
    protected function getIsSiteManagedSite($pageId)
193
    {
194
        return SiteUtility::getIsSiteManagedSite($pageId);
195
    }
196
197
    /**
198
     * @return \TYPO3Fluid\Fluid\Core\Variables\VariableProviderInterface
199
     */
200
    protected function getTemplateVariableContainer()
201
    {
202
        return $this->templateVariableContainer;
203
    }
204
205
    /**
206
     * @return string
207
     */
208
    protected function getQueryString()
209
    {
210
        $resultSet = $this->getSearchResultSet();
211
        if ($resultSet === null) {
212
            return '';
213
        }
214
        return trim($this->getSearchResultSet()->getUsedSearchRequest()->getRawUserQuery());
215
    }
216
217
    /**
218
     * @param NULL|array $additionalFilters
219
     * @param int $pageUid
220
     * @return string
221
     */
222
    protected function getSuggestUrl($additionalFilters, $pageUid)
223
    {
224
        $uriBuilder = $this->getControllerContext()->getUriBuilder();
225
        $pluginNamespace = $this->getTypoScriptConfiguration()->getSearchPluginNamespace();
226
        $suggestUrl = $uriBuilder->reset()->setTargetPageUid($pageUid)->setTargetPageType($this->arguments['suggestPageType'])->setUseCacheHash(false)->setArguments([$pluginNamespace => ['additionalFilters' => $additionalFilters]])->build();
0 ignored issues
show
The call to TYPO3\CMS\Extbase\Mvc\We...lder::setUseCacheHash() has too many arguments starting with false. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

226
        $suggestUrl = $uriBuilder->reset()->setTargetPageUid($pageUid)->setTargetPageType($this->arguments['suggestPageType'])->/** @scrutinizer ignore-call */ setUseCacheHash(false)->setArguments([$pluginNamespace => ['additionalFilters' => $additionalFilters]])->build();

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
227
228
        $urlService = GeneralUtility::makeInstance(UrlHelper::class, $suggestUrl);
0 ignored issues
show
$suggestUrl of type string is incompatible with the type array|array<mixed,mixed> expected by parameter $constructorArguments of TYPO3\CMS\Core\Utility\G...Utility::makeInstance(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

228
        $urlService = GeneralUtility::makeInstance(UrlHelper::class, /** @scrutinizer ignore-type */ $suggestUrl);
Loading history...
229
        $suggestUrl = $urlService->removeQueryParameter('cHash')->getUrl();
230
231
        return $suggestUrl;
232
    }
233
234
    /**
235
     * @param int|null $pageUid
236
     * @return string
237
     */
238
    protected function buildUriFromPageUidAndArguments($pageUid): string
239
    {
240
        $uriBuilder = $this->getControllerContext()->getUriBuilder();
241
        $uri = $uriBuilder
242
            ->reset()
243
            ->setTargetPageUid($pageUid)
0 ignored issues
show
It seems like $pageUid can also be of type null; however, parameter $targetPageUid of TYPO3\CMS\Extbase\Mvc\We...der::setTargetPageUid() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

243
            ->setTargetPageUid(/** @scrutinizer ignore-type */ $pageUid)
Loading history...
244
            ->setTargetPageType($this->arguments['pageType'] ?? 0)
245
            ->setNoCache($this->arguments['noCache'] ?? false)
246
            ->setUseCacheHash(!$this->arguments['noCacheHash'])
0 ignored issues
show
The call to TYPO3\CMS\Extbase\Mvc\We...lder::setUseCacheHash() has too many arguments starting with ! $this->arguments['noCacheHash']. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

246
            ->/** @scrutinizer ignore-call */ setUseCacheHash(!$this->arguments['noCacheHash'])

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
247
            ->setArguments($this->arguments['additionalParams'] ?? [])
248
            ->setCreateAbsoluteUri($this->arguments['absolute'] ?? false)
249
            ->setAddQueryString($this->arguments['addQueryString'] ?? false)
250
            ->setArgumentsToBeExcludedFromQueryString($this->arguments['argumentsToBeExcludedFromQueryString'] ?? [])
251
            ->setAddQueryStringMethod($this->arguments['addQueryStringMethod'] ?? '')
252
            ->setSection($this->arguments['section'] ?? '')
253
            ->build();
254
        return $uri;
255
    }
256
}
257