Example #1
0
 /**
  * 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;
 }
Example #2
0
 /**
  * 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;
 }
Example #3
0
 /**
  * Method to tokenize a text string.
  *
  * @param   string   $input   The input to tokenize.
  * @param   string   $lang    The language of the input.
  * @param   boolean  $phrase  Flag to indicate whether input could be a phrase. [optional]
  *
  * @return  array  An array of FinderIndexerToken objects.
  *
  * @since   2.5
  */
 public static function tokenize($input, $lang, $phrase = false)
 {
     static $cache;
     $store = StringHelper::strlen($input) < 128 ? md5($input . '::' . $lang . '::' . $phrase) : null;
     // Check if the string has been tokenized already.
     if ($store && isset($cache[$store])) {
         return $cache[$store];
     }
     $tokens = array();
     $quotes = html_entity_decode('&#8216;&#8217;&#39;', ENT_QUOTES, 'UTF-8');
     // Get the simple language key.
     $lang = static::getPrimaryLanguage($lang);
     /*
      * Parsing the string input into terms is a multi-step process.
      *
      * Regexes:
      *  1. Remove everything except letters, numbers, quotes, apostrophe, plus, dash, period, and comma.
      *  2. Remove plus, dash, period, and comma characters located before letter characters.
      *  3. Remove plus, dash, period, and comma characters located after other characters.
      *  4. Remove plus, period, and comma characters enclosed in alphabetical characters. Ungreedy.
      *  5. Remove orphaned apostrophe, plus, dash, period, and comma characters.
      *  6. Remove orphaned quote characters.
      *  7. Replace the assorted single quotation marks with the ASCII standard single quotation.
      *  8. Remove multiple space characters and replaces with a single space.
      */
     $input = StringHelper::strtolower($input);
     $input = preg_replace('#[^\\pL\\pM\\pN\\p{Pi}\\p{Pf}\'+-.,]+#mui', ' ', $input);
     $input = preg_replace('#(^|\\s)[+-.,]+([\\pL\\pM]+)#mui', ' $1', $input);
     $input = preg_replace('#([\\pL\\pM\\pN]+)[+-.,]+(\\s|$)#mui', '$1 ', $input);
     $input = preg_replace('#([\\pL\\pM]+)[+.,]+([\\pL\\pM]+)#muiU', '$1 $2', $input);
     $input = preg_replace('#(^|\\s)[\'+-.,]+(\\s|$)#mui', ' ', $input);
     $input = preg_replace('#(^|\\s)[\\p{Pi}\\p{Pf}]+(\\s|$)#mui', ' ', $input);
     $input = preg_replace('#[' . $quotes . ']+#mui', '\'', $input);
     $input = preg_replace('#\\s+#mui', ' ', $input);
     $input = StringHelper::trim($input);
     // Explode the normalized string to get the terms.
     $terms = explode(' ', $input);
     /*
      * If we have Unicode support and are dealing with Chinese text, Chinese
      * has to be handled specially because there are not necessarily any spaces
      * between the "words". So, we have to test if the words belong to the Chinese
      * character set and if so, explode them into single glyphs or "words".
      */
     if ($lang === 'zh') {
         // Iterate through the terms and test if they contain Chinese.
         for ($i = 0, $n = count($terms); $i < $n; $i++) {
             $charMatches = array();
             $charCount = preg_match_all('#[\\p{Han}]#mui', $terms[$i], $charMatches);
             // Split apart any groups of Chinese characters.
             for ($j = 0; $j < $charCount; $j++) {
                 $tSplit = StringHelper::str_ireplace($charMatches[0][$j], '', $terms[$i], false);
                 if (!empty($tSplit)) {
                     $terms[$i] = $tSplit;
                 } else {
                     unset($terms[$i]);
                 }
                 $terms[] = $charMatches[0][$j];
             }
         }
         // Reset array keys.
         $terms = array_values($terms);
     }
     /*
      * If we have to handle the input as a phrase, that means we don't
      * tokenize the individual terms and we do not create the two and three
      * term combinations. The phrase must contain more than one word!
      */
     if ($phrase === true && count($terms) > 1) {
         // Create tokens from the phrase.
         $tokens[] = new FinderIndexerToken($terms, $lang);
     } else {
         // Create tokens from the terms.
         for ($i = 0, $n = count($terms); $i < $n; $i++) {
             $tokens[] = new FinderIndexerToken($terms[$i], $lang);
         }
         // Create two and three word phrase tokens from the individual words.
         for ($i = 0, $n = count($tokens); $i < $n; $i++) {
             // Setup the phrase positions.
             $i2 = $i + 1;
             $i3 = $i + 2;
             // Create the two word phrase.
             if ($i2 < $n && isset($tokens[$i2])) {
                 // Tokenize the two word phrase.
                 $token = new FinderIndexerToken(array($tokens[$i]->term, $tokens[$i2]->term), $lang, $lang === 'zh' ? '' : ' ');
                 $token->derived = true;
                 // Add the token to the stack.
                 $tokens[] = $token;
             }
             // Create the three word phrase.
             if ($i3 < $n && isset($tokens[$i3])) {
                 // Tokenize the three word phrase.
                 $token = new FinderIndexerToken(array($tokens[$i]->term, $tokens[$i2]->term, $tokens[$i3]->term), $lang, $lang === 'zh' ? '' : ' ');
                 $token->derived = true;
                 // Add the token to the stack.
                 $tokens[] = $token;
             }
         }
     }
     if ($store) {
         $cache[$store] = count($tokens) > 1 ? $tokens : array_shift($tokens);
         return $cache[$store];
     } else {
         return count($tokens) > 1 ? $tokens : array_shift($tokens);
     }
 }
