Completed
Branch master (b9fc31)
by Timo
05:19
created

FacetingCommand   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 229
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Test Coverage

Coverage 82.26%

Importance

Changes 0
Metric Value
wmc 26
lcom 1
cbo 10
dl 0
loc 229
ccs 102
cts 124
cp 0.8226
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
C execute() 0 24 8
B renderAvailableFacets() 0 45 6
C renderUsedFacets() 0 75 10
A addFacetingJavascript() 0 14 1
1
<?php
2
namespace ApacheSolrForTypo3\Solr\Plugin\Results;
3
4
/***************************************************************
5
 *  Copyright notice
6
 *
7
 *  (c) 2009-2015 Ingo Renner <[email protected]>
8
 *  All rights reserved
9
 *
10
 *  This script is part of the TYPO3 project. The TYPO3 project is
11
 *  free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 2 of the License, or
14
 *  (at your option) any later version.
15
 *
16
 *  The GNU General Public License can be found at
17
 *  http://www.gnu.org/copyleft/gpl.html.
18
 *
19
 *  This script is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
23
 *
24
 *  This copyright notice MUST APPEAR in all copies of the script!
25
 ***************************************************************/
26
27
use ApacheSolrForTypo3\Solr\Facet\Facet;
28
use ApacheSolrForTypo3\Solr\Facet\FacetRendererFactory;
29
use ApacheSolrForTypo3\Solr\Facet\UsedFacetRenderer;
30
use ApacheSolrForTypo3\Solr\Plugin\CommandPluginBase;
31
use ApacheSolrForTypo3\Solr\Plugin\PluginCommand;
32
use ApacheSolrForTypo3\Solr\Query\LinkBuilder;
33
use ApacheSolrForTypo3\Solr\Search;
34
use TYPO3\CMS\Core\Utility\GeneralUtility;
35
36
/**
37
 * facets view command
38
 *
39
 * @author Ingo Renner <[email protected]>
40
 */
