Passed
Pull Request — main (#3261)
by Sebastian
48:30 queued 07:03
created

SearchFormViewHelper   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 228
Duplicated Lines 0 %

Test Coverage

Coverage 87.63%

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 17
eloc 95
dl 0
loc 228
ccs 85
cts 97
cp 0.8763
rs 10
c 2
b 0
f 1

10 Methods

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

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

229
        $uriBuilder = /** @scrutinizer ignore-deprecated */ $this->getControllerContext()->getUriBuilder();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
230 29
        $pluginNamespace = $this->getTypoScriptConfiguration()->getSearchPluginNamespace();
231 29
        $suggestUrl = $uriBuilder
232 29
            ->reset()
233 29
            ->setTargetPageUid($pageUid)
234 29
            ->setTargetPageType($this->arguments['suggestPageType'])
235 29
            ->setArguments([$pluginNamespace => ['additionalFilters' => $additionalFilters]])
236 29
            ->build();
237
238
        /* @var UrlHelper $urlService */
239 29
        $urlService = GeneralUtility::makeInstance(UrlHelper::class, $suggestUrl);
240 29
        return $urlService->removeQueryParameter('cHash')->__toString();
0 ignored issues
show
Deprecated Code introduced by
The function ApacheSolrForTypo3\Solr\...:removeQueryParameter() has been deprecated: Will be removed with v12. Use {@link withoutQueryParameter()} instead. ( Ignorable by Annotation )

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

240
        return /** @scrutinizer ignore-deprecated */ $urlService->removeQueryParameter('cHash')->__toString();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
241
    }
242
243
    /**
244
     * @param int|null $pageUid
245
     * @return string
246
     */
247 32
    protected function buildUriFromPageUidAndArguments($pageUid): string
248
    {
249 32
        $uriBuilder = $this->getControllerContext()->getUriBuilder();
0 ignored issues
show
Deprecated Code introduced by
The function TYPO3\CMS\Extbase\Mvc\Co...ontext::getUriBuilder() has been deprecated: since v11, will be removed in v12 ( Ignorable by Annotation )

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

249
        $uriBuilder = /** @scrutinizer ignore-deprecated */ $this->getControllerContext()->getUriBuilder();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
250
        return $uriBuilder
251 32
            ->reset()
252 32
            ->setTargetPageUid((int)$pageUid)
253 32
            ->setTargetPageType($this->arguments['pageType'] ?? 0)
254 32
            ->setNoCache($this->arguments['noCache'] ?? false)
255 32
            ->setArguments($this->arguments['additionalParams'] ?? [])
256 32
            ->setCreateAbsoluteUri($this->arguments['absolute'] ?? false)
257 32
            ->setAddQueryString($this->arguments['addQueryString'] ?? false)
258 32
            ->setArgumentsToBeExcludedFromQueryString($this->arguments['argumentsToBeExcludedFromQueryString'] ?? [])
259 32
            ->setAddQueryStringMethod($this->arguments['addQueryStringMethod'] ?? '')
260 32
            ->setSection($this->arguments['section'] ?? '')
261 32
            ->build();
262
    }
263
}
264