/** * Constructor for class Tx_Solr_ViewHelper_Multivalue * */ public function __construct(array $arguments = array()) { $configuration = Tx_Solr_Util::getSolrConfiguration(); if (!empty($configuration['viewhelpers.']['multivalue.']['glue'])) { $this->glue = $configuration['viewhelpers.']['multivalue.']['glue']; } }
/** * Initializes the search component. * * Sets the debug query parameter * */ public function initializeSearchComponent() { $solrConfiguration = Tx_Solr_Util::getSolrConfiguration(); if ($solrConfiguration['enableDebugMode']) { $this->query->setDebugMode(); } }
/** * Returns an URL that switches the sorting indicator according to the * given sorting direction * * @param array $arguments Expects 'asc' or 'desc' as sorting direction in key 0 * @return string * @throws InvalidArgumentException when providing an invalid sorting direction */ public function execute(array $arguments = array()) { $content = ''; $sortDirection = trim($arguments[0]); $configuration = Tx_Solr_Util::getSolrConfiguration(); $contentObject = t3lib_div::makeInstance('tslib_cObj'); $defaultImagePrefix = 'EXT:solr/Resources/Images/Indicator'; switch ($sortDirection) { case 'asc': $imageConfiguration = $configuration['viewHelpers.']['sortIndicator.']['up.']; if (!isset($imageConfiguration['file'])) { $imageConfiguration['file'] = $defaultImagePrefix . 'Up.png'; } $content = $contentObject->IMAGE($imageConfiguration); break; case 'desc': $imageConfiguration = $configuration['viewHelpers.']['sortIndicator.']['down.']; if (!isset($imageConfiguration['file'])) { $imageConfiguration['file'] = $defaultImagePrefix . 'Down.png'; } $content = $contentObject->IMAGE($imageConfiguration); break; case '###SORT.CURRENT_DIRECTION###': case '': // ignore break; default: throw new InvalidArgumentException('Invalid sorting direction "' . $arguments[0] . '", must be "asc" or "desc".', 1390868460); } return $content; }
/** * Initializes the search component. * */ public function initializeSearchComponent() { $solrConfiguration = Tx_Solr_Util::getSolrConfiguration(); if (!empty($solrConfiguration['statistics'])) { $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['modifySearchQuery']['statistics'] = 'Tx_Solr_Query_Modifier_Statistics'; $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['solr']['processSearchResponse']['statistics'] = 'Tx_Solr_Response_Processor_StatisticsWriter'; } }
/** * Constructor. * * @param string $facetName Facet Name * @param integer|string $facetOptionValue Facet option value * @param integer $facetOptionNumberOfResults number of results to be returned when applying this option's filter */ public function __construct($facetName, $facetOptionValue, $facetOptionNumberOfResults = 0) { $this->facetName = $facetName; $this->value = $facetOptionValue; $this->numberOfResults = intval($facetOptionNumberOfResults); $solrConfiguration = Tx_Solr_Util::getSolrConfiguration(); $this->facetConfiguration = $solrConfiguration['search.']['faceting.']['facets.'][$this->facetName . '.']; }
/** * Constructor. * * @param Tx_Solr_Facet_Facet $facet The facet to render. */ public function __construct(Tx_Solr_Facet_Facet $facet) { $this->search = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('Tx_Solr_Search'); $this->facet = $facet; $this->facetName = $facet->getName(); $this->solrConfiguration = Tx_Solr_Util::getSolrConfiguration(); $this->facetConfiguration = $this->solrConfiguration['search.']['faceting.']['facets.'][$this->facetName . '.']; $this->linkTargetPageId = $GLOBALS['TSFE']->id; $this->queryLinkBuilder = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('Tx_Solr_Query_LinkBuilder', $this->search->getQuery()); }
/** * Constructor. * * @param Tx_Solr_Query $query Solr query */ public function __construct(Tx_Solr_Query $query) { $this->solrConfiguration = Tx_Solr_Util::getSolrConfiguration(); $this->contentObject = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('tslib_cObj'); $this->query = $query; $targetPageUid = $this->contentObject->stdWrap($this->solrConfiguration['search.']['targetPage'], $this->solrConfiguration['search.']['targetPage.']); $this->linkTargetPageId = $targetPageUid; if (empty($this->linkTargetPageId)) { $this->linkTargetPageId = $GLOBALS['TSFE']->id; } }
/** * constructor for class Tx_Solr_ViewHelper_Crop */ public function __construct(array $arguments = array()) { $configuration = Tx_Solr_Util::getSolrConfiguration(); if (!empty($configuration['viewHelpers.']['crop.']['maxLength'])) { $this->maxLength = $configuration['viewHelpers.']['crop.']['maxLength']; } if (!empty($configuration['viewHelpers.']['crop.']['cropIndicator'])) { $this->cropIndicator = $configuration['viewHelpers.']['crop.']['cropIndicator']; } if (isset($configuration['viewHelpers.']['crop.']['cropFullWords'])) { $this->cropFullWords = (bool) $configuration['viewHelpers.']['crop.']['cropFullWords']; } }
/** * Modifies the given document and returns the modified document as result. * * @param Tx_Solr_PiResults_ResultsCommand $resultCommand The search result command * @param array $resultDocument Result document as array * @return array The document with fields as array */ public function modifyResultDocument($resultCommand, array $resultDocument) { $this->search = $resultCommand->getParentPlugin()->getSearch(); $configuration = Tx_Solr_Util::getSolrConfiguration(); $highlightedContent = $this->search->getHighlightedContent(); $highlightFields = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $configuration['search.']['results.']['resultsHighlighting.']['highlightFields'], TRUE); foreach ($highlightFields as $highlightField) { if (!empty($highlightedContent->{$resultDocument['id']}->{$highlightField}[0])) { $fragments = array(); foreach ($highlightedContent->{$resultDocument['id']}->{$highlightField} as $fragment) { $fragments[] = tx_solr_Template::escapeMarkers($fragment); } $resultDocument[$highlightField] = implode(' ' . $configuration['search.']['results.']['resultsHighlighting.']['fragmentSeparator'] . ' ', $fragments); } } return $resultDocument; }
/** * Processes a query and its response after searching for that query. * * @param Tx_Solr_Query The query that has been searched for. * @param Apache_Solr_Response The response for the last query. */ public function processResponse(Tx_Solr_Query $query, Apache_Solr_Response $response) { $urlParameters = t3lib_div::_GP('tx_solr'); $keywords = $query->getKeywords(); $filters = isset($urlParameters['filter']) ? $urlParameters['filter'] : array(); if (empty($keywords)) { // do not track empty queries return; } $keywords = t3lib_div::removeXSS($keywords); $keywords = htmlentities($keywords, ENT_QUOTES, $GLOBALS['TSFE']->metaCharset); $configuration = Tx_Solr_Util::getSolrConfiguration(); if ($configuration['search.']['frequentSearches.']['useLowercaseKeywords']) { $keywords = strtolower($keywords); } $ipMaskLength = (int) $configuration['statistics.']['anonymizeIP']; $insertFields = array('pid' => $GLOBALS['TSFE']->id, 'root_pid' => $GLOBALS['TSFE']->tmpl->rootLine[0]['uid'], 'tstamp' => $GLOBALS['EXEC_TIME'], 'language' => $GLOBALS['TSFE']->sys_language_uid, 'num_found' => $response->response->numFound, 'suggestions_shown' => (int) get_object_vars($response->spellcheck->suggestions), 'time_total' => $response->debug->timing->time, 'time_preparation' => $response->debug->timing->prepare->time, 'time_processing' => $response->debug->timing->process->time, 'feuser_id' => (int) $GLOBALS['TSFE']->fe_user->user['uid'], 'cookie' => $GLOBALS['TSFE']->fe_user->id, 'ip' => $this->applyIpMask(t3lib_div::getIndpEnv('REMOTE_ADDR'), $ipMaskLength), 'page' => (int) $urlParameters['page'], 'keywords' => $keywords, 'filters' => serialize($filters), 'sorting' => $urlParameters['sort'] ? $urlParameters['sort'] : '', 'parameters' => serialize($response->responseHeader->params)); $GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_solr_statistics', $insertFields); }
/** * Constructor * */ public function __construct($keywords) { $this->solrConfiguration = Tx_Solr_Util::getSolrConfiguration(); $this->fieldList = array('*', 'score'); $this->setKeywords($keywords); $this->sorting = ''; // What fields to search if (!empty($this->solrConfiguration['search.']['query.']['queryFields'])) { $this->setQueryFieldsFromString($this->solrConfiguration['search.']['query.']['queryFields']); } // What fields to return from Solr if (!empty($this->solrConfiguration['search.']['query.']['returnFields'])) { $this->fieldList = t3lib_div::trimExplode(',', $this->solrConfiguration['search.']['query.']['returnFields']); } $this->linkTargetPageId = $this->solrConfiguration['search.']['targetPage']; if (empty($this->linkTargetPageId)) { $this->linkTargetPageId = $GLOBALS['TSFE']->id; } $this->id = ++self::$idCount; }
/** * Renders the block of used / applied facets. * * @see Tx_Solr_FacetRenderer::render() * @return string Rendered HTML representing the used facet. */ public function render() { $solrConfiguration = Tx_Solr_Util::getSolrConfiguration(); $facetOption = t3lib_div::makeInstance('Tx_Solr_Facet_FacetOption', $this->facetName, $this->filterValue); $facetLinkBuilder = t3lib_div::makeInstance('Tx_Solr_Facet_LinkBuilder', $this->query, $this->facetName, $facetOption); /* @var $facetLinkBuilder Tx_Solr_Facet_LinkBuilder */ $facetLinkBuilder->setLinkTargetPageId($this->linkTargetPageId); if ($this->facetConfiguration['type'] == 'hierarchy') { // FIXME decouple this $filterEncoder = t3lib_div::makeInstance('Tx_Solr_Query_FilterEncoder_Hierarchy'); $facet = t3lib_div::makeInstance('Tx_Solr_Facet_Facet', $this->facetName); $facetRenderer = t3lib_div::makeInstance('Tx_Solr_Facet_HierarchicalFacetRenderer', $facet); $facetText = $facetRenderer->getLastPathSegmentFromHierarchicalFacetOption($filterEncoder->decodeFilter($this->filterValue)); } else { $facetText = $facetOption->render(); } $contentObject = t3lib_div::makeInstance('tslib_cObj'); $facetLabel = $contentObject->stdWrap($solrConfiguration['search.']['faceting.']['facets.'][$this->facetName . '.']['label'], $solrConfiguration['search.']['faceting.']['facets.'][$this->facetName . '.']['label.']); $removeFacetText = strtr($solrConfiguration['search.']['faceting.']['removeFacetLinkText'], array('@facetValue' => $this->filterValue, '@facetName' => $this->facetName, '@facetLabel' => $facetLabel, '@facetText' => $facetText)); $removeFacetLink = $facetLinkBuilder->getRemoveFacetOptionLink($removeFacetText); $removeFacetUrl = $facetLinkBuilder->getRemoveFacetOptionUrl(); $facetToRemove = array('link' => $removeFacetLink, 'url' => $removeFacetUrl, 'text' => $removeFacetText, 'value' => $this->filterValue, 'facet_name' => $this->facetName); return $facetToRemove; }
/** * Gets the document's score. * * @param string $document The result document as serialized array * @return float The document's score * @throws RuntimeException if the serialized result document array cannot be unserialized */ protected function getScore($document) { $rawDocument = $document; $score = 0; if (is_numeric($document)) { // backwards compatibility \TYPO3\CMS\Core\Utility\GeneralUtility::deprecationLog('You are using an old notation of the ' . 'releavnace view helpers. The notation used to be ' . '###RELEVANCE:###RESULT_DOCUMENT.SCORE######, please change ' . 'this to simply provide the whole result document: ' . '###RELEVANCE:###RESULT_DOCUMENT######'); return $document; } $document = unserialize($document); if (is_array($document)) { $score = $document['score']; } else { if ($rawDocument == '###RESULT_DOCUMENT###') { // unresolved marker // may happen when using search.spellchecking.searchUsingSpellCheckerSuggestion // -> ignore } else { $solrConfiguration = Tx_Solr_Util::getSolrConfiguration(); if ($solrConfiguration['logging.']['exceptions']) { \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('Could not resolve document score for relevance calculation', 'solr', 3, array('rawDocument' => $rawDocument, 'unserializedDocument' => $document)); } throw new RuntimeException('Could not resolve document score for relevance calculation', 1343670545); } } return $score; }
/** * Renders the complete facet. * * @see Tx_Solr_FacetRenderer::render() * @return string Rendered HTML representing the facet. */ public function renderFacetOptions() { $facetOptionLinks = array(); $solrConfiguration = Tx_Solr_Util::getSolrConfiguration(); $this->template->workOnSubpart('single_facet_option'); if (!empty($this->facetConfiguration['manualSortOrder'])) { $this->sortFacetOptionsByUserDefinedOrder(); } if (!empty($this->facetConfiguration['reverseOrder'])) { $this->facetOptions = array_reverse($this->facetOptions, true); } $i = 0; foreach ($this->facetOptions as $facetOption => $facetOptionResultCount) { $facetOption = (string) $facetOption; if ($facetOption == '_empty_') { // TODO - for now we don't handle facet missing. continue; } $facetOption = t3lib_div::makeInstance('Tx_Solr_Facet_FacetOption', $this->facetName, $facetOption, $facetOptionResultCount); /* @var $facetOption Tx_Solr_Facet_FacetOption */ $facetLinkBuilder = t3lib_div::makeInstance('Tx_Solr_Facet_LinkBuilder', $this->query, $this->facetName, $facetOption); /* @var $facetLinkBuilder Tx_Solr_Facet_LinkBuilder */ $facetLinkBuilder->setLinkTargetPageId($this->linkTargetPageId); $optionText = $facetOption->render(); $optionLink = $facetLinkBuilder->getAddFacetOptionLink($optionText); $optionLinkUrl = $facetLinkBuilder->getAddFacetOptionUrl(); $optionHidden = ''; if (++$i > $solrConfiguration['search.']['faceting.']['limit']) { $optionHidden = 'tx-solr-facet-hidden'; } $optionSelected = $facetOption->isSelectedInFacet($this->facetName); // negating the facet option links to remove a filter if ($this->facetConfiguration['selectingSelectedFacetOptionRemovesFilter'] && $optionSelected) { $optionLink = $facetLinkBuilder->getRemoveFacetOptionLink($optionText); $optionLinkUrl = $facetLinkBuilder->getRemoveFacetOptionUrl(); } elseif ($this->facetConfiguration['singleOptionMode']) { $optionLink = $facetLinkBuilder->getReplaceFacetOptionLink($optionText); $optionLinkUrl = $facetLinkBuilder->getReplaceFacetOptionUrl(); } $facetOptionLinks[] = array('hidden' => $optionHidden, 'link' => $optionLink, 'url' => $optionLinkUrl, 'text' => $optionText, 'value' => $facetOption->getValue(), 'count' => $facetOption->getNumberOfResults(), 'selected' => $optionSelected ? '1' : '0', 'facet_name' => $this->facetName); } $this->template->addLoop('facet_links', 'facet_link', $facetOptionLinks); return $this->template->render(); }
/** * Escapes a document's content field taking into account the wrap setting * for highlighting keywords * * @param string $content content field value * @return string escaped content */ protected function escapeResultContent($content) { $content = htmlspecialchars($content, NULL, NULL, FALSE); $configuration = Tx_Solr_Util::getSolrConfiguration(); $highlightingWrap = $configuration['search.']['results.']['resultsHighlighting.']['wrap']; $highlightingWrap = explode('|', $highlightingWrap); $pattern = '/' . htmlspecialchars($highlightingWrap[0], NULL, NULL, FALSE) . '(.+?)' . str_replace('/', '\\/', htmlspecialchars($highlightingWrap[1])) . '/is'; $replacement = $highlightingWrap[0] . '$1' . $highlightingWrap[1]; $content = preg_replace($pattern, $replacement, $content); return $content; }
/** * Returns the number of results per Page. * * Also influences how many result documents are returned by the Solr * server as the return value is used in the Solr "rows" GET parameter. * * @return int number of results to show per page */ public function getNumberOfResultsPerPage() { $configuration = Tx_Solr_Util::getSolrConfiguration(); $resultsPerPageSwitchOptions = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $configuration['search.']['results.']['resultsPerPageSwitchOptions']); $solrParameters = array(); $solrPostParameters = \TYPO3\CMS\Core\Utility\GeneralUtility::_POST('tx_solr'); $solrGetParameters = \TYPO3\CMS\Core\Utility\GeneralUtility::_GET('tx_solr'); // check for GET parameters, POST takes precedence if (isset($solrGetParameters) && is_array($solrGetParameters)) { $solrParameters = $solrGetParameters; } if (isset($solrPostParameters) && is_array($solrPostParameters)) { $solrParameters = $solrPostParameters; } if (isset($solrParameters['resultsPerPage']) && in_array($solrParameters['resultsPerPage'], $resultsPerPageSwitchOptions)) { $GLOBALS['TSFE']->fe_user->setKey('ses', 'tx_solr_resultsPerPage', intval($solrParameters['resultsPerPage'])); $this->resultsPerPageChanged = TRUE; } $defaultNumberOfResultsShown = $this->conf['search.']['results.']['resultsPerPage']; $userSetNumberOfResultsShown = $GLOBALS['TSFE']->fe_user->getKey('ses', 'tx_solr_resultsPerPage'); $currentNumberOfResultsShown = $defaultNumberOfResultsShown; if (!is_null($userSetNumberOfResultsShown) && in_array($userSetNumberOfResultsShown, $resultsPerPageSwitchOptions)) { $currentNumberOfResultsShown = (int) $userSetNumberOfResultsShown; } $rawUserQuery = $this->getRawUserQuery(); if (($this->conf['search.']['initializeWithEmptyQuery'] || $this->conf['search.']['initializeWithQuery']) && !$this->conf['search.']['showResultsOfInitialEmptyQuery'] && !$this->conf['search.']['showResultsOfInitialQuery'] && empty($rawUserQuery)) { // initialize search with an empty query, which would by default return all documents // anyway, tell Solr to not return any result documents // Solr will still return facets though $currentNumberOfResultsShown = 0; } return $currentNumberOfResultsShown; }
/** * Constructor for class Tx_Solr_SpellChecker * */ public function __construct() { $this->search = t3lib_div::makeInstance('Tx_Solr_Search'); $this->configuration = Tx_Solr_Util::getSolrConfiguration(); }
/** * constructor for class Tx_Solr_Query_Modifier_Faceting */ public function __construct() { $this->configuration = Tx_Solr_Util::getSolrConfiguration(); $this->facetRendererFactory = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('Tx_Solr_Facet_FacetRendererFactory', $this->configuration['search.']['faceting.']['facets.']); }
/** * Enables the query's elevation mode. * * @param Tx_Solr_Query $query The query to modify * @return Tx_Solr_Query The modified query with enabled elevation mode */ public function modifyQuery(Tx_Solr_Query $query) { $configuration = Tx_Solr_Util::getSolrConfiguration(); $query->setQueryElevation($configuration['search.']['elevation'], $configuration['search.']['elevation.']['forceElevation'], $configuration['search.']['elevation.']['markElevatedResults']); return $query; }
/** * Constructor for class Tx_Solr_SpellChecker * */ public function __construct() { $this->search = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('Tx_Solr_Search'); $this->configuration = Tx_Solr_Util::getSolrConfiguration(); }
/** * Constructor. * */ public function __construct() { $this->configuration = Tx_Solr_Util::getSolrConfiguration(); }
/** * constructor for class Tx_Solr_ViewHelper_SortUrl */ public function __construct(array $arguments = array()) { $this->search = GeneralUtility::makeInstance('Tx_Solr_Search'); $this->configuration = Tx_Solr_Util::getSolrConfiguration(); $this->queryLinkBuilder = GeneralUtility::makeInstance('Tx_Solr_Query_LinkBuilder', $this->search->getQuery()); }
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\Utility\EidUtility; # TSFE initialization $pageId = filter_var(GeneralUtility::_GET('id'), FILTER_SANITIZE_NUMBER_INT); $languageId = filter_var(GeneralUtility::_GET('L'), FILTER_VALIDATE_INT, array('options' => array('default' => 0, 'min_range' => 0))); $GLOBALS['TSFE'] = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Controller\\TypoScriptFrontendController', $GLOBALS['TYPO3_CONF_VARS'], $pageId, 0, TRUE); $GLOBALS['TSFE']->initFEuser(); $GLOBALS['TSFE']->initUserGroups(); // load TCA EidUtility::initTCA(); $GLOBALS['TSFE']->sys_page = GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository'); $GLOBALS['TSFE']->rootLine = $GLOBALS['TSFE']->sys_page->getRootLine($pageId, ''); $GLOBALS['TSFE']->initTemplate(); $GLOBALS['TSFE']->getConfigArray(); $GLOBALS['TSFE']->sys_language_uid = $languageId; $solrConfiguration = Tx_Solr_Util::getSolrConfiguration(); #--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- # Building Suggest Query $q = trim(GeneralUtility::_GP('termLowercase')); $isOpenSearchRequest = FALSE; if ('OpenSearch' == GeneralUtility::_GET('format')) { $isOpenSearchRequest = TRUE; $q = GeneralUtility::_GET('q'); } $allowedSites = Tx_Solr_Util::resolveSiteHashAllowedSites($pageId, $solrConfiguration['search.']['query.']['allowedSites']); $suggestQuery = GeneralUtility::makeInstance('Tx_Solr_SuggestQuery', $q); $suggestQuery->setUserAccessGroups(explode(',', $GLOBALS['TSFE']->gr_list)); $suggestQuery->setSiteHashFilter($allowedSites); $suggestQuery->setOmitHeader(); $additionalFilters = GeneralUtility::_GET('filters'); if (!empty($additionalFilters)) {
/** * constructor for class Tx_Solr_Query_Modifier_Faceting */ public function __construct() { $this->configuration = Tx_Solr_Util::getSolrConfiguration(); $this->facetRendererFactory = t3lib_div::makeInstance('Tx_Solr_Facet_FacetRendererFactory', $this->configuration['search.']['faceting.']['facets.']); }
/** * Renders an overview of how the score for a certain document has been * calculated. * * @param array $highScores The result document which to analyse * @return string The HTML showing the score analysis */ protected function renderScoreAnalysis(array $highScores) { $configuration = Tx_Solr_Util::getSolrConfiguration(); $content = ''; $scores = array(); $totalScore = 0; foreach ($highScores as $field => $highScore) { $pattern = '/' . $highScore['field'] . '\\^([\\d.]*)/'; $matches = array(); preg_match_all($pattern, $configuration['search.']['query.']['queryFields'], $matches); $scores[] = ' <td>+ ' . $highScore['score'] . '</td> <td>' . $highScore['field'] . '</td> <td>' . $matches[1][0] . '</td>'; $totalScore += $highScore['score']; } $content = '<table style="width: 100%; border: 1px solid #aaa; font-size: 11px; background-color: #eee;"> <tr style="border-bottom: 2px solid #aaa; font-weight: bold;"><td>Score</td><td>Field</td><td>Boost</td></tr><tr>' . implode('</tr><tr>', $scores) . '</tr> <tr><td colspan="3"><hr style="border-top: 1px solid #aaa; height: 0; padding: 0; margin: 0;" /></td></tr> <tr><td colspan="3">= ' . $totalScore . ' (Inaccurate analysis! Not all parts of the score have been taken into account.)</td></tr> </table>'; return $content; }
/** * Initializes/loads the facet configuration * */ protected function initializeConfiguration() { $solrConfiguration = Tx_Solr_Util::getSolrConfiguration(); $this->configuration = $solrConfiguration['search.']['faceting.']['facets.'][$this->name . '.']; $this->field = $this->configuration['field']; }