/** * Detect is this page are frontpage? * * @return boolean Is frontpage? */ public static function isHome() { $langPath = null; $tag = null; $lang = \JFactory::getLanguage(); // For multi language if (\JPluginHelper::isEnabled('system', 'languagefilter')) { $tag = $lang->getTag(); $langCodes = \JLanguageHelper::getLanguages('lang_code'); $langPath = $langCodes[$tag]->sef; } $uri = \JUri::getInstance(); $root = $uri::root(true); // Get site route $route = StringHelper::substr($uri->getPath(), StringHelper::strlen($root)); // Remove index.php $route = str_replace('index.php', '', $route); // If Multiple language enabled, we check first part of URI is language code or not. if ($langPath) { $params = ExtensionHelper::getParams('plg_system_languagefilter'); if ($tag == $lang->getDefault() && $params->get('remove_default_prefix', 0)) { $langPath = ''; } // If route equals lang path, means it is home route. if (trim($route, '/') == $langPath && !$uri->getVar('option')) { return true; } } else { if (!trim($route, '/') && !$uri->getVar('option')) { return true; } } return false; }
/** * setMeta * * @param object $article * * @return void */ public static function setMeta($article) { $app = \JFactory::getApplication(); if ($app->isAdmin()) { return; } if (!static::$firstArticle) { return; } $config = \JFactory::getConfig(); $ezset = \Ezset::getInstance(); // Get menu meta, if nonexists, use article meta if (isset($article->params) && $article->params instanceof \JRegistry && isset($article->metadesc)) { $ezset->data->metaDesc = $article->params->get('menu-meta_description', $article->metadesc); } if (\Ezset::isHome()) { $ezset->data->metaDesc = $config->get('MetaDesc'); } elseif (!$ezset->data->metaDesc) { // Get meta from article content $metaDesc = $article->text; // Remove script tags $metaDesc = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $metaDesc); $metaDesc = preg_replace('#<style(.*?)>(.*?)</style>#is', '', $metaDesc); $metaDesc = strip_tags($metaDesc); // Filter plugin like:{rsform 1} $metaDesc = preg_replace('/\\{.*\\}/', '', $metaDesc); // Remove line $metaDesc = str_replace("\r\n", '', $metaDesc); $metaDesc = str_replace(" ", '', $metaDesc); $metaDesc = trim($metaDesc); $metaDesc = StringHelper::substr($metaDesc, 0, $ezset->params->get('maxMetaChar', 250)); // Remove latest word $metaDesc = trim($metaDesc); $metaDesc = explode(' ', $metaDesc); $latestWord = array_pop($metaDesc); if (strlen($latestWord) > 10) { $metaDesc[] = $latestWord; } // Rebuild paragraph $metaDesc = implode(' ', $metaDesc); $ezset->data->metaDesc = $metaDesc; // Find category name if (property_exists($article, 'catid')) { $category = \JTable::getInstance('Category'); $category->load($article->catid); $ezset->data->catName = $category->title; } } static::$firstArticle = false; }
/** * Returns an array of options * * @param string $query SQL with 'ordering' AS value and 'name field' AS text * @param integer $chop The length of the truncated headline * * @return array An array of objects formatted for JHtml list processing * * @since 1.5 */ public static function genericordering($query, $chop = 30) { $db = JFactory::getDbo(); $options = array(); $db->setQuery($query); $items = $db->loadObjectList(); if (empty($items)) { $options[] = JHtml::_('select.option', 1, JText::_('JOPTION_ORDER_FIRST')); return $options; } $options[] = JHtml::_('select.option', 0, '0 ' . JText::_('JOPTION_ORDER_FIRST')); for ($i = 0, $n = count($items); $i < $n; $i++) { $items[$i]->text = JText::_($items[$i]->text); if (StringHelper::strlen($items[$i]->text) > $chop) { $text = StringHelper::substr($items[$i]->text, 0, $chop) . "..."; } else { $text = $items[$i]->text; } $options[] = JHtml::_('select.option', $items[$i]->value, $items[$i]->value . '. ' . $text); } $options[] = JHtml::_('select.option', $items[$i - 1]->value + 1, $items[$i - 1]->value + 1 . ' ' . JText::_('JOPTION_ORDER_LAST')); return $options; }
/** * clearView * * @param string $context * @param object $article * @param \JRegistry $params * * @return void */ public static function clearView($context, $article, $params = null) { $input = \JFactory::getApplication()->input; if ($input->get('layout') != 'blog' && $input->get('view') != 'featured') { return; } $es = \Ezset::getInstance(); $html = new Dom(); $imgW = $es->params->get('blogViewImgWidth', 150); $maxChar = $es->params->get('blogViewMaxChar', 250); $default = $es->params->get('blogViewImgDefault'); $crop = (bool) $es->params->get('blogViewImgCrop', true); $allowTags = $es->params->get('blogViewTagsAllow'); $doc = \JFactory::getDocument(); $text = $article->introtext; $mainImg = null; if ($doc->getType() != 'html') { return; } $thumb = new \Windwalker\Image\Thumb(); if ($default) { $thumb->setDefaultImage($default); } // Clean Tags if ($es->params->get('blogViewClearly', 0)) { // If first image = main image, delete this paragraph. $html = $html->load($text); /** @var \PHPHtmlParser\Dom\Collection|\PHPHtmlParser\Dom\HtmlNode[] $imgs */ $imgs = $html->find('img'); if ($imgs->count()) { $mainImg = $imgs[0]->src; // Is img in p tag? /** @var \PHPHtmlParser\Dom\HtmlNode $p */ $p = $imgs[0]->getParent(); // If image has anchor, get parent. if ($p->getTag() != 'p') { $p = $p->getParent(); } // remove first img $p->setInnerHtml(str_replace($p->firstChild()->outerHtml(), '', $p->innerHtml())); if (!trim($p->innerHtml())) { $p->setOuterHtml(''); } $text = (string) $html; } if ($es->params->get('blogViewCleanTags', 0)) { $text = strip_tags($text, $allowTags); if (!$allowTags) { $text = StringHelper::substr($text, 0, $maxChar); } } } // Handle Image if ($crop) { $imageUrl = $thumb->resize($mainImg, $imgW, $imgW, $crop); } else { $imageUrl = $thumb->resize($mainImg, $imgW, 999); } // Article Link $link = JContentHelper::getArticleLink($article->id, $article->catid, 0); $data = array('link' => $link, 'image_width' => $imgW, 'image_url' => $imageUrl, 'article' => $article, 'text' => $text); // Set layout $layout = with(new FileLayout('ezset.article.blog.clearview'))->render($data); $article->introtext = $layout; }
/** * Method to parse a language/locale key and return a simple language string. * * @param string $lang The language/locale key. For example: en-GB * * @return string The simple language string. For example: en * * @since 2.5 */ public static function getPrimaryLanguage($lang) { static $data; // Only parse the identifier if necessary. if (!isset($data[$lang])) { if (is_callable(array('Locale', 'getPrimaryLanguage'))) { // Get the language key using the Locale package. $data[$lang] = Locale::getPrimaryLanguage($lang); } else { // Get the language key using string position. $data[$lang] = StringHelper::substr($lang, 0, StringHelper::strpos($lang, '-')); } } return $data[$lang]; }
/** * Execute and display a template script. * * @param string $tpl The name of the template file to parse; automatically searches through the template paths. * * @return mixed A string if successful, otherwise an Error object. */ public function display($tpl = null) { JLoader::register('SearchHelper', JPATH_COMPONENT_ADMINISTRATOR . '/helpers/search.php'); $app = JFactory::getApplication(); $uri = JUri::getInstance(); $error = null; $rows = null; $results = null; $total = 0; // Get some data from the model $areas = $this->get('areas'); $state = $this->get('state'); $searchword = $state->get('keyword'); $params = $app->getParams(); $menus = $app->getMenu(); $menu = $menus->getActive(); // Because the application sets a default page title, we need to get it right from the menu item itself if (is_object($menu)) { $menu_params = new Registry($menu->params); if (!$menu_params->get('page_title')) { $params->set('page_title', JText::_('COM_SEARCH_SEARCH')); } } else { $params->set('page_title', JText::_('COM_SEARCH_SEARCH')); } $title = $params->get('page_title'); if ($app->get('sitename_pagetitles', 0) == 1) { $title = JText::sprintf('JPAGETITLE', $app->get('sitename'), $title); } elseif ($app->get('sitename_pagetitles', 0) == 2) { $title = JText::sprintf('JPAGETITLE', $title, $app->get('sitename')); } $this->document->setTitle($title); if ($params->get('menu-meta_description')) { $this->document->setDescription($params->get('menu-meta_description')); } if ($params->get('menu-meta_keywords')) { $this->document->setMetadata('keywords', $params->get('menu-meta_keywords')); } if ($params->get('robots')) { $this->document->setMetadata('robots', $params->get('robots')); } // Built select lists $orders = array(); $orders[] = JHtml::_('select.option', 'newest', JText::_('COM_SEARCH_NEWEST_FIRST')); $orders[] = JHtml::_('select.option', 'oldest', JText::_('COM_SEARCH_OLDEST_FIRST')); $orders[] = JHtml::_('select.option', 'popular', JText::_('COM_SEARCH_MOST_POPULAR')); $orders[] = JHtml::_('select.option', 'alpha', JText::_('COM_SEARCH_ALPHABETICAL')); $orders[] = JHtml::_('select.option', 'category', JText::_('JCATEGORY')); $lists = array(); $lists['ordering'] = JHtml::_('select.genericlist', $orders, 'ordering', 'class="inputbox"', 'value', 'text', $state->get('ordering')); $searchphrases = array(); $searchphrases[] = JHtml::_('select.option', 'all', JText::_('COM_SEARCH_ALL_WORDS')); $searchphrases[] = JHtml::_('select.option', 'any', JText::_('COM_SEARCH_ANY_WORDS')); $searchphrases[] = JHtml::_('select.option', 'exact', JText::_('COM_SEARCH_EXACT_PHRASE')); $lists['searchphrase'] = JHtml::_('select.radiolist', $searchphrases, 'searchphrase', '', 'value', 'text', $state->get('match')); // Log the search JSearchHelper::logSearch($searchword, 'com_search'); // Limit searchword $lang = JFactory::getLanguage(); $upper_limit = $lang->getUpperLimitSearchWord(); $lower_limit = $lang->getLowerLimitSearchWord(); if (SearchHelper::limitSearchWord($searchword)) { $error = JText::sprintf('COM_SEARCH_ERROR_SEARCH_MESSAGE', $lower_limit, $upper_limit); } // Sanitise searchword if (SearchHelper::santiseSearchWord($searchword, $state->get('match'))) { $error = JText::_('COM_SEARCH_ERROR_IGNOREKEYWORD'); } if (!$searchword && !empty($this->input) && count($this->input->post)) { // $error = JText::_('COM_SEARCH_ERROR_ENTERKEYWORD'); } // Put the filtered results back into the model // for next release, the checks should be done in the model perhaps... $state->set('keyword', $searchword); if ($error == null) { $results = $this->get('data'); $total = $this->get('total'); $pagination = $this->get('pagination'); JLoader::register('ContentHelperRoute', JPATH_SITE . '/components/com_content/helpers/route.php'); for ($i = 0, $count = count($results); $i < $count; $i++) { $row =& $results[$i]->text; if ($state->get('match') == 'exact') { $searchwords = array($searchword); $needle = $searchword; } else { $searchworda = preg_replace('#\\xE3\\x80\\x80#s', ' ', $searchword); $searchwords = preg_split("/\\s+/u", $searchworda); $needle = $searchwords[0]; } $row = SearchHelper::prepareSearchContent($row, $needle); $searchwords = array_values(array_unique($searchwords)); $srow = strtolower(SearchHelper::remove_accents($row)); $hl1 = '<span class="highlight">'; $hl2 = '</span>'; $posCollector = array(); $mbString = extension_loaded('mbstring'); if ($mbString) { // E.g. german umlauts like ä are converted to ae and so // $pos calculated with $srow doesn't match for $row $correctPos = mb_strlen($srow) > mb_strlen($row); $highlighterLen = mb_strlen($hl1 . $hl2); } else { // E.g. german umlauts like ä are converted to ae and so // $pos calculated with $srow desn't match for $row $correctPos = StringHelper::strlen($srow) > StringHelper::strlen($row); $highlighterLen = StringHelper::strlen($hl1 . $hl2); } foreach ($searchwords as $hlword) { if ($mbString) { if (($pos = mb_strpos($srow, strtolower(SearchHelper::remove_accents($hlword)))) !== false) { // Iconv transliterates '€' to 'EUR' // TODO: add other expanding translations? $eur_compensation = $pos > 0 ? substr_count($row, "€", 0, $pos) * 2 : 0; $pos -= $eur_compensation; if ($correctPos) { // Calculate necessary corrections from 0 to current $pos $ChkRow = mb_substr($row, 0, $pos); $sChkRowLen = mb_strlen(strtolower(SearchHelper::remove_accents($ChkRow))); $ChkRowLen = mb_strlen($ChkRow); // Correct $pos $pos -= $sChkRowLen - $ChkRowLen; } // Collect pos and searchword $posCollector[$pos] = $hlword; } } else { if (($pos = StringHelper::strpos($srow, strtolower(SearchHelper::remove_accents($hlword)))) !== false) { // Iconv transliterates '€' to 'EUR' // TODO: add other expanding translations? $eur_compensation = $pos > 0 ? substr_count($row, "€", 0, $pos) * 2 : 0; $pos -= $eur_compensation; if ($correctPos) { // Calculate necessary corrections from 0 to current $pos $ChkRow = StringHelper::substr($row, 0, $pos); $sChkRowLen = StringHelper::strlen(strtolower(SearchHelper::remove_accents($ChkRow))); $ChkRowLen = StringHelper::strlen($ChkRow); // Correct $pos $pos -= $sChkRowLen - $ChkRowLen; } // Collect pos and searchword $posCollector[$pos] = $hlword; } } } if (count($posCollector)) { // Sort by pos. Easier to handle overlapping highlighter-spans ksort($posCollector); $cnt = 0; $lastHighlighterEnd = -1; foreach ($posCollector as $pos => $hlword) { $pos += $cnt * $highlighterLen; /* Avoid overlapping/corrupted highlighter-spans * TODO $chkOverlap could be used to highlight remaining part * of searchword outside last highlighter-span. * At the moment no additional highlighter is set.*/ $chkOverlap = $pos - $lastHighlighterEnd; if ($chkOverlap >= 0) { // Set highlighter around searchword if ($mbString) { $hlwordLen = mb_strlen($hlword); $row = mb_substr($row, 0, $pos) . $hl1 . mb_substr($row, $pos, $hlwordLen) . $hl2 . mb_substr($row, $pos + $hlwordLen); } else { $hlwordLen = StringHelper::strlen($hlword); $row = StringHelper::substr($row, 0, $pos) . $hl1 . StringHelper::substr($row, $pos, StringHelper::strlen($hlword)) . $hl2 . StringHelper::substr($row, $pos + StringHelper::strlen($hlword)); } $cnt++; $lastHighlighterEnd = $pos + $hlwordLen + $highlighterLen; } } } $result =& $results[$i]; if ($result->created) { $created = JHtml::_('date', $result->created, JText::_('DATE_FORMAT_LC3')); } else { $created = ''; } $result->text = JHtml::_('content.prepare', $result->text, '', 'com_search.search'); $result->created = $created; $result->count = $i + 1; } } // Check for layout override $active = JFactory::getApplication()->getMenu()->getActive(); if (isset($active->query['layout'])) { $this->setLayout($active->query['layout']); } // Escape strings for HTML output $this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx')); $this->pagination =& $pagination; $this->results =& $results; $this->lists =& $lists; $this->params =& $params; $this->ordering = $state->get('ordering'); $this->searchword = $searchword; $this->origkeyword = $state->get('origkeyword'); $this->searchphrase = $state->get('match'); $this->searchareas = $areas; $this->total = $total; $this->error = $error; $this->action = $uri; parent::display($tpl); }
/** * Method to get an array of link ids that match excluded terms. * * @return array An array of links ids. * * @since 2.5 * @throws Exception on database error. */ protected function getExcludedLinkIds() { // Check if the search query has excluded terms. if (empty($this->excludedTerms)) { return array(); } // Get the store id. $store = $this->getStoreId('getExcludedLinkIds', false); // Use the cached data if possible. if ($this->retrieve($store)) { return $this->retrieve($store); } // Initialize containers. $links = array(); $maps = array(); /* * Iterate through the excluded search terms and group them by mapping * table suffix. This ensures that we never have to do more than 16 * queries to get a batch. This may seem like a lot but it is rarely * anywhere near 16 because of the improved mapping algorithm. */ foreach ($this->excludedTerms as $token => $id) { // Get the mapping table suffix. $suffix = StringHelper::substr(md5(StringHelper::substr($token, 0, 1)), 0, 1); // Initialize the mapping group. if (!array_key_exists($suffix, $maps)) { $maps[$suffix] = array(); } // Add the terms to the mapping group. $maps[$suffix][] = (int) $id; } /* * Iterate through the mapping groups and load the excluded links ids * from each mapping table. */ // Create a new query object. $db = $this->getDbo(); $query = $db->getQuery(true); foreach ($maps as $suffix => $ids) { // Create the query to get the links ids. $query->clear()->select('link_id')->from($db->quoteName('#__finder_links_terms' . $suffix))->where($db->quoteName('term_id') . ' IN (' . implode(',', $ids) . ')')->group($db->quoteName('link_id')); // Load the link ids from the database. $db->setQuery($query); $temp = $db->loadColumn(); // Merge the link ids. $links = array_merge($links, $temp); } // Sanitize the link ids. $links = array_unique($links); $links = ArrayHelper::toInteger($links); // Push the link ids into cache. $this->store($store, $links); return $links; }
/** * Returns substring of characters around a searchword. * * @param string $text The source string. * @param integer $searchword Number of chars to return. * * @return string * * @since 1.5 */ public static function _smartSubstr($text, $searchword) { $lang = JFactory::getLanguage(); $length = $lang->getSearchDisplayedCharactersNumber(); $ltext = self::remove_accents($text); $textlen = StringHelper::strlen($ltext); $lsearchword = StringHelper::strtolower(self::remove_accents($searchword)); $wordfound = false; $pos = 0; while ($wordfound === false && $pos < $textlen) { if (($wordpos = @StringHelper::strpos($ltext, ' ', $pos + $length)) !== false) { $chunk_size = $wordpos - $pos; } else { $chunk_size = $length; } $chunk = StringHelper::substr($ltext, $pos, $chunk_size); $wordfound = StringHelper::strpos(StringHelper::strtolower($chunk), $lsearchword); if ($wordfound === false) { $pos += $chunk_size + 1; } } if ($wordfound !== false) { return ($pos > 0 ? '... ' : '') . StringHelper::substr($text, $pos, $chunk_size) . ' ...'; } else { if (($wordpos = @StringHelper::strpos($text, ' ', $length)) !== false) { return StringHelper::substr($text, 0, $wordpos) . ' ...'; } else { return StringHelper::substr($text, 0, $length); } } }
/** * Method to process the query input string and extract required, optional, * and excluded tokens; taxonomy filters; and date filters. * * @param string $input The query input string. * @param string $lang The query input language. * @param string $mode The query matching mode. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ protected function processString($input, $lang, $mode) { // Clean up the input string. $input = html_entity_decode($input, ENT_QUOTES, 'UTF-8'); $input = StringHelper::strtolower($input); $input = preg_replace('#\\s+#mi', ' ', $input); $input = StringHelper::trim($input); $debug = JFactory::getConfig()->get('debug_lang'); /* * First, we need to handle string based modifiers. String based * modifiers could potentially include things like "category:blah" or * "before:2009-10-21" or "type:article", etc. */ $patterns = array('before' => JText::_('COM_FINDER_FILTER_WHEN_BEFORE'), 'after' => JText::_('COM_FINDER_FILTER_WHEN_AFTER')); // Add the taxonomy branch titles to the possible patterns. foreach (FinderIndexerTaxonomy::getBranchTitles() as $branch) { // Add the pattern. $patterns[$branch] = StringHelper::strtolower(JText::_(FinderHelperLanguage::branchSingular($branch))); } // Container for search terms and phrases. $terms = array(); $phrases = array(); // Cleared filter branches. $cleared = array(); /* * Compile the suffix pattern. This is used to match the values of the * filter input string. Single words can be input directly, multi-word * values have to be wrapped in double quotes. */ $quotes = html_entity_decode('‘’'', ENT_QUOTES, 'UTF-8'); $suffix = '(([\\w\\d' . $quotes . '-]+)|\\"([\\w\\d\\s' . $quotes . '-]+)\\")'; /* * Iterate through the possible filter patterns and search for matches. * We need to match the key, colon, and a value pattern for the match * to be valid. */ foreach ($patterns as $modifier => $pattern) { $matches = array(); if ($debug) { $pattern = substr($pattern, 2, -2); } // Check if the filter pattern is in the input string. if (preg_match('#' . $pattern . '\\s*:\\s*' . $suffix . '#mi', $input, $matches)) { // Get the value given to the modifier. $value = isset($matches[3]) ? $matches[3] : $matches[1]; // Now we have to handle the filter string. switch ($modifier) { // Handle a before and after date filters. case 'before': case 'after': // Get the time offset. $offset = JFactory::getApplication()->get('offset'); // Array of allowed when values. $whens = array('before', 'after', 'exact'); // The value of 'today' is a special case that we need to handle. if ($value === StringHelper::strtolower(JText::_('COM_FINDER_QUERY_FILTER_TODAY'))) { $value = JFactory::getDate('now', $offset)->format('%Y-%m-%d'); } // Try to parse the date string. $date = JFactory::getDate($value, $offset); // Check if the date was parsed successfully. if ($date->toUnix() !== null) { // Set the date filter. $this->date1 = $date->toSql(); $this->when1 = in_array($modifier, $whens) ? $modifier : 'before'; } break; // Handle a taxonomy branch filter. // Handle a taxonomy branch filter. default: // Try to find the node id. $return = FinderIndexerTaxonomy::getNodeByTitle($modifier, $value); // Check if the node id was found. if ($return) { // Check if the branch has been cleared. if (!in_array($modifier, $cleared)) { // Clear the branch. $this->filters[$modifier] = array(); // Add the branch to the cleared list. $cleared[] = $modifier; } // Add the filter to the list. $this->filters[$modifier][$return->title] = (int) $return->id; } break; } // Clean up the input string again. $input = str_replace($matches[0], '', $input); $input = preg_replace('#\\s+#mi', ' ', $input); $input = StringHelper::trim($input); } } /* * Extract the tokens enclosed in double quotes so that we can handle * them as phrases. */ if (StringHelper::strpos($input, '"') !== false) { $matches = array(); // Extract the tokens enclosed in double quotes. if (preg_match_all('#\\"([^"]+)\\"#mi', $input, $matches)) { /* * One or more phrases were found so we need to iterate through * them, tokenize them as phrases, and remove them from the raw * input string before we move on to the next processing step. */ foreach ($matches[1] as $key => $match) { // Find the complete phrase in the input string. $pos = StringHelper::strpos($input, $matches[0][$key]); $len = StringHelper::strlen($matches[0][$key]); // Add any terms that are before this phrase to the stack. if (StringHelper::trim(StringHelper::substr($input, 0, $pos))) { $terms = array_merge($terms, explode(' ', StringHelper::trim(StringHelper::substr($input, 0, $pos)))); } // Strip out everything up to and including the phrase. $input = StringHelper::substr($input, $pos + $len); // Clean up the input string again. $input = preg_replace('#\\s+#mi', ' ', $input); $input = StringHelper::trim($input); // Get the number of words in the phrase. $parts = explode(' ', $match); // Check if the phrase is longer than three words. if (count($parts) > 3) { /* * If the phrase is longer than three words, we need to * break it down into smaller chunks of phrases that * are less than or equal to three words. We overlap * the chunks so that we can ensure that a match is * found for the complete phrase and not just portions * of it. */ for ($i = 0, $c = count($parts); $i < $c; $i += 2) { // Set up the chunk. $chunk = array(); // The chunk has to be assembled based on how many // pieces are available to use. switch ($c - $i) { /* * If only one word is left, we can break from * the switch and loop because the last word * was already used at the end of the last * chunk. */ case 1: break 2; // If there words are left, we use them both as // the last chunk of the phrase and we're done. // If there words are left, we use them both as // the last chunk of the phrase and we're done. case 2: $chunk[] = $parts[$i]; $chunk[] = $parts[$i + 1]; break; // If there are three or more words left, we // build a three word chunk and continue on. // If there are three or more words left, we // build a three word chunk and continue on. default: $chunk[] = $parts[$i]; $chunk[] = $parts[$i + 1]; $chunk[] = $parts[$i + 2]; break; } // If the chunk is not empty, add it as a phrase. if (count($chunk)) { $phrases[] = implode(' ', $chunk); $terms[] = implode(' ', $chunk); } } } else { // The phrase is <= 3 words so we can use it as is. $phrases[] = $match; $terms[] = $match; } } } } // Add the remaining terms if present. if (!empty($input)) { $terms = array_merge($terms, explode(' ', $input)); } // An array of our boolean operators. $operator => $translation $operators = array('AND' => StringHelper::strtolower(JText::_('COM_FINDER_QUERY_OPERATOR_AND')), 'OR' => StringHelper::strtolower(JText::_('COM_FINDER_QUERY_OPERATOR_OR')), 'NOT' => StringHelper::strtolower(JText::_('COM_FINDER_QUERY_OPERATOR_NOT'))); // If language debugging is enabled you need to ignore the debug strings in matching. if (JDEBUG) { $debugStrings = array('**', '??'); $operators = str_replace($debugStrings, '', $operators); } /* * Iterate through the terms and perform any sorting that needs to be * done based on boolean search operators. Terms that are before an * and/or/not modifier have to be handled in relation to their operator. */ for ($i = 0, $c = count($terms); $i < $c; $i++) { // Check if the term is followed by an operator that we understand. if (isset($terms[$i + 1]) && in_array($terms[$i + 1], $operators)) { // Get the operator mode. $op = array_search($terms[$i + 1], $operators); // Handle the AND operator. if ($op === 'AND' && isset($terms[$i + 2])) { // Tokenize the current term. $token = FinderIndexerHelper::tokenize($terms[$i], $lang, true); $token = $this->getTokenData($token); // Set the required flag. $token->required = true; // Add the current token to the stack. $this->included[] = $token; $this->highlight = array_merge($this->highlight, array_keys($token->matches)); // Skip the next token (the mode operator). $this->operators[] = $terms[$i + 1]; // Tokenize the term after the next term (current plus two). $other = FinderIndexerHelper::tokenize($terms[$i + 2], $lang, true); $other = $this->getTokenData($other); // Set the required flag. $other->required = true; // Add the token after the next token to the stack. $this->included[] = $other; $this->highlight = array_merge($this->highlight, array_keys($other->matches)); // Remove the processed phrases if possible. if (($pk = array_search($terms[$i], $phrases)) !== false) { unset($phrases[$pk]); } if (($pk = array_search($terms[$i + 2], $phrases)) !== false) { unset($phrases[$pk]); } // Remove the processed terms. unset($terms[$i]); unset($terms[$i + 1]); unset($terms[$i + 2]); // Adjust the loop. $i += 2; continue; } elseif ($op === 'OR' && isset($terms[$i + 2])) { // Tokenize the current term. $token = FinderIndexerHelper::tokenize($terms[$i], $lang, true); $token = $this->getTokenData($token); // Set the required flag. $token->required = false; // Add the current token to the stack. if (count($token->matches)) { $this->included[] = $token; $this->highlight = array_merge($this->highlight, array_keys($token->matches)); } else { $this->ignored[] = $token; } // Skip the next token (the mode operator). $this->operators[] = $terms[$i + 1]; // Tokenize the term after the next term (current plus two). $other = FinderIndexerHelper::tokenize($terms[$i + 2], $lang, true); $other = $this->getTokenData($other); // Set the required flag. $other->required = false; // Add the token after the next token to the stack. if (count($other->matches)) { $this->included[] = $other; $this->highlight = array_merge($this->highlight, array_keys($other->matches)); } else { $this->ignored[] = $other; } // Remove the processed phrases if possible. if (($pk = array_search($terms[$i], $phrases)) !== false) { unset($phrases[$pk]); } if (($pk = array_search($terms[$i + 2], $phrases)) !== false) { unset($phrases[$pk]); } // Remove the processed terms. unset($terms[$i]); unset($terms[$i + 1]); unset($terms[$i + 2]); // Adjust the loop. $i += 2; continue; } } elseif (isset($terms[$i + 1]) && array_search($terms[$i], $operators) === 'OR') { // Skip the next token (the mode operator). $this->operators[] = $terms[$i]; // Tokenize the next term (current plus one). $other = FinderIndexerHelper::tokenize($terms[$i + 1], $lang, true); $other = $this->getTokenData($other); // Set the required flag. $other->required = false; // Add the token after the next token to the stack. if (count($other->matches)) { $this->included[] = $other; $this->highlight = array_merge($this->highlight, array_keys($other->matches)); } else { $this->ignored[] = $other; } // Remove the processed phrase if possible. if (($pk = array_search($terms[$i + 1], $phrases)) !== false) { unset($phrases[$pk]); } // Remove the processed terms. unset($terms[$i]); unset($terms[$i + 1]); // Adjust the loop. $i++; continue; } elseif (isset($terms[$i + 1]) && array_search($terms[$i], $operators) === 'NOT') { // Skip the next token (the mode operator). $this->operators[] = $terms[$i]; // Tokenize the next term (current plus one). $other = FinderIndexerHelper::tokenize($terms[$i + 1], $lang, true); $other = $this->getTokenData($other); // Set the required flag. $other->required = false; // Add the next token to the stack. if (count($other->matches)) { $this->excluded[] = $other; } else { $this->ignored[] = $other; } // Remove the processed phrase if possible. if (($pk = array_search($terms[$i + 1], $phrases)) !== false) { unset($phrases[$pk]); } // Remove the processed terms. unset($terms[$i]); unset($terms[$i + 1]); // Adjust the loop. $i++; continue; } } /* * Iterate through any search phrases and tokenize them. We handle * phrases as autonomous units and do not break them down into two and * three word combinations. */ for ($i = 0, $c = count($phrases); $i < $c; $i++) { // Tokenize the phrase. $token = FinderIndexerHelper::tokenize($phrases[$i], $lang, true); $token = $this->getTokenData($token); // Set the required flag. $token->required = true; // Add the current token to the stack. $this->included[] = $token; $this->highlight = array_merge($this->highlight, array_keys($token->matches)); // Remove the processed term if possible. if (($pk = array_search($phrases[$i], $terms)) !== false) { unset($terms[$pk]); } // Remove the processed phrase. unset($phrases[$i]); } /* * Handle any remaining tokens using the standard processing mechanism. */ if (!empty($terms)) { // Tokenize the terms. $terms = implode(' ', $terms); $tokens = FinderIndexerHelper::tokenize($terms, $lang, false); // Make sure we are working with an array. $tokens = is_array($tokens) ? $tokens : array($tokens); // Get the token data and required state for all the tokens. foreach ($tokens as $token) { // Get the token data. $token = $this->getTokenData($token); // Set the required flag for the token. $token->required = $mode === 'AND' ? $token->phrase ? false : true : false; // Add the token to the appropriate stack. if (count($token->matches) || $token->required) { $this->included[] = $token; $this->highlight = array_merge($this->highlight, array_keys($token->matches)); } else { $this->ignored[] = $token; } } } return true; }
/** * Abridges text strings over the specified character limit. The * behavior will insert an ellipsis into the text replacing a section * of variable size to ensure the string does not exceed the defined * maximum length. This method is UTF-8 safe. * * For example, it transforms "Really long title" to "Really...title". * * Note that this method does not scan for HTML tags so will potentially break them. * * @param string $text The text to abridge. * @param integer $length The maximum length of the text (default is 50). * @param integer $intro The maximum length of the intro text (default is 30). * * @return string The abridged text. * * @since 1.6 */ public static function abridge($text, $length = 50, $intro = 30) { // Abridge the item text if it is too long. if (StringHelper::strlen($text) > $length) { // Determine the remaining text length. $remainder = $length - ($intro + 3); // Extract the beginning and ending text sections. $beg = StringHelper::substr($text, 0, $intro); $end = StringHelper::substr($text, StringHelper::strlen($text) - $remainder); // Build the resulting string. $text = $beg . '...' . $end; } return $text; }
/** * Create workarounds for data to be cached * * @param string $data Cached data * @param array $options Array of options * * @return string Data to be cached * * @since 11.1 */ public static function setWorkarounds($data, $options = array()) { $loptions = array('nopathway' => 0, 'nohead' => 0, 'nomodules' => 0, 'modulemode' => 0); if (isset($options['nopathway'])) { $loptions['nopathway'] = $options['nopathway']; } if (isset($options['nohead'])) { $loptions['nohead'] = $options['nohead']; } if (isset($options['nomodules'])) { $loptions['nomodules'] = $options['nomodules']; } if (isset($options['modulemode'])) { $loptions['modulemode'] = $options['modulemode']; } $app = JFactory::getApplication(); $document = JFactory::getDocument(); if ($loptions['nomodules'] != 1) { // Get the modules buffer before component execution. $buffer1 = $document->getBuffer(); if (!is_array($buffer1)) { $buffer1 = array(); } // Make sure the module buffer is an array. if (!isset($buffer1['module']) || !is_array($buffer1['module'])) { $buffer1['module'] = array(); } } // View body data $cached['body'] = $data; // Document head data if ($loptions['nohead'] != 1 && method_exists($document, 'getHeadData')) { if ($loptions['modulemode'] == 1) { $headnow = $document->getHeadData(); $unset = array('title', 'description', 'link', 'links', 'metaTags'); foreach ($unset as $un) { unset($headnow[$un]); unset($options['headerbefore'][$un]); } $cached['head'] = array(); // Only store what this module has added foreach ($headnow as $now => $value) { if (isset($options['headerbefore'][$now])) { // We have to serialize the content of the arrays because the may contain other arrays which is a notice in PHP 5.4 and newer $nowvalue = array_map('serialize', $headnow[$now]); $beforevalue = array_map('serialize', $options['headerbefore'][$now]); $newvalue = array_diff_assoc($nowvalue, $beforevalue); $newvalue = array_map('unserialize', $newvalue); // Special treatment for script and style declarations. if (($now == 'script' || $now == 'style') && is_array($newvalue) && is_array($options['headerbefore'][$now])) { foreach ($newvalue as $type => $currentScriptStr) { if (isset($options['headerbefore'][$now][strtolower($type)])) { $oldScriptStr = $options['headerbefore'][$now][strtolower($type)]; if ($oldScriptStr != $currentScriptStr) { // Save only the appended declaration. $newvalue[strtolower($type)] = StringHelper::substr($currentScriptStr, StringHelper::strlen($oldScriptStr)); } } } } } else { $newvalue = $headnow[$now]; } if (!empty($newvalue)) { $cached['head'][$now] = $newvalue; } } } else { $cached['head'] = $document->getHeadData(); } } // Document MIME encoding $cached['mime_encoding'] = $document->getMimeEncoding(); // Pathway data if ($app->isSite() && $loptions['nopathway'] != 1) { $cached['pathway'] = is_array($data) && isset($data['pathway']) ? $data['pathway'] : $app->getPathway()->getPathway(); } if ($loptions['nomodules'] != 1) { // @todo Check if the following is needed, seems like it should be in page cache // Get the module buffer after component execution. $buffer2 = $document->getBuffer(); if (!is_array($buffer2)) { $buffer2 = array(); } // Make sure the module buffer is an array. if (!isset($buffer2['module']) || !is_array($buffer2['module'])) { $buffer2['module'] = array(); } // Compare the second module buffer against the first buffer. $cached['module'] = array_diff_assoc($buffer2['module'], $buffer1['module']); } // Headers data if (isset($options['headers']) && $options['headers']) { $cached['headers'] = $app->getHeaders(); } return $cached; }
/** * Groups items by date * * @param array $list list of items * @param string $type type of grouping * @param string $article_grouping_direction ordering direction * @param string $month_year_format date format to use * * @return array * * @since 1.6 */ public static function groupByDate($list, $type = 'year', $article_grouping_direction, $month_year_format = 'F Y') { $grouped = array(); if (!is_array($list)) { if ($list == '') { return $grouped; } $list = array($list); } foreach ($list as $key => $item) { switch ($type) { case 'month_year': $month_year = StringHelper::substr($item->created, 0, 7); if (!isset($grouped[$month_year])) { $grouped[$month_year] = array(); } $grouped[$month_year][$key] = $item; break; case 'year': default: $year = StringHelper::substr($item->created, 0, 4); if (!isset($grouped[$year])) { $grouped[$year] = array(); } $grouped[$year][$key] = $item; break; } unset($list[$key]); } $article_grouping_direction($grouped); if ($type === 'month_year') { foreach ($grouped as $group => $items) { $date = new JDate($group); $formatted_group = $date->format($month_year_format); $grouped[$formatted_group] = $items; unset($grouped[$group]); } } return $grouped; }
// Get the mime type class. $mime = !empty($this->result->mime) ? 'mime-' . $this->result->mime : null; $show_description = $this->params->get('show_description', 1); if ($show_description) { // Calculate number of characters to display around the result $term_length = StringHelper::strlen($this->query->input); $desc_length = $this->params->get('description_length', 255); $pad_length = $term_length < $desc_length ? (int) floor(($desc_length - $term_length) / 2) : 0; // Find the position of the search term $pos = $term_length ? StringHelper::strpos(StringHelper::strtolower($this->result->description), StringHelper::strtolower($this->query->input)) : false; // Find a potential start point $start = $pos && $pos > $pad_length ? $pos - $pad_length : 0; // Find a space between $start and $pos, start right after it. $space = StringHelper::strpos($this->result->description, ' ', $start > 0 ? $start - 1 : 0); $start = $space && $space < $pos ? $space + 1 : $start; $description = JHtml::_('string.truncate', StringHelper::substr($this->result->description, $start), $desc_length, true); } $route = $this->result->route; // Get the route with highlighting information. if (!empty($this->query->highlight) && empty($this->result->mime) && $this->params->get('highlight_terms', 1) && JPluginHelper::isEnabled('system', 'highlight')) { $route .= '&highlight=' . base64_encode(json_encode($this->query->highlight)); } ?> <li> <h4 class="result-title <?php echo $mime; ?> "> <a href="<?php echo JRoute::_($route);