Issues (202)

Classes/ViewHelpers/SearchFormViewHelper.php (3 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 35
    /**
54
     * Constructor
55 35
     */
56 35
    public function __construct()
57 35
    {
58
        parent::__construct();
59
        $this->frontendController = $GLOBALS['TSFE'];
60
    }
61
62
    /**
63
     * Initialize arguments.
64 35
     *
65
     * @return void
66 35
     */
67 35
    public function initializeArguments()
68 35
    {
69 35
        parent::initializeArguments();
70 35
        $this->registerTagAttribute('enctype', 'string', 'MIME type with which the form is submitted');
71 35
        $this->registerTagAttribute('method', 'string', 'Transfer type (GET or POST)', false, 'get');
72 35
        $this->registerTagAttribute('name', 'string', 'Name of form');
73
        $this->registerTagAttribute('onreset', 'string', 'JavaScript: On reset of the form');
74 35
        $this->registerTagAttribute('onsubmit', 'string', 'JavaScript: On submit of the form');
75 35
        $this->registerUniversalTagAttributes();
76 35
77 35
        $this->registerArgument('pageUid', 'integer', 'When not set current page is used', false);
78
        $this->registerArgument('additionalFilters', 'array', 'Additional filters', false);
79 35
        $this->registerArgument('additionalParams', 'array', 'Query parameters to be attached to the resulting URI', false, []);
80 35
        $this->registerArgument('pageType', 'integer', 'Type of the target page. See typolink.parameter', false, 0);
81 35
82 35
        $this->registerArgument('noCache', 'boolean', 'Set this to disable caching for the target page. You should not need this.', false, false);
83 35
        $this->registerArgument('noCacheHash', 'boolean', 'Set this to supress the cHash query parameter created by TypoLink. You should not need this.', false, false);
84 35
        $this->registerArgument('section', 'string', 'The anchor to be added to the action URI (only active if $actionUri is not set)', false, '');
85 35
        $this->registerArgument('absolute', 'boolean', 'If set, the URI of the rendered link is absolute', false, false);
86 35
        $this->registerArgument('addQueryString', 'boolean', 'If set, the current query parameters will be kept in the URI', false, false);
87 35
        $this->registerArgument('argumentsToBeExcludedFromQueryString', 'array', 'arguments to be removed from the URI. Only active if $addQueryString = TRUE', false, []);
88 35
        $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
        $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 35
    /**
96
     * Render search form tag
97 35
     *
98 35
     * @return string
99 35
     */
100
    public function render()
101
    {
102 35
        $pageUid = $this->arguments['pageUid'];
103
        if ($pageUid === null && !empty($this->getTypoScriptConfiguration()->getSearchTargetPage())) {
104 35
            $pageUid = $this->getTypoScriptConfiguration()->getSearchTargetPage();
105 35
        }
106 35
107
        $uri = $this->buildUriFromPageUidAndArguments($pageUid);
108 35
109 35
        $this->tag->addAttribute('action', trim($uri));
110
        if ($this->arguments['addSuggestUrl']) {
111
            $this->tag->addAttribute('data-suggest', $this->getSuggestUrl($this->arguments['additionalFilters'], $pageUid));
112 35
        }
113 35
        $this->tag->addAttribute('data-suggest-header', htmlspecialchars($this->arguments['suggestHeader']));
114 35
        $this->tag->addAttribute('accept-charset', $this->frontendController->metaCharset);
115 35
116 35
        // Get search term
117 35
        // @extensionScannerIgnoreLine
118 35
        $this->getTemplateVariableContainer()->add('q', $this->getQueryString());
119
        // @extensionScannerIgnoreLine
120 35
        $this->getTemplateVariableContainer()->add('pageUid', $pageUid);
121
        // @extensionScannerIgnoreLine
122 35
        $this->getTemplateVariableContainer()->add('languageUid', Util::getLanguageUid());
123
        // @extensionScannerIgnoreLine
124
        $this->getTemplateVariableContainer()->add('existingParameters', $this->getExistingSearchParameters());
125
        // @extensionScannerIgnoreLine
126
        $this->getTemplateVariableContainer()->add('addPageAndLanguageId', !$this->getIsSiteManagedSite($pageUid));
127
        $formContent = $this->renderChildren();
128 35
        // @extensionScannerIgnoreLine
129
        $this->getTemplateVariableContainer()->remove('addPageAndLanguageId');
130 35
        // @extensionScannerIgnoreLine
131 35
        $this->getTemplateVariableContainer()->remove('q');
132 2
        // @extensionScannerIgnoreLine
133
        $this->getTemplateVariableContainer()->remove('pageUid');
134 33
        // @extensionScannerIgnoreLine
135
        $this->getTemplateVariableContainer()->remove('languageUid');
136
        // @extensionScannerIgnoreLine
137
        $this->getTemplateVariableContainer()->remove('existingParameters');
138
139
        $this->tag->setContent($formContent);
140
141
        return $this->tag->render();
142 35
    }
143
144 35
    /**
145
     * Get the existing search parameters in an array
146 35
     * Returns an empty array if search.keepExistingParametersForNewSearches is not set
147
     *
148
     * @return array
149 35
     */
150 1
    protected function getExistingSearchParameters()
151 1
    {
152
        $searchParameters = [];
153 1
        if ($this->getTypoScriptConfiguration()->getSearchKeepExistingParametersForNewSearches()) {
154
            $arguments = GeneralUtility::_GPmerged($this->getTypoScriptConfiguration()->getSearchPluginNamespace());
155
            unset($arguments['q'], $arguments['id'], $arguments['L']);
156
            $searchParameters = $this->translateSearchParametersToInputTagAttributes($arguments);
157 35
        }
158
        return $searchParameters;
159
    }
160
161 35
    /**
162
     * Translate the multi-dimensional array of existing arguments into a flat array of name-value pairs for the input tags
163
     *
164
     * @param $arguments
165
     * @param string $nameAttributePrefix
166
     * @return array
167 35
     */
168
    protected function translateSearchParametersToInputTagAttributes($arguments, $nameAttributePrefix = '')
169 35
    {
170 35
        $attributes = [];
171 35
        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);
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