Example #4
0
 /**
  * Method to construct the token object.
  *
  * @param   mixed   $term    The term as a string for words or an array for phrases.
  * @param   string  $lang    The simple language identifier.
  * @param   string  $spacer  The space separator for phrases. [optional]
  *
  * @since   2.5
  */
 public function __construct($term, $lang, $spacer = ' ')
 {
     $this->language = $lang;
     // Tokens can be a single word or an array of words representing a phrase.
     if (is_array($term)) {
         // Populate the token instance.
         $this->term = implode($spacer, $term);
         $this->stem = implode($spacer, array_map(array('FinderIndexerHelper', 'stem'), $term, array($lang)));
         $this->numeric = false;
         $this->common = false;
         $this->phrase = true;
         $this->length = StringHelper::strlen($this->term);
         /*
          * Calculate the weight of the token.
          *
          * 1. Length of the token up to 30 and divide by 30, add 1.
          * 2. Round weight to 4 decimal points.
          */
         $this->weight = ($this->length >= 30 ? 30 : $this->length) / 30 + 1;
         $this->weight = round($this->weight, 4);
     } else {
         // Populate the token instance.
         $this->term = $term;
         $this->stem = FinderIndexerHelper::stem($this->term, $lang);
         $this->numeric = is_numeric($this->term) || (bool) preg_match('#^[0-9,.\\-\\+]+$#', $this->term);
         $this->common = $this->numeric ? false : FinderIndexerHelper::isCommon($this->term, $lang);
         $this->phrase = false;
         $this->length = StringHelper::strlen($this->term);
         /*
          * Calculate the weight of the token.
          *
          * 1. Length of the token up to 15 and divide by 15.
          * 2. If common term, divide weight by 8.
          * 3. If numeric, multiply weight by 1.5.
          * 4. Round weight to 4 decimal points.
          */
         $this->weight = ($this->length >= 15 ? 15 : $this->length) / 15;
         $this->weight = $this->common == true ? $this->weight / 8 : $this->weight;
         $this->weight = $this->numeric == true ? $this->weight * 1.5 : $this->weight;
         $this->weight = round($this->weight, 4);
     }
 }
Example #5
0
 /**
  * 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);
 }
Example #6
0
 /**
  * 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 ? '...&#160;' : '') . StringHelper::substr($text, $pos, $chunk_size) . '&#160;...';
     } else {
         if (($wordpos = @StringHelper::strpos($text, ' ', $length)) !== false) {
             return StringHelper::substr($text, 0, $wordpos) . '&#160;...';
         } else {
             return StringHelper::substr($text, 0, $length);
         }
     }
 }
Example #7
0
 /**
  * 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('&#8216;&#8217;&#39;', 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;
 }
Example #8
0
 /**
  * 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;
 }
Example #9
0
 /**
  * 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;
 }
Example #10
0
/**
 * @package     Joomla.Site
 * @subpackage  com_finder
 *
 * @copyright   Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */
defined('_JEXEC') or die;
use Joomla\String\StringHelper;
// 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));