41
class FacetingCommand implements PluginCommand
42
{
43
44
    /**
45
     * Search instance
46
     *
47
     * @var Search
48
     */
49
    protected $search;
50
51
    /**
52
     * Parent plugin
53
     *
54
     * @var Results
55
     */
56
    protected $parentPlugin;
57
58
    /**
59
     * Configuration
60
     *
61
     * @var array
62
     */
63
    protected $configuration;
64
65
    /**
66
     * Facets active: TRUE if any option of any facet has been selected.
67
     *
68
     * @var bool
69
     */
70
    protected $facetsActive = false;
71
72
    /**
73
     * Constructor.
74
     *
75
     * @param CommandPluginBase $parentPlugin Parent plugin object.
76
     */
77 20
    public function __construct(CommandPluginBase $parentPlugin)
78
    {
79 20
        $this->search = GeneralUtility::makeInstance(Search::class);
80
81 20
        $this->parentPlugin = $parentPlugin;
0 ignored issues
show
Documentation Bug introduced by
$parentPlugin is of type object<ApacheSolrForTypo...ugin\CommandPluginBase>, but the property $parentPlugin was declared to be of type object<ApacheSolrForTypo...Plugin\Results\Results>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
82 20
        $this->configuration = $parentPlugin->typoScriptConfiguration;
0 ignored issues
show
Documentation Bug introduced by
It seems like $parentPlugin->typoScriptConfiguration of type object<ApacheSolrForTypo...ypoScriptConfiguration> is incompatible with the declared type array of property $configuration.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
83 20
    }
84
85
    /**
86
     * Executes the command, renders the template subpart markers if faceting
87
     * is activated.
88
     *
89
     * @return array|null Array of faceting markers or null if faceting is deactivated
90
     */
91 20
    public function execute()
92
    {
93 20
        $marker = [];
94
95 20
        if ($this->configuration->getSearchFaceting()
0 ignored issues
show
Bug introduced by
The method getSearchFaceting cannot be called on $this->configuration (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
96 20
            && ($this->search->getNumberOfResults() || $this->configuration->getSearchInitializeWithEmptyQuery() || $this->configuration->getSearchInitializeWithQuery())
0 ignored issues
show
Bug introduced by
The method getSearchInitializeWithEmptyQuery cannot be called on $this->configuration (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
Bug introduced by
The method getSearchInitializeWithQuery cannot be called on $this->configuration (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
97 20
        ) {
98 18
            $marker['subpart_available_facets'] = $this->renderAvailableFacets();
99 18
            $marker['subpart_used_facets'] = $this->renderUsedFacets();
100 18
            $marker['active'] = $this->facetsActive ? '1' : '0';
101 18
            $marker['search_has_results'] = $this->search->getNumberOfResults() ? 1 : 0;
102
103 18
            $this->addFacetingJavascript();
104 18
        }
105
106 20
        if (count($marker) === 0) {
107
            // in case we didn't fill any markers - like when there are no
108
            // search results - we set markers to NULL to signal that we
109
            // want to have the subpart removed completely
110 2
            $marker = null;
111 2
        }
112
113 20
        return $marker;
114
    }
115
116
    /**
117
     * Renders user-selectable facets.
118
     *
119
     * @return string rendered facets subpart
120
     */
121 18
    protected function renderAvailableFacets()
122
    {
123 18
        $facetContent = '';
124
125 18
        $template = clone $this->parentPlugin->getTemplate();
126 18
        $template->workOnSubpart('available_facets');
127
128 18
        $configuredFacets = $this->configuration->getSearchFacetingFacets();
0 ignored issues
show
Bug introduced by
The method getSearchFacetingFacets cannot be called on $this->configuration (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
129
130 18
        $facetRendererFactory = GeneralUtility::makeInstance(
131 18
            FacetRendererFactory::class,
132
            $configuredFacets
133 18
        );
134
        /** @var $facetRendererFactory FacetRendererFactory */
135 18
        foreach ($configuredFacets as $facetName => $facetConfiguration) {
136 18
            $facetName = substr($facetName, 0, -1);
137 18
            $facet = GeneralUtility::makeInstance(Facet::class,
138 18
                $facetName,
139 18
                $facetRendererFactory->getFacetInternalType($facetName)
140 18
            );
141
            /** @var $facet Facet */
142
            if (
143 18
                (isset($facetConfiguration['includeInAvailableFacets']) && $facetConfiguration['includeInAvailableFacets'] == '0')
144 18
                || !$facet->isRenderingAllowed()
145 18
            ) {
146
                // don't render facets that should not be included in available facets
147
                // or that do not meet their requirements to be rendered
148
                continue;
149
            }
150
151 18
            $facetRenderer = $facetRendererFactory->getFacetRendererByFacet($facet);
152 18
            $facetRenderer->setTemplate($template);
153 18
            $facetRenderer->setLinkTargetPageId($this->parentPlugin->getLinkTargetPageId());
154
155 18
            if ($facet->isActive()) {
156 1
                $this->facetsActive = true;
157 1
            }
158
159 18
            $facetContent .= $facetRenderer->renderFacet();
160 18
        }
161
162 18
        $template->addSubpart('single_facet', $facetContent);
163
164 18
        return $template->render();
165
    }
166
167
    /**
168
     * Renders facets selected by the user.
169
     *
170
     * @return string rendered selected facets subpart
171
     */
172 18
    protected function renderUsedFacets()
173
    {
174 18
        $template = clone $this->parentPlugin->getTemplate();
175 18
        $template->workOnSubpart('used_facets');
176
177 18
        $query = $this->search->getQuery();
178
179 18
        $queryLinkBuilder = GeneralUtility::makeInstance(LinkBuilder::class,
180 18
            $this->search->getQuery());
181
        /* @var $queryLinkBuilder LinkBuilder */
182 18
        $queryLinkBuilder->setLinkTargetPageId($this->parentPlugin->getLinkTargetPageId());
183
184
        // URL parameters added to facet URLs may not need to be added to the facets reset URL
185 18
        $facetLinkUrlParameters = $this->configuration->getSearchFacetingFacetLinkUrlParametersAsArray();
0 ignored issues
show
Bug introduced by
The method getSearchFacetingFacetLinkUrlParametersAsArray cannot be called on $this->configuration (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
186 18
        $useForFacetResetLink = $this->configuration->getSearchFacetingFacetLinkUrlParametersUseForFacetResetLinkUrl();
0 ignored issues
show
Bug introduced by
The method getSearchFacetingFacetLi...UseForFacetResetLinkUrl cannot be called on $this->configuration (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
187
188 18
        if (count($facetLinkUrlParameters) > 0 && $useForFacetResetLink) {
189 18
            $addedUrlParameterKeys = array_keys($facetLinkUrlParameters);
190
191 18
            foreach ($addedUrlParameterKeys as $addedUrlParameterKey) {
192 18
                if (GeneralUtility::isFirstPartOfStr($addedUrlParameterKey, 'tx_solr')) {
193
                    $addedUrlParameterKey = substr($addedUrlParameterKey, 8, -1);
194
                    $queryLinkBuilder->addUnwantedUrlParameter($addedUrlParameterKey);
195
                }
196 18
            }
197 18
        }
198
199 18
        $resultParameters = GeneralUtility::_GET('tx_solr');
200 18
        $filterParameters = [];
201 18
        if (isset($resultParameters['filter'])) {
202 1
            $filterParameters = (array)array_map('urldecode',
203 1
                $resultParameters['filter']);
204 1
        }
205
206 18
        $facetsInUse = [];
207 18
        foreach ($filterParameters as $filter) {
208
            // only split by the first ":" to allow the use of colons in the filter value
209 1
            list($filterName, $filterValue) = explode(':', $filter, 2);
210
211 1
            $facetConfiguration = $this->configuration->getSearchFacetingFacetByName($filterName);
0 ignored issues
show
Bug introduced by
The method getSearchFacetingFacetByName cannot be called on $this->configuration (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
212
213
            // don't render facets that should not be included in used facets
214 1
            if (isset($facetConfiguration['includeInUsedFacets']) && $facetConfiguration['includeInUsedFacets'] == '0') {
215
                continue;
216
            }
217
218 1
            $usedFacetRenderer = GeneralUtility::makeInstance(
219 1
                UsedFacetRenderer::class,
220 1
                $filterName,
221 1
                $filterValue,
222 1
                $filter,
223 1
                $this->parentPlugin->getTemplate(),
224
#FIXME usage of $query
225
                $query
226 1
            );
227 1
            $usedFacetRenderer->setLinkTargetPageId($this->parentPlugin->getLinkTargetPageId());
228
229 1
            $facetToRemove = $usedFacetRenderer->render();
230
231 1
            $facetsInUse[] = $facetToRemove;
232 18
        }
233 18
        $template->addLoop('facets_in_use', 'remove_facet', $facetsInUse);
234
235 18
        $template->addVariable('remove_all_facets', [
236 18
            'url' => $queryLinkBuilder->getQueryUrl(['filter' => []]),
237
            'text' => '###LLL:faceting_removeAllFilters###'
238 18
        ]);
239
240 18
        $content = '';
241 18
        if (count($facetsInUse)) {
242 1
            $content = $template->render();
243 1
        }
244
245 18
        return $content;
246
    }
247
248
    /**
249
     * Adds the JavaScript necessary for some of the faceting features;
250
     * folding/unfolding a list of facet options that exceed the configured
251
     * limit of visible options
252
     *
253
     * @return void
254
     */
255 18
    protected function addFacetingJavascript()
256
    {
257 18
        $javascriptManager = $this->parentPlugin->getJavascriptManager();
258
259
        $expansionLabels = '
260
			var tx_solr_facetLabels = {
261 18
				\'showMore\' : \'' . $this->parentPlugin->pi_getLL('faceting_showMore') . '\',
262 18
				\'showFewer\' : \'' . $this->parentPlugin->pi_getLL('faceting_showFewer') . '\'
263
			};
264 18
		';
265 18
        $javascriptManager->addJavascript('tx_solr-facetingExpansionLabels',
266 18
            $expansionLabels);
267 18
        $javascriptManager->loadFile('faceting.limitExpansion');
268 18
    }
269
}
270