PageRenderTime 48ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/solr/classes/facet/class.tx_solr_facet_simplefacetrenderer.php

https://github.com/hkremer/Publieke-Omroep-Typo3
PHP | 391 lines | 174 code | 60 blank | 157 comment | 21 complexity | 75371683098fd63dcda029576ff7d45f MD5 | raw file
  1. <?php
  2. /***************************************************************
  3. * Copyright notice
  4. *
  5. * (c) 2010-2011 Markus Goldbach <markus.goldbach@dkd.de>
  6. * All rights reserved
  7. *
  8. * This script is part of the TYPO3 project. The TYPO3 project is
  9. * free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * The GNU General Public License can be found at
  15. * http://www.gnu.org/copyleft/gpl.html.
  16. *
  17. * This script is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * This copyright notice MUST APPEAR in all copies of the script!
  23. ***************************************************************/
  24. /**
  25. * Default facet renderer.
  26. *
  27. * @author Markus Goldbach <markus.goldbach@dkd.de>
  28. */
  29. class tx_solr_facet_SimpleFacetRenderer implements tx_solr_FacetRenderer {
  30. /**
  31. * The facet's name as configured in TypoScript.
  32. *
  33. * @var string
  34. */
  35. protected $facetName;
  36. /**
  37. * The facet's TypoScript configuration.
  38. *
  39. * @var string
  40. */
  41. protected $facetConfiguration;
  42. /**
  43. * The facet options the user can select from.
  44. *
  45. * @var array
  46. */
  47. protected $facetOptions = array();
  48. /**
  49. * A cObject used to render things like the facet options.
  50. *
  51. * @var tslib_cObj
  52. */
  53. protected $contentObject;
  54. /**
  55. * Template engine to replace template markers with their values.
  56. *
  57. * @var tx_solr_Template
  58. */
  59. protected $template;
  60. /**
  61. * The query which is going to be sent to Solr when a user selects a facet.
  62. *
  63. * @var tx_solr_Query
  64. */
  65. protected $query;
  66. /**
  67. * Constructor
  68. *
  69. * @param string $facetName The facet's name
  70. * @param array $facetOptions The facet's options.
  71. * @param array $facetConfiguration The facet's TypoScript configuration.
  72. * @param tx_solr_Template $template Template to use to render the facet
  73. * @param tx_solr_Query $query Query instance used to build links.
  74. */
  75. public function __construct($facetName, array $facetOptions, array $facetConfiguration, tx_solr_Template $template, tx_solr_Query $query) {
  76. $this->facetName = $facetName;
  77. $this->facetOptions = $facetOptions;
  78. $this->facetConfiguration = $facetConfiguration;
  79. $this->contentObject = t3lib_div::makeInstance('tslib_cObj');
  80. $this->query = $query;
  81. $this->template = clone $template;
  82. }
  83. /**
  84. * Sets the link target page Id for links generated by the query linking
  85. * methods.
  86. *
  87. * @param integer $pageId The link target page Id.
  88. */
  89. public function setLinkTargetPageId($pageId) {
  90. $this->query->setLinkTargetPageId(intval($pageId));
  91. }
  92. /**
  93. * Renders the complete facet.
  94. *
  95. * @see tx_solr_FacetRenderer::render()
  96. * @return string Rendered HTML representing the facet.
  97. */
  98. public function render() {
  99. $facetOptionLinks = array();
  100. $solrConfiguration = tx_solr_Util::getSolrConfiguration();
  101. $this->template->workOnSubpart('single_facet_option');
  102. $i = 0;
  103. foreach ($this->facetOptions as $facetOption => $facetOptionResultCount) {
  104. if ($facetOption == '_empty_') {
  105. // TODO - for now we don't handle facet missing.
  106. continue;
  107. }
  108. $facetText = $this->renderOption($facetOption);
  109. $facetLink = $this->buildAddFacetLink(
  110. $facetText,
  111. $this->facetName . ':' . $facetOption
  112. );
  113. $facetLinkUrl = $this->buildAddFacetUrl(
  114. $this->facetName . ':' . $facetOption
  115. );
  116. $facetHidden = '';
  117. if (++$i > $solrConfiguration['search.']['faceting.']['limit']) {
  118. $facetHidden = 'tx-solr-facet-hidden';
  119. }
  120. $facetSelected = $this->isSelectedFacetOption($facetOption);
  121. // negating the facet option links to remove a filter
  122. if ($this->facetConfiguration['selectingSelectedFacetOptionRemovesFilter']
  123. && $facetSelected) {
  124. $facetLink = $this->buildRemoveFacetLink(
  125. $facetText,
  126. $this->facetName . ':' . $facetOption
  127. );
  128. $facetLinkUrl = $this->buildRemoveFacetUrl(
  129. $this->facetName . ':' . $facetOption
  130. );
  131. }
  132. if ($this->facetConfiguration['singleOptionMode']) {
  133. $facetLink = $this->buildReplaceFacetLink(
  134. $facetText,
  135. $this->facetName . ':' . $facetOption
  136. );
  137. $facetLinkUrl = $this->buildReplaceFacetUrl(
  138. $this->facetName . ':' . $facetOption
  139. );
  140. }
  141. $facetOptionLinks[] = array(
  142. 'hidden' => $facetHidden,
  143. 'link' => $facetLink,
  144. 'url' => $facetLinkUrl,
  145. 'text' => $facetText,
  146. 'value' => $facetOption,
  147. 'count' => $facetOptionResultCount,
  148. 'selected' => $facetSelected ? '1' : '0'
  149. );
  150. }
  151. $this->template->addLoop('facet_links', 'facet_link', $facetOptionLinks);
  152. return $this->template->render();
  153. }
  154. /**
  155. * Renders a single facet option link according to the rendering
  156. * instructions that may have been configured.
  157. *
  158. * @param string $option The facet option's raw string value.
  159. * @return string The facet option rendered according to rendering instructions if available
  160. */
  161. protected function renderOption($option) {
  162. $renderedFacetOption = $option;
  163. if (isset($this->facetConfiguration['renderingInstruction'])) {
  164. // TODO provide a data field with information about whether a facet option is selected, and pssibly all information from the renderOptions method so that one can use that with TS
  165. $this->contentObject->start(array('optionValue' => $option));
  166. $renderedFacetOption = $this->contentObject->cObjGetSingle(
  167. $this->facetConfiguration['renderingInstruction'],
  168. $this->facetConfiguration['renderingInstruction.']
  169. );
  170. }
  171. return $renderedFacetOption;
  172. }
  173. /**
  174. * Checks whether a given facet has been selected by the user by checking
  175. * the GET values in the URL.
  176. *
  177. * @param string $facetOptionValue Concret facet filter value to check whether it's selected.
  178. */
  179. protected function isSelectedFacetOption($facetOptionValue) {
  180. $isSelectedOption = FALSE;
  181. $resultParameters = t3lib_div::_GET('tx_solr');
  182. $filterParameters = array();
  183. if (isset($resultParameters['filter'])) {
  184. $filterParameters = (array) array_map('urldecode', $resultParameters['filter']);
  185. }
  186. $facetsInUse = array();
  187. foreach ($filterParameters as $filter) {
  188. list($filterName, $filterValue) = explode(':', $filter);
  189. if ($filterName == $this->facetName && $filterValue == $facetOptionValue) {
  190. $isSelectedOption = TRUE;
  191. break;
  192. }
  193. }
  194. return $isSelectedOption;
  195. }
  196. /**
  197. * Creates a link tag to add a facet to a search result.
  198. *
  199. * @param string $linkText The link text
  200. * @param string $facetToAdd A filter string to be used as a link parameter
  201. * @return string Html link tag to add a facet to a search result
  202. */
  203. protected function buildAddFacetLink($linkText, $facetToAdd) {
  204. $filterParameters = $this->addFacetAndEncodeFilterParameters($facetToAdd);
  205. return $this->query->getQueryLink($linkText, array('filter' => $filterParameters));
  206. }
  207. /**
  208. * Create only the url to add a facet to a search result.
  209. *
  210. * @param string $facetToAdd A filter string to be used as a link parameter
  211. * @return string Url to a a facet to a search result
  212. */
  213. protected function buildAddFacetUrl($facetToAdd) {
  214. $filterParameters = $this->addFacetAndEncodeFilterParameters($facetToAdd);
  215. return $this->query->getQueryUrl(array('filter' => $filterParameters));
  216. }
  217. /**
  218. * Returns a link tag with a link to remove a given facet from the search result array.
  219. *
  220. * @param string $linkText link text
  221. * @param string $facetToRemove A filter string to be removed from the link parameters
  222. * @return string Html tag with link to remove a facet
  223. */
  224. protected function buildRemoveFacetLink($linkText, $facetToRemove) {
  225. $filterParameters = $this->removeFacetAndEncodeFilterParameters($facetToRemove);
  226. return $this->query->getQueryLink($linkText, array('filter' => $filterParameters));
  227. }
  228. /**
  229. * Build the url to remove a facet from a search result.
  230. *
  231. * @param string $facetToRemove A filter string to be removed from the link parameters
  232. * @return string Url to remove a facet
  233. */
  234. protected function buildRemoveFacetUrl($facetToRemove) {
  235. $filterParameters = $this->removeFacetAndEncodeFilterParameters($facetToRemove);
  236. return $this->query->getQueryUrl(array('filter' => $filterParameters));
  237. }
  238. /**
  239. * Returns a link tag with a link to a given facet from the search result array.
  240. *
  241. * @param string $linkText link text
  242. * @param string $facetToReplace A filter string to use in the link parameters
  243. * @return string Html tag with link to remove a facet
  244. */
  245. protected function buildReplaceFacetLink($linkText, $facetToReplace) {
  246. $filterParameters = $this->replaceFacetAndEncodeFilterParameters($facetToReplace);
  247. return $this->query->getQueryLink($linkText, array('filter' => $filterParameters));
  248. }
  249. /**
  250. * Builds the url to a facet from a search result.
  251. *
  252. * @param string $facetToReplace A filter string to use in the link parameters
  253. * @return string Url to remooce a facet
  254. */
  255. protected function buildReplaceFacetUrl($facetToReplace) {
  256. $filterParameters = $this->replaceFacetAndEncodeFilterParameters($facetToReplace);
  257. return $this->query->getQueryUrl(array('filter' => $filterParameters));
  258. }
  259. /**
  260. * Retrieves the filter parmeters from the url and adds an additional facet
  261. * to create a link to add additional facets to a search result.
  262. *
  263. * @param string $facetToAdd Facet filter to add to the filter parameters
  264. * @return array An array of filter parameters
  265. */
  266. protected function addFacetAndEncodeFilterParameters($facetToAdd) {
  267. $solrConfiguration = tx_solr_Util::getSolrConfiguration();
  268. $resultParameters = t3lib_div::_GPmerged('tx_solr');
  269. $filterParameters = array();
  270. if (isset($resultParameters['filter'])
  271. && !$solrConfiguration['search.']['faceting.']['singleFacetMode']) {
  272. $filterParameters = array_map('urldecode', $resultParameters['filter']);
  273. }
  274. $filterParameters[] = $facetToAdd;
  275. $filterParameters = array_unique($filterParameters);
  276. $filterParameters = array_map('urlencode', $filterParameters);
  277. return $filterParameters;
  278. }
  279. /**
  280. * Removes a facet from to filter query.
  281. *
  282. * @param string $facetToRemove Facet filter to remove from the filter parameters
  283. * @return array An array of filter parameters
  284. */
  285. protected function removeFacetAndEncodeFilterParameters($facetToRemove) {
  286. $resultParameters = t3lib_div::_GPmerged('tx_solr');
  287. // urlencode the array to get the original representation
  288. $filterParameters = array_values((array) array_map('urldecode', $resultParameters['filter']));
  289. $filterParameters = array_unique($filterParameters);
  290. $indexToRemove = array_search($facetToRemove, $filterParameters);
  291. if ($indexToRemove !== FALSE) {
  292. unset($filterParameters[$indexToRemove]);
  293. }
  294. $filterParameters = array_map('urlencode', $filterParameters);
  295. return $filterParameters;
  296. }
  297. /**
  298. * Replaces a facet in a filter query.
  299. *
  300. * @param string $facetToReplace Facet filter to replace in the filter parameters
  301. * @return array Array of filter parameters
  302. */
  303. protected function replaceFacetAndEncodeFilterParameters($facetToReplace) {
  304. $resultParameters = t3lib_div::_GPmerged('tx_solr');
  305. // urlencode the array to get the original representation
  306. $filterParameters = array_values((array) array_map('urldecode', $resultParameters['filter']));
  307. $filterParameters = array_unique($filterParameters);
  308. // find the currently used option for this facet
  309. $indexToReplace = FALSE;
  310. foreach ($filterParameters as $key => $filter) {
  311. list($filterName, $filterValue) = explode(':', $filter);
  312. if ($filterName == $this->facetName) {
  313. $indexToReplace = $key;
  314. break;
  315. }
  316. }
  317. if ($indexToReplace !== FALSE) {
  318. // facet found, replace facet
  319. $filterParameters[$indexToReplace] = $facetToReplace;
  320. } else {
  321. // facet not found, add facet
  322. $filterParameters[] = $facetToReplace;
  323. }
  324. $filterParameters = array_map('urlencode', $filterParameters);
  325. return $filterParameters;
  326. }
  327. }
  328. if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/solr/classes/facet/class.tx_solr_facet_simplefacetrenderer.php']) {
  329. include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/solr/classes/facet/class.tx_solr_facet_simplefacetrenderer.php']);
  330. }
  331. ?>