diff --git a/administrator/components/com_finder/access.xml b/administrator/components/com_finder/access.xml deleted file mode 100644 index 7d09d2cbf1294..0000000000000 --- a/administrator/components/com_finder/access.xml +++ /dev/null @@ -1,12 +0,0 @@ - - -
- - - - - - - -
-
diff --git a/administrator/components/com_finder/config.xml b/administrator/components/com_finder/config.xml deleted file mode 100644 index a821957fbd7b3..0000000000000 --- a/administrator/components/com_finder/config.xml +++ /dev/null @@ -1,285 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
diff --git a/administrator/components/com_finder/controller.php b/administrator/components/com_finder/controller.php deleted file mode 100644 index b8de88f93b705..0000000000000 --- a/administrator/components/com_finder/controller.php +++ /dev/null @@ -1,57 +0,0 @@ -input->get('view', 'index', 'word'); - $layout = $this->input->get('layout', 'index', 'word'); - $f_id = $this->input->get('filter_id', null, 'int'); - - // Check for edit form. - if ($view == 'filter' && $layout == 'edit' && !$this->checkEditId('com_finder.edit.filter', $f_id)) - { - // Somehow the person just went to the form - we don't allow that. - $this->setMessage(JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $f_id), 'error'); - $this->setRedirect(JRoute::_('index.php?option=com_finder&view=filters', false)); - - return false; - } - - return parent::display(); - } -} diff --git a/administrator/components/com_finder/finder.php b/administrator/components/com_finder/finder.php deleted file mode 100644 index 49f37bc9b2cac..0000000000000 --- a/administrator/components/com_finder/finder.php +++ /dev/null @@ -1,19 +0,0 @@ -authorise('core.manage', 'com_finder')) -{ - throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403); -} - -$controller = JControllerLegacy::getInstance('Finder'); -$controller->execute(JFactory::getApplication()->input->get('task')); -$controller->redirect(); diff --git a/administrator/components/com_finder/finder.xml b/administrator/components/com_finder/finder.xml deleted file mode 100644 index 5967bc0b2ef04..0000000000000 --- a/administrator/components/com_finder/finder.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - com_finder - Joomla! Project - (C) 2005 - 2016 Open Source Matters. All rights reserved. - August 2011 - GNU General Public License version 2 or later; see LICENSE.txt - admin@joomla.org - www.joomla.org - 3.0.0 - COM_FINDER_XML_DESCRIPTION - COM_FINDER - - controller.php - finder.php - router.php - controllers - helpers - models - views - - - js - css - - - - sql/install.mysql.sql - sql/install.postgresql.sql - - - - - sql/uninstall.mysql.sql - sql/uninstall.postgresql.sql - - - - language/en-GB.com_finder.ini - - - - access.xml - config.xml - controller.php - finder.php - controllers - helpers - models - sql - tables - views - - - language/en-GB.com_finder.ini - language/en-GB.com_finder.sys.ini - - COM_FINDER - - diff --git a/administrator/components/com_finder/helpers/finder.php b/administrator/components/com_finder/helpers/finder.php deleted file mode 100644 index 9a0f44d727ad3..0000000000000 --- a/administrator/components/com_finder/helpers/finder.php +++ /dev/null @@ -1,100 +0,0 @@ -getQuery(true) - ->select($db->quoteName('extension_id')) - ->from($db->quoteName('#__extensions')) - ->where($db->quoteName('folder') . ' = ' . $db->quote('content')) - ->where($db->quoteName('element') . ' = ' . $db->quote('finder')); - $db->setQuery($query); - - try - { - $result = (int) $db->loadResult(); - } - catch (RuntimeException $e) - { - JError::raiseWarning(500, $e->getMessage()); - } - - return $result; - } - - /** - * Gets a list of the actions that can be performed. - * - * @return JObject A JObject containing the allowed actions. - * - * @since 2.5 - * @deprecated 3.2 Use JHelperContent::getActions() instead - */ - public static function getActions() - { - // Log usage of deprecated function - JLog::add(__METHOD__ . '() is deprecated, use JHelperContent::getActions() with new arguments order instead.', JLog::WARNING, 'deprecated'); - - // Get list of actions - return JHelperContent::getActions('com_finder'); - } -} diff --git a/administrator/components/com_finder/helpers/indexer/stemmer.php b/administrator/components/com_finder/helpers/indexer/stemmer.php deleted file mode 100644 index 3061a2de9b2b5..0000000000000 --- a/administrator/components/com_finder/helpers/indexer/stemmer.php +++ /dev/null @@ -1,83 +0,0 @@ -clean($adapter, 'cmd'); - $path = __DIR__ . '/stemmer/' . $adapter . '.php'; - $class = 'FinderIndexerStemmer' . ucfirst($adapter); - - // Check if a stemmer exists for the adapter. - if (!file_exists($path)) - { - // Throw invalid adapter exception. - throw new Exception(JText::sprintf('COM_FINDER_INDEXER_INVALID_STEMMER', $adapter)); - } - - // Instantiate the stemmer. - JLoader::register($class, $path); - $instances[$adapter] = new $class; - - return $instances[$adapter]; - } - - /** - * Method to stem a token and return the root. - * - * @param string $token The token to stem. - * @param string $lang The language of the token. - * - * @return string The root token. - * - * @since 2.5 - */ - abstract public function stem($token, $lang); -} diff --git a/administrator/components/com_finder/helpers/indexer/stemmer/fr.php b/administrator/components/com_finder/helpers/indexer/stemmer/fr.php deleted file mode 100644 index 7f40a5ed832ef..0000000000000 --- a/administrator/components/com_finder/helpers/indexer/stemmer/fr.php +++ /dev/null @@ -1,265 +0,0 @@ -cache[$lang][$token])) - { - // Stem the token. - $result = self::getStem($token); - - // Add the token to the cache. - $this->cache[$lang][$token] = $result; - } - - return $this->cache[$lang][$token]; - } - - /** - * French stemmer rules variables. - * - * @return array The rules - * - * @since 3.0 - */ - protected static function getStemRules() - { - if (self::$stemRules) - { - return self::$stemRules; - } - - $vars = array(); - - // French accented letters in ISO-8859-1 encoding - $vars['accents'] = chr(224) . chr(226) . chr(232) . chr(233) . chr(234) . chr(235) . chr(238) . chr(239) - . chr(244) . chr(251) . chr(249) . chr(231); - - // The rule patterns include all accented words for french language - $vars['rule_pattern'] = "/^([a-z" . $vars['accents'] . "]*)(\*){0,1}(\d)([a-z" . $vars['accents'] . "]*)([.|>])/"; - - // French vowels (including y) in ISO-8859-1 encoding - $vars['vowels'] = chr(97) . chr(224) . chr(226) . chr(101) . chr(232) . chr(233) . chr(234) . chr(235) - . chr(105) . chr(238) . chr(239) . chr(111) . chr(244) . chr(117) . chr(251) . chr(249) . chr(121); - - // The French rules in ISO-8859-1 encoding - $vars['rules'] = array( - 'esre1>', 'esio1>', 'siol1.', 'siof0.', 'sioe0.', 'sio3>', 'st1>', 'sf1>', 'sle1>', 'slo1>', 's' . chr(233) . '1>', chr(233) . 'tuae5.', - chr(233) . 'tuae2.', 'tnia0.', 'tniv1.', 'tni3>', 'suor1.', 'suo0.', 'sdrail5.', 'sdrai4.', 'er' . chr(232) . 'i1>', 'sesue3x>', - 'esuey5i.', 'esue2x>', 'se1>', 'er' . chr(232) . 'g3.', 'eca1>', 'esiah0.', 'esi1>', 'siss2.', 'sir2>', 'sit2>', 'egan' . chr(233) . '1.', - 'egalli6>', 'egass1.', 'egas0.', 'egat3.', 'ega3>', 'ette4>', 'ett2>', 'etio1.', 'tio' . chr(231) . '4c.', 'tio0.', 'et1>', 'eb1>', - 'snia1>', 'eniatnau8>', 'eniatn4.', 'enia1>', 'niatnio3.', 'niatg3.', 'e' . chr(233) . '1>', chr(233) . 'hcat1.', chr(233) . 'hca4.', - chr(233) . 'tila5>', chr(233) . 'tici5.', chr(233) . 'tir1.', chr(233) . 'ti3>', chr(233) . 'gan1.', chr(233) . 'ga3>', - chr(233) . 'tehc1.', chr(233) . 'te3>', chr(233) . 'it0.', chr(233) . '1>', 'eire4.', 'eirue5.', 'eio1.', 'eia1.', 'ei1>', 'eng1.', - 'xuaessi7.', 'xuae1>', 'uaes0.', 'uae3.', 'xuave2l.', 'xuav2li>', 'xua3la>', 'ela1>', 'lart2.', 'lani2>', 'la' . chr(233) . '2>', - 'siay4i.', 'siassia7.', 'siarv1*.', 'sia1>', 'tneiayo6i.', 'tneiay6i.', 'tneiassia9.', 'tneiareio7.', 'tneia5>', 'tneia4>', 'tiario4.', - 'tiarim3.', 'tiaria3.', 'tiaris3.', 'tiari5.', 'tiarve6>', 'tiare5>', 'iare4>', 'are3>', 'tiay4i.', 'tia3>', 'tnay4i.', - 'em' . chr(232) . 'iu5>', 'em' . chr(232) . 'i4>', 'tnaun3.', 'tnauqo3.', 'tnau4>', 'tnaf0.', 'tnat' . chr(233) . '2>', 'tna3>', 'tno3>', - 'zeiy4i.', 'zey3i.', 'zeire5>', 'zeird4.', 'zeirio4.', 'ze2>', 'ssiab0.', 'ssia4.', 'ssi3.', 'tnemma6>', 'tnemesuey9i.', 'tnemesue8>', - 'tnemevi7.', 'tnemessia5.', 'tnemessi8.', 'tneme5>', 'tnemia4.', 'tnem' . chr(233) . '5>', 'el2l>', 'lle3le>', 'let' . chr(244) . '0.', - 'lepp0.', 'le2>', 'srei1>', 'reit3.', 'reila2.', 'rei3>', 'ert' . chr(226) . 'e5.', 'ert' . chr(226) . chr(233) . '1.', - 'ert' . chr(226) . '4.', 'drai4.', 'erdro0.', 'erute5.', 'ruta0.', 'eruta1.', 'erutiov1.', 'erub3.', 'eruh3.', 'erul3.', 'er2r>', 'nn1>', - 'r' . chr(232) . 'i3.', 'srev0.', 'sr1>', 'rid2>', 're2>', 'xuei4.', 'esuei5.', 'lbati3.', 'lba3>', 'rueis0.', 'ruehcn4.', 'ecirta6.', - 'ruetai6.', 'rueta5.', 'rueir0.', 'rue3>', 'esseti6.', 'essere6>', 'esserd1.', 'esse4>', 'essiab1.', 'essia5.', 'essio1.', 'essi4.', - 'essal4.', 'essa1>', 'ssab1.', 'essurp1.', 'essu4.', 'essi1.', 'ssor1.', 'essor2.', 'esso1>', 'ess2>', 'tio3.', 'r' . chr(232) . 's2re.', - 'r' . chr(232) . '0e.', 'esn1.', 'eu1>', 'sua0.', 'su1>', 'utt1>', 'tu' . chr(231) . '3c.', 'u' . chr(231) . '2c.', 'ur1.', 'ehcn2>', - 'ehcu1>', 'snorr3.', 'snoru3.', 'snorua3.', 'snorv3.', 'snorio4.', 'snori5.', 'snore5>', 'snortt4>', 'snort' . chr(238) . 'a7.', 'snort3.', - 'snor4.', 'snossi6.', 'snoire6.', 'snoird5.', 'snoitai7.', 'snoita6.', 'snoits1>', 'noits0.', 'snoi4>', 'noitaci7>', 'noitai6.', 'noita5.', - 'noitu4.', 'noi3>', 'snoya0.', 'snoy4i.', 'sno' . chr(231) . 'a1.', 'sno' . chr(231) . 'r1.', 'snoe4.', 'snosiar1>', 'snola1.', 'sno3>', - 'sno1>', 'noll2.', 'tnennei4.', 'ennei2>', 'snei1>', 'sne' . chr(233) . '1>', 'enne' . chr(233) . '5e.', 'ne' . chr(233) . '3e.', 'neic0.', - 'neiv0.', 'nei3.', 'sc1.', 'sd1.', 'sg1.', 'sni1.', 'tiu0.', 'ti2.', 'sp1>', 'sna1>', 'sue1.', 'enn2>', 'nong2.', 'noss2.', 'rioe4.', - 'riot0.', 'riorc1.', 'riovec5.', 'rio3.', 'ric2.', 'ril2.', 'tnerim3.', 'tneris3>', 'tneri5.', 't' . chr(238) . 'a3.', 'riss2.', - 't' . chr(238) . '2.', 't' . chr(226) . '2>', 'ario2.', 'arim1.', 'ara1.', 'aris1.', 'ari3.', 'art1>', 'ardn2.', 'arr1.', 'arua1.', - 'aro1.', 'arv1.', 'aru1.', 'ar2.', 'rd1.', 'ud1.', 'ul1.', 'ini1.', 'rin2.', 'tnessiab3.', 'tnessia7.', 'tnessi6.', 'tnessni4.', 'sini2.', - 'sl1.', 'iard3.', 'iario3.', 'ia2>', 'io0.', 'iule2.', 'i1>', 'sid2.', 'sic2.', 'esoi4.', 'ed1.', 'ai2>', 'a1>', 'adr1.', - 'tner' . chr(232) . '5>', 'evir1.', 'evio4>', 'evi3.', 'fita4.', 'fi2>', 'enie1.', 'sare4>', 'sari4>', 'sard3.', 'sart2>', 'sa2.', - 'tnessa6>', 'tnessu6>', 'tnegna3.', 'tnegi3.', 'tneg0.', 'tneru5>', 'tnemg0.', 'tnerni4.', 'tneiv1.', 'tne3>', 'une1.', 'en1>', 'nitn2.', - 'ecnay5i.', 'ecnal1.', 'ecna4.', 'ec1>', 'nn1.', 'rit2>', 'rut2>', 'rud2.', 'ugn1>', 'eg1>', 'tuo0.', 'tul2>', 't' . chr(251) . '2>', - 'ev1>', 'v' . chr(232) . '2ve>', 'rtt1>', 'emissi6.', 'em1.', 'ehc1.', 'c' . chr(233) . 'i2c' . chr(232) . '.', 'libi2l.', 'llie1.', - 'liei4i.', 'xuev1.', 'xuey4i.', 'xueni5>', 'xuell4.', 'xuere5.', 'xue3>', 'rb' . chr(233) . '3rb' . chr(232) . '.', 'tur2.', - 'rir' . chr(233) . '4re.', 'rir2.', 'c' . chr(226) . '2ca.', 'snu1.', 'rt' . chr(238) . 'a4.', 'long2.', 'vec2.', chr(231) . '1c>', - 'ssilp3.', 'silp2.', 't' . chr(232) . 'hc2te.', 'n' . chr(232) . 'm2ne.', 'llepp1.', 'tan2.', 'rv' . chr(232) . '3rve.', - 'rv' . chr(233) . '3rve.', 'r' . chr(232) . '2re.', 'r' . chr(233) . '2re.', 't' . chr(232) . '2te.', 't' . chr(233) . '2te.', 'epp1.', - 'eya2i.', 'ya1i.', 'yo1i.', 'esu1.', 'ugi1.', 'tt1.', 'end0.' - ); - - self::$stemRules = $vars; - - return self::$stemRules; - } - - /** - * Returns the number of the first rule from the rule number - * that can be applied to the given reversed input. - * returns -1 if no rule can be applied, ie the stem has been found - * - * @param string $reversed_input The input to check in reversed order - * @param integer $rule_number The rule number to check - * - * @return integer Number of the first rule - * - * @since 3.0 - */ - private static function getFirstRule($reversed_input, $rule_number) - { - $vars = static::getStemRules(); - - $nb_rules = count($vars['rules']); - - for ($i = $rule_number; $i < $nb_rules; $i++) - { - // Gets the letters from the current rule - $rule = $vars['rules'][$i]; - $rule = preg_replace($vars['rule_pattern'], "\\1", $rule); - - if (strncasecmp(utf8_decode($rule), $reversed_input, strlen(utf8_decode($rule))) == 0) - { - return $i; - } - } - - return -1; - } - - /** - * Check the acceptability of a stem for French language - * - * @param string $reversed_stem The stem to check in reverse form - * - * @return boolean True if stem is acceptable - * - * @since 3.0 - */ - private static function check($reversed_stem) - { - $vars = static::getStemRules(); - - if (preg_match('/[' . $vars['vowels'] . ']$/', utf8_encode($reversed_stem))) - { - // If the form starts with a vowel then at least two letters must remain after stemming (e.g.: "etaient" --> "et") - return (strlen($reversed_stem) > 2); - } - else - { - // If the reversed stem starts with a consonant then at least two letters must remain after stemming - if (strlen($reversed_stem) <= 2) - { - return false; - } - - // And at least one of these must be a vowel or "y" - return (preg_match('/[' . $vars['vowels'] . ']/', utf8_encode($reversed_stem))); - } - } - - /** - * Paice/Husk stemmer which returns a stem for the given $input - * - * @param string $input The word for which we want the stem in UTF-8 - * - * @return string The stem - * - * @since 3.0 - */ - private static function getStem($input) - { - $vars = static::getStemRules(); - - $intact = true; - $reversed_input = strrev(utf8_decode($input)); - $rule_number = 0; - - // This loop goes through the rules' array until it finds an ending one (ending by '.') or the last one ('end0.') - while (true) - { - $rule_number = self::getFirstRule($reversed_input, $rule_number); - - if ($rule_number == -1) - { - // No other rule can be applied => the stem has been found - break; - } - - $rule = $vars['rules'][$rule_number]; - preg_match($vars['rule_pattern'], $rule, $matches); - - if (($matches[2] != '*') || ($intact)) - { - $reversed_stem = utf8_decode($matches[4]) . substr($reversed_input, $matches[3], strlen($reversed_input) - $matches[3]); - - if (self::check($reversed_stem)) - { - $reversed_input = $reversed_stem; - - if ($matches[5] == '.') - { - break; - } - } - else - { - // Go to another rule - $rule_number++; - } - } - else - { - // Go to another rule - $rule_number++; - } - } - - return utf8_encode(strrev($reversed_input)); - } -} diff --git a/administrator/components/com_finder/helpers/indexer/stemmer/porter_en.php b/administrator/components/com_finder/helpers/indexer/stemmer/porter_en.php deleted file mode 100644 index 340a82d1e3f07..0000000000000 --- a/administrator/components/com_finder/helpers/indexer/stemmer/porter_en.php +++ /dev/null @@ -1,446 +0,0 @@ -cache[$lang][$token])) - { - // Stem the token. - $result = $token; - $result = self::step1ab($result); - $result = self::step1c($result); - $result = self::step2($result); - $result = self::step3($result); - $result = self::step4($result); - $result = self::step5($result); - - // Add the token to the cache. - $this->cache[$lang][$token] = $result; - } - - return $this->cache[$lang][$token]; - } - - /** - * Step 1 - * - * @param string $word The token to stem. - * - * @return string - * - * @since 2.5 - */ - private static function step1ab($word) - { - // Part a - if (substr($word, -1) == 's') - { - self::replace($word, 'sses', 'ss') - or self::replace($word, 'ies', 'i') - or self::replace($word, 'ss', 'ss') - or self::replace($word, 's', ''); - } - - // Part b - if (substr($word, -2, 1) != 'e' or !self::replace($word, 'eed', 'ee', 0)) - { - // First rule - $v = self::$regex_vowel; - - // Words ending with ing and ed - // Note use of && and OR, for precedence reasons - if (preg_match("#$v+#", substr($word, 0, -3)) && self::replace($word, 'ing', '') - or preg_match("#$v+#", substr($word, 0, -2)) && self::replace($word, 'ed', '')) - { - // If one of above two test successful - if (!self::replace($word, 'at', 'ate') and !self::replace($word, 'bl', 'ble') and !self::replace($word, 'iz', 'ize')) - { - // Double consonant ending - if (self::doubleConsonant($word) and substr($word, -2) != 'll' and substr($word, -2) != 'ss' and substr($word, -2) != 'zz') - { - $word = substr($word, 0, -1); - } - elseif (self::m($word) == 1 and self::cvc($word)) - { - $word .= 'e'; - } - } - } - } - - return $word; - } - - /** - * Step 1c - * - * @param string $word The token to stem. - * - * @return string - * - * @since 2.5 - */ - private static function step1c($word) - { - $v = self::$regex_vowel; - - if (substr($word, -1) == 'y' && preg_match("#$v+#", substr($word, 0, -1))) - { - self::replace($word, 'y', 'i'); - } - - return $word; - } - - /** - * Step 2 - * - * @param string $word The token to stem. - * - * @return string - * - * @since 2.5 - */ - private static function step2($word) - { - switch (substr($word, -2, 1)) - { - case 'a': - self::replace($word, 'ational', 'ate', 0) - or self::replace($word, 'tional', 'tion', 0); - break; - case 'c': - self::replace($word, 'enci', 'ence', 0) - or self::replace($word, 'anci', 'ance', 0); - break; - case 'e': - self::replace($word, 'izer', 'ize', 0); - break; - case 'g': - self::replace($word, 'logi', 'log', 0); - break; - case 'l': - self::replace($word, 'entli', 'ent', 0) - or self::replace($word, 'ousli', 'ous', 0) - or self::replace($word, 'alli', 'al', 0) - or self::replace($word, 'bli', 'ble', 0) - or self::replace($word, 'eli', 'e', 0); - break; - case 'o': - self::replace($word, 'ization', 'ize', 0) - or self::replace($word, 'ation', 'ate', 0) - or self::replace($word, 'ator', 'ate', 0); - break; - case 's': - self::replace($word, 'iveness', 'ive', 0) - or self::replace($word, 'fulness', 'ful', 0) - or self::replace($word, 'ousness', 'ous', 0) - or self::replace($word, 'alism', 'al', 0); - break; - case 't': - self::replace($word, 'biliti', 'ble', 0) - or self::replace($word, 'aliti', 'al', 0) - or self::replace($word, 'iviti', 'ive', 0); - break; - } - - return $word; - } - - /** - * Step 3 - * - * @param string $word The token to stem. - * - * @return string - * - * @since 2.5 - */ - private static function step3($word) - { - switch (substr($word, -2, 1)) - { - case 'a': - self::replace($word, 'ical', 'ic', 0); - break; - case 's': - self::replace($word, 'ness', '', 0); - break; - case 't': - self::replace($word, 'icate', 'ic', 0) - or self::replace($word, 'iciti', 'ic', 0); - break; - case 'u': - self::replace($word, 'ful', '', 0); - break; - case 'v': - self::replace($word, 'ative', '', 0); - break; - case 'z': - self::replace($word, 'alize', 'al', 0); - break; - } - - return $word; - } - - /** - * Step 4 - * - * @param string $word The token to stem. - * - * @return string - * - * @since 2.5 - */ - private static function step4($word) - { - switch (substr($word, -2, 1)) - { - case 'a': - self::replace($word, 'al', '', 1); - break; - case 'c': - self::replace($word, 'ance', '', 1) - or self::replace($word, 'ence', '', 1); - break; - case 'e': - self::replace($word, 'er', '', 1); - break; - case 'i': - self::replace($word, 'ic', '', 1); - break; - case 'l': - self::replace($word, 'able', '', 1) - or self::replace($word, 'ible', '', 1); - break; - case 'n': - self::replace($word, 'ant', '', 1) - or self::replace($word, 'ement', '', 1) - or self::replace($word, 'ment', '', 1) - or self::replace($word, 'ent', '', 1); - break; - case 'o': - if (substr($word, -4) == 'tion' or substr($word, -4) == 'sion') - { - self::replace($word, 'ion', '', 1); - } - else - { - self::replace($word, 'ou', '', 1); - } - break; - case 's': - self::replace($word, 'ism', '', 1); - break; - case 't': - self::replace($word, 'ate', '', 1) - or self::replace($word, 'iti', '', 1); - break; - case 'u': - self::replace($word, 'ous', '', 1); - break; - case 'v': - self::replace($word, 'ive', '', 1); - break; - case 'z': - self::replace($word, 'ize', '', 1); - break; - } - - return $word; - } - - /** - * Step 5 - * - * @param string $word The token to stem. - * - * @return string - * - * @since 2.5 - */ - private static function step5($word) - { - // Part a - if (substr($word, -1) == 'e') - { - if (self::m(substr($word, 0, -1)) > 1) - { - self::replace($word, 'e', ''); - } - elseif (self::m(substr($word, 0, -1)) == 1) - { - if (!self::cvc(substr($word, 0, -1))) - { - self::replace($word, 'e', ''); - } - } - } - - // Part b - if (self::m($word) > 1 and self::doubleConsonant($word) and substr($word, -1) == 'l') - { - $word = substr($word, 0, -1); - } - - return $word; - } - - /** - * Replaces the first string with the second, at the end of the string. If third - * arg is given, then the preceding string must match that m count at least. - * - * @param string &$str String to check - * @param string $check Ending to check for - * @param string $repl Replacement string - * @param integer $m Optional minimum number of m() to meet - * - * @return boolean Whether the $check string was at the end - * of the $str string. True does not necessarily mean - * that it was replaced. - * - * @since 2.5 - */ - private static function replace(&$str, $check, $repl, $m = null) - { - $len = 0 - strlen($check); - - if (substr($str, $len) == $check) - { - $substr = substr($str, 0, $len); - - if (is_null($m) or self::m($substr) > $m) - { - $str = $substr . $repl; - } - - return true; - } - - return false; - } - - /** - * m() measures the number of consonant sequences in $str. if c is - * a consonant sequence and v a vowel sequence, and <..> indicates arbitrary - * presence, - * - * gives 0 - * vc gives 1 - * vcvc gives 2 - * vcvcvc gives 3 - * - * @param string $str The string to return the m count for - * - * @return integer The m count - * - * @since 2.5 - */ - private static function m($str) - { - $c = self::$regex_consonant; - $v = self::$regex_vowel; - - $str = preg_replace("#^$c+#", '', $str); - $str = preg_replace("#$v+$#", '', $str); - - preg_match_all("#($v+$c+)#", $str, $matches); - - return count($matches[1]); - } - - /** - * Returns true/false as to whether the given string contains two - * of the same consonant next to each other at the end of the string. - * - * @param string $str String to check - * - * @return boolean Result - * - * @since 2.5 - */ - private static function doubleConsonant($str) - { - $c = self::$regex_consonant; - - return preg_match("#$c{2}$#", $str, $matches) and $matches[0]{0} == $matches[0]{1}; - } - - /** - * Checks for ending CVC sequence where second C is not W, X or Y - * - * @param string $str String to check - * - * @return boolean Result - * - * @since 2.5 - */ - private static function cvc($str) - { - $c = self::$regex_consonant; - $v = self::$regex_vowel; - - return preg_match("#($c$v$c)$#", $str, $matches) and strlen($matches[1]) == 3 and $matches[1]{2} != 'w' and $matches[1]{2} != 'x' - and $matches[1]{2} != 'y'; - } -} diff --git a/administrator/components/com_finder/helpers/indexer/stemmer/snowball.php b/administrator/components/com_finder/helpers/indexer/stemmer/snowball.php deleted file mode 100644 index df1f23db4842a..0000000000000 --- a/administrator/components/com_finder/helpers/indexer/stemmer/snowball.php +++ /dev/null @@ -1,133 +0,0 @@ -sef) ? $languages[0]->sef : '*'; - $lang = $defaultLang; - } - - // Stem the token if it is not in the cache. - if (!isset($this->cache[$lang][$token])) - { - // Get the stem function from the language string. - switch ($lang) - { - // Danish stemmer. - case 'da': - $function = 'stem_danish'; - break; - - // German stemmer. - case 'de': - $function = 'stem_german'; - break; - - // English stemmer. - default: - case 'en': - $function = 'stem_english'; - break; - - // Spanish stemmer. - case 'es': - $function = 'stem_spanish'; - break; - - // Finnish stemmer. - case 'fi': - $function = 'stem_finnish'; - break; - - // French stemmer. - case 'fr': - $function = 'stem_french'; - break; - - // Hungarian stemmer. - case 'hu': - $function = 'stem_hungarian'; - break; - - // Italian stemmer. - case 'it': - $function = 'stem_italian'; - break; - - // Norwegian stemmer. - case 'nb': - $function = 'stem_norwegian'; - break; - - // Dutch stemmer. - case 'nl': - $function = 'stem_dutch'; - break; - - // Portuguese stemmer. - case 'pt': - $function = 'stem_portuguese'; - break; - - // Romanian stemmer. - case 'ro': - $function = 'stem_romanian'; - break; - - // Russian stemmer. - case 'ru': - $function = 'stem_russian_unicode'; - break; - - // Swedish stemmer. - case 'sv': - $function = 'stem_swedish'; - break; - - // Turkish stemmer. - case 'tr': - $function = 'stem_turkish_unicode'; - break; - } - - // Stem the word if the stemmer method exists. - $this->cache[$lang][$token] = function_exists($function) ? $function($token) : $token; - } - - return $this->cache[$lang][$token]; - } -} diff --git a/administrator/components/com_finder/sql/uninstall.mysql.sql b/administrator/components/com_finder/sql/uninstall.mysql.sql deleted file mode 100644 index 89579b982d43f..0000000000000 --- a/administrator/components/com_finder/sql/uninstall.mysql.sql +++ /dev/null @@ -1,25 +0,0 @@ -DROP TABLE IF EXISTS `#__finder_filters`; -DROP TABLE IF EXISTS `#__finder_links`; -DROP TABLE IF EXISTS `#__finder_links_terms0`; -DROP TABLE IF EXISTS `#__finder_links_terms1`; -DROP TABLE IF EXISTS `#__finder_links_terms2`; -DROP TABLE IF EXISTS `#__finder_links_terms3`; -DROP TABLE IF EXISTS `#__finder_links_terms4`; -DROP TABLE IF EXISTS `#__finder_links_terms5`; -DROP TABLE IF EXISTS `#__finder_links_terms6`; -DROP TABLE IF EXISTS `#__finder_links_terms7`; -DROP TABLE IF EXISTS `#__finder_links_terms8`; -DROP TABLE IF EXISTS `#__finder_links_terms9`; -DROP TABLE IF EXISTS `#__finder_links_termsa`; -DROP TABLE IF EXISTS `#__finder_links_termsb`; -DROP TABLE IF EXISTS `#__finder_links_termsc`; -DROP TABLE IF EXISTS `#__finder_links_termsd`; -DROP TABLE IF EXISTS `#__finder_links_termse`; -DROP TABLE IF EXISTS `#__finder_links_termsf`; -DROP TABLE IF EXISTS `#__finder_taxonomy`; -DROP TABLE IF EXISTS `#__finder_taxonomy_map`; -DROP TABLE IF EXISTS `#__finder_terms`; -DROP TABLE IF EXISTS `#__finder_terms_common`; -DROP TABLE IF EXISTS `#__finder_tokens`; -DROP TABLE IF EXISTS `#__finder_tokens_aggregate`; -DROP TABLE IF EXISTS `#__finder_types`; diff --git a/administrator/components/com_finder/sql/uninstall.postgresql.sql b/administrator/components/com_finder/sql/uninstall.postgresql.sql deleted file mode 100644 index 76d7981529149..0000000000000 --- a/administrator/components/com_finder/sql/uninstall.postgresql.sql +++ /dev/null @@ -1,25 +0,0 @@ -DROP TABLE IF EXISTS "#__finder_filters"; -DROP TABLE IF EXISTS "#__finder_links"; -DROP TABLE IF EXISTS "#__finder_links_terms0"; -DROP TABLE IF EXISTS "#__finder_links_terms1"; -DROP TABLE IF EXISTS "#__finder_links_terms2"; -DROP TABLE IF EXISTS "#__finder_links_terms3"; -DROP TABLE IF EXISTS "#__finder_links_terms4"; -DROP TABLE IF EXISTS "#__finder_links_terms5"; -DROP TABLE IF EXISTS "#__finder_links_terms6"; -DROP TABLE IF EXISTS "#__finder_links_terms7"; -DROP TABLE IF EXISTS "#__finder_links_terms8"; -DROP TABLE IF EXISTS "#__finder_links_terms9"; -DROP TABLE IF EXISTS "#__finder_links_termsa"; -DROP TABLE IF EXISTS "#__finder_links_termsb"; -DROP TABLE IF EXISTS "#__finder_links_termsc"; -DROP TABLE IF EXISTS "#__finder_links_termsd"; -DROP TABLE IF EXISTS "#__finder_links_termse"; -DROP TABLE IF EXISTS "#__finder_links_termsf"; -DROP TABLE IF EXISTS "#__finder_taxonomy"; -DROP TABLE IF EXISTS "#__finder_taxonomy_map"; -DROP TABLE IF EXISTS "#__finder_terms"; -DROP TABLE IF EXISTS "#__finder_terms_common"; -DROP TABLE IF EXISTS "#__finder_tokens"; -DROP TABLE IF EXISTS "#__finder_tokens_aggregate"; -DROP TABLE IF EXISTS "#__finder_types"; diff --git a/administrator/components/com_search/access.xml b/administrator/components/com_search/access.xml index 9b65a75052466..f19530a348048 100644 --- a/administrator/components/com_search/access.xml +++ b/administrator/components/com_search/access.xml @@ -4,6 +4,9 @@ + + + diff --git a/administrator/components/com_search/config.xml b/administrator/components/com_search/config.xml index 69b5cf4f94602..872d5e843ff2c 100644 --- a/administrator/components/com_search/config.xml +++ b/administrator/components/com_search/config.xml @@ -60,7 +60,275 @@ cols="30" rows="2" /> - +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
input->get('view', 'searches')); - return parent::display(); } } diff --git a/administrator/components/com_finder/controllers/filter.php b/administrator/components/com_search/controllers/filter.php similarity index 100% rename from administrator/components/com_finder/controllers/filter.php rename to administrator/components/com_search/controllers/filter.php diff --git a/administrator/components/com_finder/controllers/filters.php b/administrator/components/com_search/controllers/filters.php similarity index 100% rename from administrator/components/com_finder/controllers/filters.php rename to administrator/components/com_search/controllers/filters.php diff --git a/administrator/components/com_finder/controllers/index.php b/administrator/components/com_search/controllers/index.php similarity index 70% rename from administrator/components/com_finder/controllers/index.php rename to administrator/components/com_search/controllers/index.php index a21f31575969b..b7df466c047e1 100644 --- a/administrator/components/com_finder/controllers/index.php +++ b/administrator/components/com_search/controllers/index.php @@ -1,7 +1,7 @@ true)) + public function getModel($name = 'Index', $prefix = 'SearchModel', $config = array('ignore_request' => true)) { return parent::getModel($name, $prefix, $config); } @@ -46,22 +46,22 @@ public function purge() // Remove the script time limit. @set_time_limit(0); - $model = $this->getModel('Index', 'FinderModel'); + $model = $this->getModel('Index', 'SearchModel'); // Attempt to purge the index. $return = $model->purge(); if (!$return) { - $message = JText::_('COM_FINDER_INDEX_PURGE_FAILED', $model->getError()); - $this->setRedirect('index.php?option=com_finder&view=index', $message); + $message = JText::_('COM_SEARCH_INDEX_PURGE_FAILED', $model->getError()); + $this->setRedirect('index.php?option=com_search&view=index', $message); return false; } else { - $message = JText::_('COM_FINDER_INDEX_PURGE_SUCCESS'); - $this->setRedirect('index.php?option=com_finder&view=index', $message); + $message = JText::_('COM_SEARCH_INDEX_PURGE_SUCCESS'); + $this->setRedirect('index.php?option=com_search&view=index', $message); return true; } diff --git a/administrator/components/com_finder/controllers/indexer.json.php b/administrator/components/com_search/controllers/indexer.json.php similarity index 81% rename from administrator/components/com_finder/controllers/indexer.json.php rename to administrator/components/com_search/controllers/indexer.json.php index edd059fbcff99..15656453edb77 100644 --- a/administrator/components/com_finder/controllers/indexer.json.php +++ b/administrator/components/com_search/controllers/indexer.json.php @@ -1,7 +1,7 @@ get('enable_logging', '0')) { @@ -54,23 +54,23 @@ public function start() ob_start(); // Reset the indexer state. - FinderIndexer::resetState(); + SearchIndexer::resetState(); // Import the finder plugins. - JPluginHelper::importPlugin('finder'); + JPluginHelper::importPlugin('search'); // Add the indexer language to JS - JText::script('COM_FINDER_AN_ERROR_HAS_OCCURRED'); - JText::script('COM_FINDER_NO_ERROR_RETURNED'); + JText::script('COM_SEARCH_AN_ERROR_HAS_OCCURRED'); + JText::script('COM_SEARCH_NO_ERROR_RETURNED'); // Start the indexer. try { // Trigger the onStartIndex event. - JFactory::getApplication()->triggerEvent('onStartIndex'); + JFactory::getApplication()->triggerEvent('onSearchStartIndex'); // Get the indexer state. - $state = FinderIndexer::getState(); + $state = SearchIndexer::getState(); $state->start = 1; // Send the response. @@ -92,7 +92,7 @@ public function start() */ public function batch() { - $params = JComponentHelper::getParams('com_finder'); + $params = JComponentHelper::getParams('com_search'); if ($params->get('enable_logging', '0')) { @@ -121,16 +121,16 @@ public function batch() @set_time_limit(0); // Get the indexer state. - $state = FinderIndexer::getState(); + $state = SearchIndexer::getState(); // Reset the batch offset. $state->batchOffset = 0; // Update the indexer state. - FinderIndexer::setState($state); + SearchIndexer::setState($state); // Import the finder plugins. - JPluginHelper::importPlugin('finder'); + JPluginHelper::importPlugin('search'); /* * We are going to swap out the raw document object with an HTML document @@ -169,14 +169,14 @@ public function batch() // Start the indexer. try { - // Trigger the onBeforeIndex event. - JFactory::getApplication()->triggerEvent('onBeforeIndex'); + // Trigger the onSearchBeforeIndex event. + JFactory::getApplication()->triggerEvent('onSearchBeforeIndex'); - // Trigger the onBuildIndex event. - JFactory::getApplication()->triggerEvent('onBuildIndex'); + // Trigger the onSearchBuildIndex event. + JFactory::getApplication()->triggerEvent('onSearchBuildIndex'); // Get the indexer state. - $state = FinderIndexer::getState(); + $state = SearchIndexer::getState(); $state->start = 0; $state->complete = 0; @@ -223,15 +223,15 @@ public function optimize() ob_start(); // Import the finder plugins. - JPluginHelper::importPlugin('finder'); + JPluginHelper::importPlugin('search'); try { // Optimize the index - FinderIndexer::getInstance()->optimize(); + SearchIndexer::getInstance()->optimize(); // Get the indexer state. - $state = FinderIndexer::getState(); + $state = SearchIndexer::getState(); $state->start = 0; $state->complete = 1; @@ -262,7 +262,7 @@ public static function sendResponse($data = null) $app = JFactory::getApplication(); $app->mimeType = 'application/json'; - $params = JComponentHelper::getParams('com_finder'); + $params = JComponentHelper::getParams('com_search'); if ($params->get('enable_logging', '0')) { @@ -279,7 +279,7 @@ public static function sendResponse($data = null) } // Create the response object. - $response = new FinderIndexerResponse($data); + $response = new SearchIndexerResponse($data); // Add the buffer. $response->buffer = JDEBUG ? ob_get_contents() : ob_end_clean(); @@ -295,11 +295,11 @@ public static function sendResponse($data = null) } /** - * Finder Indexer JSON Response Class + * Search Indexer JSON Response Class * * @since 2.5 */ -class FinderIndexerResponse +class SearchIndexerResponse { /** * Class Constructor @@ -310,7 +310,7 @@ class FinderIndexerResponse */ public function __construct($state) { - $params = JComponentHelper::getParams('com_finder'); + $params = JComponentHelper::getParams('com_search'); if ($params->get('enable_logging', '0')) { @@ -330,7 +330,7 @@ public function __construct($state) // Prepare the error response. $this->error = true; - $this->header = JText::_('COM_FINDER_INDEXER_HEADER_ERROR'); + $this->header = JText::_('COM_SEARCH_INDEXER_HEADER_ERROR'); $this->message = $state->getMessage(); } else @@ -349,22 +349,22 @@ public function __construct($state) // Set the appropriate messages. if ($this->totalItems <= 0 && $this->complete) { - $this->header = JText::_('COM_FINDER_INDEXER_HEADER_COMPLETE'); - $this->message = JText::_('COM_FINDER_INDEXER_MESSAGE_COMPLETE'); + $this->header = JText::_('COM_SEARCH_INDEXER_HEADER_COMPLETE'); + $this->message = JText::_('COM_SEARCH_INDEXER_MESSAGE_COMPLETE'); } elseif ($this->totalItems <= 0) { - $this->header = JText::_('COM_FINDER_INDEXER_HEADER_OPTIMIZE'); - $this->message = JText::_('COM_FINDER_INDEXER_MESSAGE_OPTIMIZE'); + $this->header = JText::_('COM_SEARCH_INDEXER_HEADER_OPTIMIZE'); + $this->message = JText::_('COM_SEARCH_INDEXER_MESSAGE_OPTIMIZE'); } else { - $this->header = JText::_('COM_FINDER_INDEXER_HEADER_RUNNING'); - $this->message = JText::_('COM_FINDER_INDEXER_MESSAGE_RUNNING'); + $this->header = JText::_('COM_SEARCH_INDEXER_HEADER_RUNNING'); + $this->message = JText::_('COM_SEARCH_INDEXER_MESSAGE_RUNNING'); } } } } // Register the error handler. -JError::setErrorHandling(E_ALL, 'callback', array('FinderControllerIndexer', 'sendResponse')); +JError::setErrorHandling(E_ALL, 'callback', array('SearchControllerIndexer', 'sendResponse')); diff --git a/administrator/components/com_finder/controllers/maps.php b/administrator/components/com_search/controllers/maps.php similarity index 100% rename from administrator/components/com_finder/controllers/maps.php rename to administrator/components/com_search/controllers/maps.php diff --git a/administrator/components/com_finder/helpers/html/finder.php b/administrator/components/com_search/helpers/html/finder.php similarity index 100% rename from administrator/components/com_finder/helpers/html/finder.php rename to administrator/components/com_search/helpers/html/finder.php diff --git a/administrator/components/com_finder/helpers/indexer/adapter.php b/administrator/components/com_search/helpers/indexer/adapter.php similarity index 94% rename from administrator/components/com_finder/helpers/indexer/adapter.php rename to administrator/components/com_search/helpers/indexer/adapter.php index 6314ebece649c..0c0d8dab73013 100644 --- a/administrator/components/com_finder/helpers/indexer/adapter.php +++ b/administrator/components/com_search/helpers/indexer/adapter.php @@ -11,23 +11,23 @@ use Joomla\Utilities\ArrayHelper; -JLoader::register('FinderIndexer', __DIR__ . '/indexer.php'); -JLoader::register('FinderIndexerHelper', __DIR__ . '/helper.php'); -JLoader::register('FinderIndexerResult', __DIR__ . '/result.php'); -JLoader::register('FinderIndexerTaxonomy', __DIR__ . '/taxonomy.php'); +JLoader::register('SearchIndexer', __DIR__ . '/indexer.php'); +JLoader::register('SearchIndexerHelper', __DIR__ . '/helper.php'); +JLoader::register('SearchIndexerResult', __DIR__ . '/result.php'); +JLoader::register('SearchIndexerTaxonomy', __DIR__ . '/taxonomy.php'); /** - * Prototype adapter class for the Finder indexer package. + * Prototype adapter class for the Search indexer package. * * @since 2.5 */ -abstract class FinderIndexerAdapter extends JPlugin +abstract class SearchIndexerAdapter extends JPlugin { /** * The context is somewhat arbitrary but it must be unique or there will be * conflicts when managing plugin/indexer state. A good best practice is to * use the plugin name suffix as the context. For example, if the plugin is - * named 'plgFinderContent', the context could be 'Content'. + * named 'plgSearchContent', the context could be 'Content'. * * @var string * @since 2.5 @@ -109,7 +109,7 @@ abstract class FinderIndexerAdapter extends JPlugin /** * The indexer object. * - * @var FinderIndexer + * @var SearchIndexer * @since 3.0 */ protected $indexer; @@ -144,7 +144,7 @@ public function __construct(&$subject, $config) // Add the content type if it doesn't exist and is set. if (empty($this->type_id) && !empty($this->type_title)) { - $this->type_id = FinderIndexerHelper::addContentType($this->type_title, $this->mime); + $this->type_id = SearchIndexerHelper::addContentType($this->type_title, $this->mime); } // Check for a layout override. @@ -154,7 +154,7 @@ public function __construct(&$subject, $config) } // Get the indexer object - $this->indexer = FinderIndexer::getInstance(); + $this->indexer = SearchIndexer::getInstance(); } /** @@ -168,7 +168,7 @@ public function __construct(&$subject, $config) public function onStartIndex() { // Get the indexer state. - $iState = FinderIndexer::getState(); + $iState = SearchIndexer::getState(); // Get the number of content items. $total = (int) $this->getContentCount(); @@ -181,7 +181,7 @@ public function onStartIndex() $iState->pluginState[$this->context]['offset'] = 0; // Set the indexer state. - FinderIndexer::setState($iState); + SearchIndexer::setState($iState); } /** @@ -196,7 +196,7 @@ public function onStartIndex() public function onBeforeIndex() { // Get the indexer and adapter state. - $iState = FinderIndexer::getState(); + $iState = SearchIndexer::getState(); $aState = $iState->pluginState[$this->context]; // Check the progress of the indexer and the adapter. @@ -223,7 +223,7 @@ public function onBeforeIndex() public function onBuildIndex() { // Get the indexer and adapter state. - $iState = FinderIndexer::getState(); + $iState = SearchIndexer::getState(); $aState = $iState->pluginState[$this->context]; // Check the progress of the indexer and the adapter. @@ -254,7 +254,7 @@ public function onBuildIndex() // Update the indexer state. $aState['offset'] = $offset; $iState->pluginState[$this->context] = $aState; - FinderIndexer::setState($iState); + SearchIndexer::setState($iState); return true; } @@ -298,14 +298,14 @@ protected function change($id, $property, $value) /** * Method to index an item. * - * @param FinderIndexerResult $item The item to index as a FinderIndexerResult object. + * @param SearchIndexerResult $item The item to index as a SearchIndexerResult object. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ - abstract protected function index(FinderIndexerResult $item); + abstract protected function index(SearchIndexerResult $item); /** * Method to reindex an item. @@ -536,7 +536,7 @@ protected function getContentCount() * * @param integer $id The id of the content item. * - * @return FinderIndexerResult A FinderIndexerResult object. + * @return SearchIndexerResult A SearchIndexerResult object. * * @since 2.5 * @throws Exception on database error. @@ -552,7 +552,7 @@ protected function getItem($id) $row = $this->db->loadAssoc(); // Convert the item to a result object. - $item = ArrayHelper::toObject((array) $row, 'FinderIndexerResult'); + $item = ArrayHelper::toObject((array) $row, 'SearchIndexerResult'); // Set the item type. $item->type_id = $this->type_id; @@ -570,7 +570,7 @@ protected function getItem($id) * @param integer $limit The list limit. * @param JDatabaseQuery $query A JDatabaseQuery object. [optional] * - * @return array An array of FinderIndexerResult objects. + * @return array An array of SearchIndexerResult objects. * * @since 2.5 * @throws Exception on database error. @@ -587,7 +587,7 @@ protected function getItems($offset, $limit, $query = null) foreach ($rows as $row) { // Convert the item to a result object. - $item = ArrayHelper::toObject((array) $row, 'FinderIndexerResult'); + $item = ArrayHelper::toObject((array) $row, 'SearchIndexerResult'); // Set the item type. $item->type_id = $this->type_id; @@ -731,7 +731,7 @@ protected function getTypeId() /** * Method to get the URL for the item. The URL is how we look up the link - * in the Finder index. + * in the Search index. * * @param integer $id The id of the item. * @param string $extension The extension the category is in. diff --git a/administrator/components/com_finder/helpers/indexer/driver/mysql.php b/administrator/components/com_search/helpers/indexer/driver/mysql.php similarity index 87% rename from administrator/components/com_finder/helpers/indexer/driver/mysql.php rename to administrator/components/com_search/helpers/indexer/driver/mysql.php index 5e7f150c098d8..05bb663f12554 100644 --- a/administrator/components/com_finder/helpers/indexer/driver/mysql.php +++ b/administrator/components/com_search/helpers/indexer/driver/mysql.php @@ -12,9 +12,9 @@ jimport('joomla.filesystem.file'); /** - * Indexer class supporting MySQL(i) for the Finder indexer package. + * Indexer class supporting MySQL(i) for the Search indexer package. * - * The indexer class provides the core functionality of the Finder + * The indexer class provides the core functionality of the Search * search engine. It is responsible for adding and updating the * content links table; extracting and scoring tokens; and maintaining * all referential information for the content. @@ -24,12 +24,12 @@ * * @since 3.0 */ -class FinderIndexerDriverMysql extends FinderIndexer +class SearchIndexerDriverMysql extends SearchIndexer { /** * Method to index a content item. * - * @param FinderIndexerResult $item The content item to index. + * @param SearchIndexerResult $item The content item to index. * @param string $format The format of the content. [optional] * * @return integer The ID of the record in the links table. @@ -78,18 +78,15 @@ public function index($item, $format = 'html') */ if (!$isNew) { - for ($i = 0; $i <= 15; $i++) - { - // Flush the maps for the link. - $query->clear() - ->delete($db->quoteName('#__finder_links_terms' . dechex($i))) - ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); - $db->setQuery($query); - $db->execute(); - } + // Flush the maps for the link. + $query->clear() + ->delete($db->quoteName('#__finder_links_terms')) + ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); + $db->setQuery($query); + $db->execute(); // Remove the taxonomy maps. - FinderIndexerTaxonomy::removeMaps($linkId); + SearchIndexerTaxonomy::removeMaps($linkId); } // Mark afterUnmapping in the profiler. @@ -102,7 +99,9 @@ public function index($item, $format = 'html') $item->end_date = (int) $item->end_date != 0 ? $item->end_date : $nd; // Prepare the item description. - $item->description = FinderIndexerHelper::parse($item->summary); + $tokenizer = new SearchIndexerLanguage($item->language); + $parser = SearchIndexerParser::getInstance($format); + $item->description = $parser->parse($item->summary, false); /* * Now, we need to enter the item into the links table. If the item @@ -119,7 +118,7 @@ public function index($item, $format = 'html') $db->quoteName('publish_end_date'), $db->quoteName('start_date'), $db->quoteName('end_date'), $db->quoteName('list_price'), $db->quoteName('sale_price') ); - + // Insert the link. $query->clear() ->insert($db->quoteName('#__finder_links')) @@ -128,7 +127,7 @@ public function index($item, $format = 'html') $db->quote($item->url) . ', ' . $db->quote($item->route) . ', ' . $db->quote($item->title) . ', ' - . $db->quote($item->description) . ', ' + . $db->quote(substr($item->description, 0, 255)) . ', ' . $query->currentTimestamp() . ', ' . '1, ' . (int) $item->state . ', ' @@ -156,7 +155,7 @@ public function index($item, $format = 'html') ->update($db->quoteName('#__finder_links')) ->set($db->quoteName('route') . ' = ' . $db->quote($item->route)) ->set($db->quoteName('title') . ' = ' . $db->quote($item->title)) - ->set($db->quoteName('description') . ' = ' . $db->quote($item->description)) + ->set($db->quoteName('description') . ' = ' . $db->quote(substr($item->description, 0, 255))) ->set($db->quoteName('indexdate') . ' = ' . $query->currentTimestamp()) ->set($db->quoteName('state') . ' = ' . (int) $item->state) ->set($db->quoteName('access') . ' = ' . (int) $item->access) @@ -266,10 +265,10 @@ public function index($item, $format = 'html') foreach ($nodes as $node) { // Add the node to the tree. - $nodeId = FinderIndexerTaxonomy::addNode($branch, $node->title, $node->state, $node->access); + $nodeId = SearchIndexerTaxonomy::addNode($branch, $node->title, $node->state, $node->access); // Add the link => node map. - FinderIndexerTaxonomy::addMap($linkId, $nodeId); + SearchIndexerTaxonomy::addMap($linkId, $nodeId); // Tokenize the node title and add them to the database. $count += $this->tokenizeToDb($node->title, static::META_CONTEXT, $item->language, $format); @@ -297,7 +296,7 @@ public function index($item, $format = 'html') ', ' . $db->quoteName('context_weight') . ', ' . $db->quoteName('language') . ')' . ' SELECT' . - ' t.term_id, t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, ' . + ' IFNULL(t.term_id, 0), t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, ' . ' ROUND( t1.weight * COUNT( t2.term ) * %F, 8 ) AS context_weight, t1.language' . ' FROM (' . ' SELECT DISTINCT t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' . @@ -307,7 +306,7 @@ public function index($item, $format = 'html') ' JOIN ' . $db->quoteName('#__finder_tokens') . ' AS t2 ON t2.term = t1.term' . ' LEFT JOIN ' . $db->quoteName('#__finder_terms') . ' AS t ON t.term = t1.term' . ' WHERE t2.context = %d' . - ' GROUP BY t1.term' . + ' GROUP BY t1.term, t1.stem, t.term_id, t1.common, t1.phrase, t1.weight, t1.context, t1.language' . ' ORDER BY t1.term DESC'; // Iterate through the contexts and aggregate the tokens per context. @@ -340,7 +339,7 @@ public function index($item, $format = 'html') ' SELECT ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight, SOUNDEX(ta.term), ta.language' . ' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . ' AS ta' . ' WHERE ta.term_id = 0' . - ' GROUP BY ta.term' + ' GROUP BY ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight, SOUNDEX(ta.term), ta.language' ); $db->execute(); @@ -396,29 +395,19 @@ public function index($item, $format = 'html') * this link. Then, we insert all of that data into the appropriate * mapping table. */ - for ($i = 0; $i <= 15; $i++) - { - // Get the mapping table suffix. - $suffix = dechex($i); - - /* - * We have to run this query 16 times, one for each link => term - * mapping table. - */ - $db->setQuery( - 'INSERT INTO ' . $db->quoteName('#__finder_links_terms' . $suffix) . - ' (' . $db->quoteName('link_id') . - ', ' . $db->quoteName('term_id') . - ', ' . $db->quoteName('weight') . ')' . - ' SELECT ' . (int) $linkId . ', ' . $db->quoteName('term_id') . ',' . - ' ROUND(SUM(' . $db->quoteName('context_weight') . '), 8)' . - ' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . - ' WHERE ' . $db->quoteName('map_suffix') . ' = ' . $db->quote($suffix) . - ' GROUP BY ' . $db->quoteName('term') . - ' ORDER BY ' . $db->quoteName('term') . ' DESC' - ); - $db->execute(); - } + + $db->setQuery( + 'INSERT INTO ' . $db->quoteName('#__finder_links_terms') . + ' (' . $db->quoteName('link_id') . + ', ' . $db->quoteName('term_id') . + ', ' . $db->quoteName('weight') . ')' . + ' SELECT ' . (int) $linkId . ', ' . $db->quoteName('term_id') . ',' . + ' ROUND(SUM(' . $db->quoteName('context_weight') . '), 8)' . + ' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . + ' GROUP BY ' . $db->quoteName('term') . ', ' . $db->quoteName('term_id') . + ' ORDER BY ' . $db->quoteName('term') . ' DESC' + ); + $db->execute(); // Mark afterMapping in the profiler. static::$profiler ? static::$profiler->mark('afterMapping') : null; @@ -465,23 +454,20 @@ public function remove($linkId) $query = $db->getQuery(true); // Update the link counts and remove the mapping records. - for ($i = 0; $i <= 15; $i++) - { - // Update the link counts for the terms. - $query->update($db->quoteName('#__finder_terms') . ' AS t') - ->join('INNER', $db->quoteName('#__finder_links_terms' . dechex($i)) . ' AS m ON m.term_id = t.term_id') - ->set('t.links = t.links - 1') - ->where('m.link_id = ' . $db->quote((int) $linkId)); - $db->setQuery($query); - $db->execute(); + // Update the link counts for the terms. + $query->update($db->quoteName('#__finder_terms') . ' AS t') + ->join('INNER', $db->quoteName('#__finder_links_terms') . ' AS m ON m.term_id = t.term_id') + ->set('t.links = t.links - 1') + ->where('m.link_id = ' . $db->quote((int) $linkId)); + $db->setQuery($query); + $db->execute(); - // Remove all records from the mapping tables. - $query->clear() - ->delete($db->quoteName('#__finder_links_terms' . dechex($i))) - ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); - $db->setQuery($query); - $db->execute(); - } + // Remove all records from the mapping tables. + $query->clear() + ->delete($db->quoteName('#__finder_links_terms')) + ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); + $db->setQuery($query); + $db->execute(); // Delete all orphaned terms. $query->clear() @@ -498,10 +484,10 @@ public function remove($linkId) $db->execute(); // Remove the taxonomy maps. - FinderIndexerTaxonomy::removeMaps($linkId); + SearchIndexerTaxonomy::removeMaps($linkId); // Remove the orphaned taxonomy nodes. - FinderIndexerTaxonomy::removeOrphanNodes(); + SearchIndexerTaxonomy::removeOrphanNodes(); return true; } @@ -531,19 +517,12 @@ public function optimize() $db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_links')); $db->execute(); - for ($i = 0; $i <= 15; $i++) - { - // Optimize the terms mapping table. - $db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_links_terms' . dechex($i))); - $db->execute(); - } - // Optimize the terms mapping table. $db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_links_terms')); $db->execute(); // Remove the orphaned taxonomy nodes. - FinderIndexerTaxonomy::removeOrphanNodes(); + SearchIndexerTaxonomy::removeOrphanNodes(); // Optimize the taxonomy mapping table. $db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_taxonomy_map')); @@ -555,7 +534,7 @@ public function optimize() /** * Method to add a set of tokens to the database. * - * @param mixed $tokens An array or single FinderIndexerToken object. + * @param mixed $tokens An array or single SearchIndexerToken object. * @param mixed $context The context of the tokens. See context constants. [optional] * * @return integer The number of tokens inserted into the database. diff --git a/administrator/components/com_finder/helpers/indexer/driver/postgresql.php b/administrator/components/com_search/helpers/indexer/driver/postgresql.php similarity index 87% rename from administrator/components/com_finder/helpers/indexer/driver/postgresql.php rename to administrator/components/com_search/helpers/indexer/driver/postgresql.php index 5cff3a7b8ce27..384854a996e71 100644 --- a/administrator/components/com_finder/helpers/indexer/driver/postgresql.php +++ b/administrator/components/com_search/helpers/indexer/driver/postgresql.php @@ -12,16 +12,16 @@ jimport('joomla.filesystem.file'); /** - * Indexer class supporting PostgreSQL for the Finder indexer package. + * Indexer class supporting PostgreSQL for the Search indexer package. * * @since 3.0 */ -class FinderIndexerDriverPostgresql extends FinderIndexer +class SearchIndexerDriverPostgresql extends SearchIndexer { /** * Method to index a content item. * - * @param FinderIndexerResult $item The content item to index. + * @param SearchIndexerResult $item The content item to index. * @param string $format The format of the content. [optional] * * @return integer The ID of the record in the links table. @@ -70,18 +70,15 @@ public function index($item, $format = 'html') */ if (!$isNew) { - for ($i = 0; $i <= 15; $i++) - { - // Flush the maps for the link. - $query->clear() - ->delete($db->quoteName('#__finder_links_terms' . dechex($i))) - ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); - $db->setQuery($query); - $db->execute(); - } + // Flush the maps for the link. + $query->clear() + ->delete($db->quoteName('#__finder_links_terms')) + ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); + $db->setQuery($query); + $db->execute(); // Remove the taxonomy maps. - FinderIndexerTaxonomy::removeMaps($linkId); + SearchIndexerTaxonomy::removeMaps($linkId); } // Mark afterUnmapping in the profiler. @@ -94,7 +91,7 @@ public function index($item, $format = 'html') $item->end_date = (int) $item->end_date != 0 ? $item->end_date : $nd; // Prepare the item description. - $item->description = FinderIndexerHelper::parse($item->summary); + $item->description = SearchIndexerHelper::parse($item->summary); /* * Now, we need to enter the item into the links table. If the item @@ -258,10 +255,10 @@ public function index($item, $format = 'html') foreach ($nodes as $node) { // Add the node to the tree. - $nodeId = FinderIndexerTaxonomy::addNode($branch, $node->title, $node->state, $node->access); + $nodeId = SearchIndexerTaxonomy::addNode($branch, $node->title, $node->state, $node->access); // Add the link => node map. - FinderIndexerTaxonomy::addMap($linkId, $nodeId); + SearchIndexerTaxonomy::addMap($linkId, $nodeId); // Tokenize the node title and add them to the database. $count += $this->tokenizeToDb($node->title, static::META_CONTEXT, $item->language, $format); @@ -398,29 +395,18 @@ public function index($item, $format = 'html') * this link. Then, we insert all of that data into the appropriate * mapping table. */ - for ($i = 0; $i <= 15; $i++) - { - // Get the mapping table suffix. - $suffix = dechex($i); - - /* - * We have to run this query 16 times, one for each link => term - * mapping table. - */ - $db->setQuery( - 'INSERT INTO ' . $db->quoteName('#__finder_links_terms' . $suffix) . - ' (' . $db->quoteName('link_id') . - ', ' . $db->quoteName('term_id') . - ', ' . $db->quoteName('weight') . ')' . - ' SELECT ' . (int) $linkId . ', ' . $db->quoteName('term_id') . ',' . - ' ROUND(SUM(' . $db->quoteName('context_weight') . '), 8)' . - ' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . - ' WHERE ' . $db->quoteName('map_suffix') . ' = ' . $db->quote($suffix) . - ' GROUP BY ' . $db->quoteName('term') . - ' ORDER BY ' . $db->quoteName('term') . ' DESC' - ); - $db->execute(); - } + $db->setQuery( + 'INSERT INTO ' . $db->quoteName('#__finder_links_terms') . + ' (' . $db->quoteName('link_id') . + ', ' . $db->quoteName('term_id') . + ', ' . $db->quoteName('weight') . ')' . + ' SELECT ' . (int) $linkId . ', ' . $db->quoteName('term_id') . ',' . + ' ROUND(SUM(' . $db->quoteName('context_weight') . '), 8)' . + ' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . + ' GROUP BY ' . $db->quoteName('term') . + ' ORDER BY ' . $db->quoteName('term') . ' DESC' + ); + $db->execute(); // Mark afterMapping in the profiler. static::$profiler ? static::$profiler->mark('afterMapping') : null; @@ -466,24 +452,20 @@ public function remove($linkId) $db = JFactory::getDbo(); $query = $db->getQuery(true); - // Update the link counts and remove the mapping records. - for ($i = 0; $i <= 15; $i++) - { - // Update the link counts for the terms. - $query->update($db->quoteName('#__finder_terms') . ' AS t') - ->join('INNER', $db->quoteName('#__finder_links_terms' . dechex($i)) . ' AS m ON m.term_id = t.term_id') - ->set('t.links = t.links - 1') - ->where('m.link_id = ' . $db->quote((int) $linkId)); - $db->setQuery($query); - $db->execute(); + // Update the link counts for the terms. + $query->update($db->quoteName('#__finder_terms') . ' AS t') + ->join('INNER', $db->quoteName('#__finder_links_terms') . ' AS m ON m.term_id = t.term_id') + ->set('t.links = t.links - 1') + ->where('m.link_id = ' . $db->quote((int) $linkId)); + $db->setQuery($query); + $db->execute(); - // Remove all records from the mapping tables. - $query->clear() - ->delete($db->quoteName('#__finder_links_terms' . dechex($i))) - ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); - $db->setQuery($query); - $db->execute(); - } + // Remove all records from the mapping tables. + $query->clear() + ->delete($db->quoteName('#__finder_links_terms')) + ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); + $db->setQuery($query); + $db->execute(); // Delete all orphaned terms. $query->clear() @@ -500,10 +482,10 @@ public function remove($linkId) $db->execute(); // Remove the taxonomy maps. - FinderIndexerTaxonomy::removeMaps($linkId); + SearchIndexerTaxonomy::removeMaps($linkId); // Remove the orphaned taxonomy nodes. - FinderIndexerTaxonomy::removeOrphanNodes(); + SearchIndexerTaxonomy::removeOrphanNodes(); return true; } @@ -535,21 +517,14 @@ public function optimize() $db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_links')); $db->execute(); - for ($i = 0; $i <= 15; $i++) - { - // Optimize the terms mapping table. - $db->setQuery('VACUUM ' . $db->quoteName('#__finder_links_terms' . dechex($i))); - $db->execute(); - $db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_links_terms' . dechex($i))); - $db->execute(); - } - // Optimize the terms mapping table. + $db->setQuery('VACUUM ' . $db->quoteName('#__finder_links_terms')); + $db->execute(); $db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_links_terms')); $db->execute(); // Remove the orphaned taxonomy nodes. - FinderIndexerTaxonomy::removeOrphanNodes(); + SearchIndexerTaxonomy::removeOrphanNodes(); // Optimize the taxonomy mapping table. $db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_taxonomy_map')); @@ -561,7 +536,7 @@ public function optimize() /** * Method to add a set of tokens to the database. * - * @param mixed $tokens An array or single FinderIndexerToken object. + * @param mixed $tokens An array or single SearchIndexerToken object. * @param mixed $context The context of the tokens. See context constants. [optional] * * @return integer The number of tokens inserted into the database. diff --git a/administrator/components/com_finder/helpers/indexer/helper.php b/administrator/components/com_search/helpers/indexer/helper.php similarity index 60% rename from administrator/components/com_finder/helpers/indexer/helper.php rename to administrator/components/com_search/helpers/indexer/helper.php index deb9009736671..b1c4148741746 100644 --- a/administrator/components/com_finder/helpers/indexer/helper.php +++ b/administrator/components/com_search/helpers/indexer/helper.php @@ -12,25 +12,25 @@ use Joomla\Registry\Registry; use Joomla\String\StringHelper; -JLoader::register('FinderIndexerParser', __DIR__ . '/parser.php'); -JLoader::register('FinderIndexerStemmer', __DIR__ . '/stemmer.php'); -JLoader::register('FinderIndexerToken', __DIR__ . '/token.php'); +JLoader::register('SearchIndexerParser', __DIR__ . '/parser.php'); +JLoader::register('SearchIndexerStemmer', __DIR__ . '/stemmer.php'); +JLoader::register('SearchIndexerToken', __DIR__ . '/token.php'); /** - * Helper class for the Finder indexer package. + * Helper class for the Search indexer package. * * @since 2.5 */ -class FinderIndexerHelper +class SearchIndexerHelper { /** * The token stemmer object. The stemmer is set by whatever class - * wishes to use it but it must be an instance of FinderIndexerStemmer. + * wishes to use it but it must be an instance of SearchIndexerStemmer. * - * @var FinderIndexerStemmer + * @var SearchIndexerStemmer * @since 2.5 */ - public static $stemmer; + protected static $languageHelper = array(); /** * Method to parse input into plain text. @@ -46,7 +46,7 @@ class FinderIndexerHelper public static function parse($input, $format = 'html') { // Get a parser for the specified format and parse the input. - return FinderIndexerParser::getInstance($format)->parse($input); + return SearchIndexerParser::getInstance($format)->parse($input); } /** @@ -56,137 +56,31 @@ public static function parse($input, $format = 'html') * @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. + * @return array An array of SearchIndexerToken objects. * * @since 2.5 */ public static function tokenize($input, $lang, $phrase = false) { static $cache; - $store = StringHelper::strlen($input) < 128 ? md5($input . '::' . $lang . '::' . $phrase) : null; + /**$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('‘’'', 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]; - } - } + $tokenizer = SearchIndexerLanguage::getInstance($lang); - // Reset array keys. - $terms = array_values($terms); - } + // Tokenize the input. + $terms = $tokenizer->tokenize($input); - /* - * 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 terms. + foreach ($terms as $term) { - // 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; - } - } + $tokens[] = new SearchIndexerToken($term, $lang); } if ($store) @@ -203,7 +97,7 @@ public static function tokenize($input, $lang, $phrase = false) /** * Method to get the base word of a token. This method uses the public - * {@link FinderIndexerHelper::$stemmer} object if it is set. If no stemmer is set, + * {@link SearchIndexerHelper::$stemmer} object if it is set. If no stemmer is set, * the original token is returned. * * @param string $token The token to stem. @@ -224,13 +118,12 @@ public static function stem($token, $lang) $token = StringHelper::substr($token, 0, $pos); } - // Stem the token if we have a valid stemmer to use. - if (static::$stemmer instanceof FinderIndexerStemmer) + if (!isset(self::$languageHelper[$lang])) { - return static::$stemmer->stem($token, $lang); + self::$languageHelper[$lang] = SearchIndexerLanguage::getInstance($lang); } - return $token; + return self::$languageHelper[$lang]->stem($token); } /** @@ -401,7 +294,6 @@ public static function getContentPath($url) // Get and configure the site router. $config = JFactory::getConfig(); $router = JRouter::getInstance('site'); - $router->setMode($config->get('sef', 1)); } // Build the relative route. @@ -414,16 +306,16 @@ public static function getContentPath($url) /** * Method to get extra data for a content before being indexed. This is how - * we add Comments, Tags, Labels, etc. that should be available to Finder. + * we add Comments, Tags, Labels, etc. that should be available to Search. * - * @param FinderIndexerResult &$item The item to index as an FinderIndexerResult object. + * @param SearchIndexerResult &$item The item to index as an SearchIndexerResult object. * * @return boolean True on success, false on failure. * * @since 2.5 * @throws Exception on database error. */ - public static function getContentExtras(FinderIndexerResult &$item) + public static function getContentExtras(SearchIndexerResult &$item) { // Load the finder plugin group. JPluginHelper::importPlugin('finder'); diff --git a/administrator/components/com_finder/helpers/indexer/indexer.php b/administrator/components/com_search/helpers/indexer/indexer.php similarity index 76% rename from administrator/components/com_finder/helpers/indexer/indexer.php rename to administrator/components/com_search/helpers/indexer/indexer.php index 14480231bf0a1..32e05308cf21f 100644 --- a/administrator/components/com_finder/helpers/indexer/indexer.php +++ b/administrator/components/com_search/helpers/indexer/indexer.php @@ -11,18 +11,18 @@ use Joomla\String\StringHelper; -JLoader::register('FinderIndexerHelper', __DIR__ . '/helper.php'); -JLoader::register('FinderIndexerParser', __DIR__ . '/parser.php'); -JLoader::register('FinderIndexerStemmer', __DIR__ . '/stemmer.php'); -JLoader::register('FinderIndexerTaxonomy', __DIR__ . '/taxonomy.php'); -JLoader::register('FinderIndexerToken', __DIR__ . '/token.php'); +JLoader::register('SearchIndexerHelper', __DIR__ . '/helper.php'); +JLoader::register('SearchIndexerParser', __DIR__ . '/parser.php'); +JLoader::register('SearchIndexerLanguage', __DIR__ . '/language.php'); +JLoader::register('SearchIndexerTaxonomy', __DIR__ . '/taxonomy.php'); +JLoader::register('SearchIndexerToken', __DIR__ . '/token.php'); jimport('joomla.filesystem.file'); /** - * Main indexer class for the Finder indexer package. + * Main indexer class for the Search indexer package. * - * The indexer class provides the core functionality of the Finder + * The indexer class provides the core functionality of the Search * search engine. It is responsible for adding and updating the * content links table; extracting and scoring tokens; and maintaining * all referential information for the content. @@ -32,7 +32,7 @@ * * @since 2.5 */ -abstract class FinderIndexer +abstract class SearchIndexer { /** * The title context identifier. @@ -91,9 +91,9 @@ abstract class FinderIndexer public static $profiler; /** - * Returns a reference to the FinderIndexer object. + * Returns a reference to the SearchIndexer object. * - * @return FinderIndexer instance based on the database driver + * @return SearchIndexer instance based on the database driver * * @since 3.0 * @throws RuntimeException if driver class for indexer not present. @@ -109,7 +109,7 @@ public static function getInstance() } $path = __DIR__ . '/driver/' . $format . '.php'; - $class = 'FinderIndexerDriver' . ucfirst($format); + $class = 'SearchIndexerDriver' . ucfirst($format); // Check if a parser exists for the format. if (file_exists($path)) @@ -173,13 +173,13 @@ public static function getState() // Setup the profiler if debugging is enabled. if (JFactory::getApplication()->get('debug')) { - static::$profiler = JProfiler::getInstance('FinderIndexer'); + static::$profiler = JProfiler::getInstance('SearchIndexer'); } // Setup the stemmer. - if ($data->options->get('stem', 1) && $data->options->get('stemmer', 'porter_en')) + if ($data->options->get('stem', 1)) { - FinderIndexerHelper::$stemmer = FinderIndexerStemmer::getInstance($data->options->get('stemmer', 'porter_en')); + //SearchIndexerHelper::$stemmer = SearchIndexerStemmer::getInstance($data->options->get('stemmer', 'porter_en')); } // Set the state. @@ -233,7 +233,7 @@ public static function resetState() /** * Method to index a content item. * - * @param FinderIndexerResult $item The content item to index. + * @param SearchIndexerResult $item The content item to index. * @param string $format The format of the content. [optional] * * @return integer The ID of the record in the links table. @@ -310,6 +310,9 @@ protected function tokenizeToDb($input, $context, $lang, $format) if (!empty($input)) { + $tokenizer = new SearchIndexerLanguage($lang); + $parser = SearchIndexerParser::getInstance($format); + // If the input is a resource, batch the process out. if (is_resource($input)) { @@ -317,7 +320,7 @@ protected function tokenizeToDb($input, $context, $lang, $format) while (!feof($input)) { // Read into the buffer. - $buffer .= fread($input, 2048); + $buffer .= fread($input, 16384); /* * If we haven't reached the end of the file, seek to the last @@ -351,7 +354,7 @@ protected function tokenizeToDb($input, $context, $lang, $format) } // Parse the input. - $string = FinderIndexerHelper::parse($string, $format); + $string = $parser->parse($string); // Check the input. if (empty($string)) @@ -360,7 +363,7 @@ protected function tokenizeToDb($input, $context, $lang, $format) } // Tokenize the input. - $tokens = FinderIndexerHelper::tokenize($string, $lang); + $tokens = SearchIndexerHelper::tokenize($string, $lang); // Add the tokens to the database. $count += $this->addTokensToDb($tokens, $context); @@ -375,62 +378,10 @@ protected function tokenizeToDb($input, $context, $lang, $format) unset($tokens); } } - // If the input is greater than 2K in size, it is more efficient to - // batch out the operation into smaller chunks of work. - elseif (strlen($input) > 2048) - { - $start = 0; - $end = strlen($input); - $chunk = 2048; - - /* - * As it turns out, the complex regular expressions we use for - * sanitizing input are not very efficient when given large - * strings. It is much faster to process lots of short strings. - */ - while ($start < $end) - { - // Setup the string. - $string = substr($input, $start, $chunk); - - // Find the last space character if we aren't at the end. - $ls = (($start + $chunk) < $end ? strrpos($string, ' ') : false); - - // Truncate to the last space character. - if ($ls !== false) - { - $string = substr($string, 0, $ls); - } - - // Adjust the start position for the next iteration. - $start += ($ls !== false ? ($ls + 1 - $chunk) + $chunk : $chunk); - - // Parse the input. - $string = FinderIndexerHelper::parse($string, $format); - - // Check the input. - if (empty($string)) - { - continue; - } - - // Tokenize the input. - $tokens = FinderIndexerHelper::tokenize($string, $lang); - - // Add the tokens to the database. - $count += $this->addTokensToDb($tokens, $context); - - // Check if we're approaching the memory limit of the token table. - if ($count > static::$state->options->get('memory_table_limit', 30000)) - { - $this->toggleTables(false); - } - } - } else { // Parse the input. - $input = FinderIndexerHelper::parse($input, $format); + $input = $parser->parse($input); // Check the input. if (empty($input)) @@ -439,7 +390,7 @@ protected function tokenizeToDb($input, $context, $lang, $format) } // Tokenize the input. - $tokens = FinderIndexerHelper::tokenize($input, $lang); + $tokens = SearchIndexerHelper::tokenize($input, $lang); // Add the tokens to the database. $count = $this->addTokensToDb($tokens, $context); @@ -452,7 +403,7 @@ protected function tokenizeToDb($input, $context, $lang, $format) /** * Method to add a set of tokens to the database. * - * @param mixed $tokens An array or single FinderIndexerToken object. + * @param mixed $tokens An array or single SearchIndexerToken object. * @param mixed $context The context of the tokens. See context constants. [optional] * * @return integer The number of tokens inserted into the database. diff --git a/administrator/components/com_search/helpers/indexer/language.php b/administrator/components/com_search/helpers/indexer/language.php new file mode 100644 index 0000000000000..8f66f1cebdcfb --- /dev/null +++ b/administrator/components/com_search/helpers/indexer/language.php @@ -0,0 +1,165 @@ +stopwords); + } + + return $this->stopwords; + } + + /** + * Add a word to the list of stopwords for this indexer object + * + * @param string $word Word to add to the stopword list + * + * @since 4.0 + */ + public function addStopWord($word) + { + $this->stopwords[] = $word; + } + + /** + * Remvoe a word from the list of stopwords for this indexer object + * + * @param string $word Word to remove from the stopword list + * + * @since 4.0 + */ + public function removeStopWord($word) + { + if (in_array($word, $this->stopwords)) + { + unset($this->stopwords[array_search($word, $this->stopwords)]); + } + } + + /** + * Take a string and tokenize it into an array of single, lowercase words + * This method should be overriden by languages that don't use white space + * to separate words + * + * @param string $string String to tokenize + * + * @return array List of words + * + * @since 4.0 + */ + public function tokenize($string) + { + $string = strtolower(html_entity_decode(utf8_decode($string))); + $string = preg_replace('/&#?\w+;/', ' ', $string); + $string = preg_replace('/\s+/', ' ', $string); + $string = strip_tags($string); + $string = preg_replace('/\W+/', ' ', $string); + $words = preg_split('/\s+/', trim($string)); + + return $words; + } + + /** + * Try to create the stem of the word given + * This method should be overriden by each language with a language specific + * stemmer. + * + * @param string $word Word to stem + * + * @return string Stemmed word + * + * @since 4.0 + */ + public function stem($word) + { + return $word; + } +} \ No newline at end of file diff --git a/administrator/components/com_finder/helpers/indexer/parser.php b/administrator/components/com_search/helpers/indexer/parser.php similarity index 55% rename from administrator/components/com_finder/helpers/indexer/parser.php rename to administrator/components/com_search/helpers/indexer/parser.php index ccf578a6a1129..e1ab29c3e127d 100644 --- a/administrator/components/com_finder/helpers/indexer/parser.php +++ b/administrator/components/com_search/helpers/indexer/parser.php @@ -10,18 +10,20 @@ defined('_JEXEC') or die; /** - * Parser base class for the Finder indexer package. + * Parser base class for the Search indexer package. * * @since 2.5 */ -abstract class FinderIndexerParser +abstract class SearchIndexerParser { + protected $tokenizer; + /** * Method to get a parser, creating it if necessary. * * @param string $format The type of parser to load. * - * @return FinderIndexerParser A FinderIndexerParser instance. + * @return SearchIndexerParser A SearchIndexerParser instance. * * @since 2.5 * @throws Exception on invalid parser. @@ -45,7 +47,7 @@ public static function getInstance($format) // Setup the adapter for the parser. $format = JFilterInput::getInstance()->clean($format, 'cmd'); $path = __DIR__ . '/parser/' . $format . '.php'; - $class = 'FinderIndexerParser' . ucfirst($format); + $class = 'SearchIndexerParser' . ucfirst($format); // Check if a parser exists for the format. if (!file_exists($path)) @@ -73,56 +75,5 @@ public static function getInstance($format) * * @since 2.5 */ - public function parse($input) - { - $return = null; - - // Parse the input in batches if bigger than 2KB. - if (strlen($input) > 2048) - { - $start = 0; - $end = strlen($input); - $chunk = 2048; - - while ($start < $end) - { - // Setup the string. - $string = substr($input, $start, $chunk); - - // Find the last space character if we aren't at the end. - $ls = (($start + $chunk) < $end ? strrpos($string, ' ') : false); - - // Truncate to the last space character. - if ($ls !== false) - { - $string = substr($string, 0, $ls); - } - - // Adjust the start position for the next iteration. - $start += ($ls !== false ? ($ls + 1 - $chunk) + $chunk : $chunk); - - // Parse the chunk. - $return .= $this->process($string); - } - } - // The input is less than 2KB so we can parse it efficiently. - else - { - // Parse the chunk. - $return .= $this->process($input); - } - - return $return; - } - - /** - * Method to process input and extract the plain text. - * - * @param string $input The input to process. - * - * @return string The plain text input. - * - * @since 2.5 - */ - abstract protected function process($input); + abstract public function parse($input); } diff --git a/administrator/components/com_finder/helpers/indexer/parser/html.php b/administrator/components/com_search/helpers/indexer/parser/html.php similarity index 86% rename from administrator/components/com_finder/helpers/indexer/parser/html.php rename to administrator/components/com_search/helpers/indexer/parser/html.php index 16bbe283a7e3d..b8289d9ed2731 100644 --- a/administrator/components/com_finder/helpers/indexer/parser/html.php +++ b/administrator/components/com_search/helpers/indexer/parser/html.php @@ -9,14 +9,14 @@ defined('_JEXEC') or die; -JLoader::register('FinderIndexerParser', dirname(__DIR__) . '/parser.php'); +JLoader::register('SearchIndexerParser', dirname(__DIR__) . '/parser.php'); /** - * HTML Parser class for the Finder indexer package. + * HTML Parser class for the Search indexer package. * * @since 2.5 */ -class FinderIndexerParserHtml extends FinderIndexerParser +class SearchIndexerParserHtml extends SearchIndexerParser { /** * Method to parse input and extract the plain text. Because this method is @@ -65,22 +65,7 @@ public function parse($input) // Strip HTML tags. $input = strip_tags($input); - return parent::parse($input); - } - - /** - * Method to process HTML input and extract the plain text. - * - * @param string $input The input to process. - * - * @return string The plain text input. - * - * @since 2.5 - */ - protected function process($input) - { - // Replace any amount of white space with a single space. - return preg_replace('#\s+#u', ' ', $input); + return $input; } /** diff --git a/administrator/components/com_finder/helpers/indexer/parser/rtf.php b/administrator/components/com_search/helpers/indexer/parser/rtf.php similarity index 80% rename from administrator/components/com_finder/helpers/indexer/parser/rtf.php rename to administrator/components/com_search/helpers/indexer/parser/rtf.php index 0e05cb90c341c..3e60b210780ff 100644 --- a/administrator/components/com_finder/helpers/indexer/parser/rtf.php +++ b/administrator/components/com_search/helpers/indexer/parser/rtf.php @@ -9,14 +9,14 @@ defined('_JEXEC') or die; -JLoader::register('FinderIndexerParser', dirname(__DIR__) . '/parser.php'); +JLoader::register('SearchIndexerParser', dirname(__DIR__) . '/parser.php'); /** - * RTF Parser class for the Finder indexer package. + * RTF Parser class for the Search indexer package. * * @since 2.5 */ -class FinderIndexerParserRtf extends FinderIndexerParser +class SearchIndexerParserRtf extends SearchIndexerParser { /** * Method to process RTF input and extract the plain text. @@ -27,7 +27,7 @@ class FinderIndexerParserRtf extends FinderIndexerParser * * @since 2.5 */ - protected function process($input) + public function parse($input) { // Remove embedded pictures. $input = preg_replace('#{\\\pict[^}]*}#mis', '', $input); diff --git a/administrator/components/com_finder/helpers/indexer/parser/txt.php b/administrator/components/com_search/helpers/indexer/parser/txt.php similarity index 71% rename from administrator/components/com_finder/helpers/indexer/parser/txt.php rename to administrator/components/com_search/helpers/indexer/parser/txt.php index caaf10771b7ac..b4165e4a48df9 100644 --- a/administrator/components/com_finder/helpers/indexer/parser/txt.php +++ b/administrator/components/com_search/helpers/indexer/parser/txt.php @@ -9,14 +9,14 @@ defined('_JEXEC') or die; -JLoader::register('FinderIndexerParser', dirname(__DIR__) . '/parser.php'); +JLoader::register('SearchIndexerParser', dirname(__DIR__) . '/parser.php'); /** - * Text Parser class for the Finder indexer package. + * Text Parser class for the Search indexer package. * * @since 2.5 */ -class FinderIndexerParserTxt extends FinderIndexerParser +class SearchIndexerParserTxt extends SearchIndexerParser { /** * Method to process Text input and extract the plain text. @@ -27,7 +27,7 @@ class FinderIndexerParserTxt extends FinderIndexerParser * * @since 2.5 */ - protected function process($input) + public function parse($input) { return $input; } diff --git a/administrator/components/com_finder/helpers/indexer/query.php b/administrator/components/com_search/helpers/indexer/query.php similarity index 92% rename from administrator/components/com_finder/helpers/indexer/query.php rename to administrator/components/com_search/helpers/indexer/query.php index 98db5dd4512af..0d4eb8ea7d782 100644 --- a/administrator/components/com_finder/helpers/indexer/query.php +++ b/administrator/components/com_search/helpers/indexer/query.php @@ -10,20 +10,19 @@ defined('_JEXEC') or die; use Joomla\Registry\Registry; -use Joomla\String\StringHelper; use Joomla\Utilities\ArrayHelper; -JLoader::register('FinderIndexerHelper', __DIR__ . '/helper.php'); -JLoader::register('FinderIndexerTaxonomy', __DIR__ . '/taxonomy.php'); -JLoader::register('FinderHelperRoute', JPATH_SITE . '/components/com_finder/helpers/route.php'); -JLoader::register('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php'); +JLoader::register('SearchIndexerHelper', __DIR__ . '/helper.php'); +JLoader::register('SearchIndexerTaxonomy', __DIR__ . '/taxonomy.php'); +JLoader::register('SearchHelperRoute', JPATH_SITE . '/components/com_finder/helpers/route.php'); +JLoader::register('SearchHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_search/helpers/lang.php'); /** - * Query class for the Finder indexer package. + * Query class for the Search indexer package. * * @since 2.5 */ -class FinderIndexerQuery +class SearchIndexerQuery { /** * Flag to show whether the query can return results. @@ -178,8 +177,8 @@ public function __construct($options) $this->empty = isset($options['empty']) ? (bool) $options['empty'] : false; // Get the input language. - $this->language = !empty($options['language']) ? $options['language'] : FinderIndexerHelper::getDefaultLanguage(); - $this->language = FinderIndexerHelper::getPrimaryLanguage($this->language); + $this->language = !empty($options['language']) ? $options['language'] : SearchIndexerHelper::getDefaultLanguage(); + $this->language = SearchIndexerHelper::getPrimaryLanguage($this->language); // Get the matching mode. $this->mode = 'AND'; @@ -349,7 +348,7 @@ public function toUri($base = null) 'f' => $uri->getVar('f'), 'q' => $uri->getVar('q') ); - $item = FinderHelperRoute::getItemid($query); + $item = SearchHelperRoute::getItemid($query); // Add the menu item id if present. if ($item !== null) @@ -507,7 +506,8 @@ protected function processStaticTaxonomy($filterId) $this->filter = (int) $filterId; // Get a parameter object for the filter date options. - $registry = new Registry($return->params); + $registry = new Registry; + $registry->loadString($return->params); $params = $registry; // Set the dates if not already set. @@ -665,10 +665,10 @@ protected function processDynamicTaxonomy($filters) protected function processDates($date1, $date2, $when1, $when2) { // Clean up the inputs. - $date1 = StringHelper::trim(StringHelper::strtolower($date1)); - $date2 = StringHelper::trim(StringHelper::strtolower($date2)); - $when1 = StringHelper::trim(StringHelper::strtolower($when1)); - $when2 = StringHelper::trim(StringHelper::strtolower($when2)); + $date1 = JString::trim(JString::strtolower($date1)); + $date2 = JString::trim(JString::strtolower($date2)); + $when1 = JString::trim(JString::strtolower($when1)); + $when2 = JString::trim(JString::strtolower($when2)); // Get the time offset. $offset = JFactory::getApplication()->get('offset'); @@ -677,7 +677,7 @@ protected function processDates($date1, $date2, $when1, $when2) $whens = array('before', 'after', 'exact'); // The value of 'today' is a special case that we need to handle. - if ($date1 === StringHelper::strtolower(JText::_('COM_FINDER_QUERY_FILTER_TODAY'))) + if ($date1 === JString::strtolower(JText::_('COM_FINDER_QUERY_FILTER_TODAY'))) { $date1 = JFactory::getDate('now', $offset)->format('%Y-%m-%d'); } @@ -694,7 +694,7 @@ protected function processDates($date1, $date2, $when1, $when2) } // The value of 'today' is a special case that we need to handle. - if ($date2 === StringHelper::strtolower(JText::_('COM_FINDER_QUERY_FILTER_TODAY'))) + if ($date2 === JString::strtolower(JText::_('COM_FINDER_QUERY_FILTER_TODAY'))) { $date2 = JFactory::getDate('now', $offset)->format('%Y-%m-%d'); } @@ -730,9 +730,9 @@ 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 = JString::strtolower($input); $input = preg_replace('#\s+#mi', ' ', $input); - $input = StringHelper::trim($input); + $input = JString::trim($input); $debug = JFactory::getConfig()->get('debug_lang'); /* @@ -746,10 +746,10 @@ protected function processString($input, $lang, $mode) ); // Add the taxonomy branch titles to the possible patterns. - foreach (FinderIndexerTaxonomy::getBranchTitles() as $branch) + foreach (SearchIndexerTaxonomy::getBranchTitles() as $branch) { // Add the pattern. - $patterns[$branch] = StringHelper::strtolower(JText::_(FinderHelperLanguage::branchSingular($branch))); + $patterns[$branch] = JString::strtolower(JText::_(SearchHelperLanguage::branchSingular($branch))); } // Container for search terms and phrases. @@ -801,7 +801,7 @@ protected function processString($input, $lang, $mode) $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'))) + if ($value === JString::strtolower(JText::_('COM_FINDER_QUERY_FILTER_TODAY'))) { $value = JFactory::getDate('now', $offset)->format('%Y-%m-%d'); } @@ -824,7 +824,7 @@ protected function processString($input, $lang, $mode) default: { // Try to find the node id. - $return = FinderIndexerTaxonomy::getNodeByTitle($modifier, $value); + $return = SearchIndexerTaxonomy::getNodeByTitle($modifier, $value); // Check if the node id was found. if ($return) @@ -850,7 +850,7 @@ protected function processString($input, $lang, $mode) // Clean up the input string again. $input = str_replace($matches[0], '', $input); $input = preg_replace('#\s+#mi', ' ', $input); - $input = StringHelper::trim($input); + $input = JString::trim($input); } } @@ -858,7 +858,7 @@ protected function processString($input, $lang, $mode) * Extract the tokens enclosed in double quotes so that we can handle * them as phrases. */ - if (StringHelper::strpos($input, '"') !== false) + if (JString::strpos($input, '"') !== false) { $matches = array(); @@ -873,21 +873,21 @@ protected function processString($input, $lang, $mode) 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]); + $pos = JString::strpos($input, $matches[0][$key]); + $len = JString::strlen($matches[0][$key]); // Add any terms that are before this phrase to the stack. - if (StringHelper::trim(StringHelper::substr($input, 0, $pos))) + if (JString::trim(JString::substr($input, 0, $pos))) { - $terms = array_merge($terms, explode(' ', StringHelper::trim(StringHelper::substr($input, 0, $pos)))); + $terms = array_merge($terms, explode(' ', JString::trim(JString::substr($input, 0, $pos)))); } // Strip out everything up to and including the phrase. - $input = StringHelper::substr($input, $pos + $len); + $input = JString::substr($input, $pos + $len); // Clean up the input string again. $input = preg_replace('#\s+#mi', ' ', $input); - $input = StringHelper::trim($input); + $input = JString::trim($input); // Get the number of words in the phrase. $parts = explode(' ', $match); @@ -963,9 +963,9 @@ protected function processString($input, $lang, $mode) // 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')) + 'AND' => JString::strtolower(JText::_('COM_FINDER_QUERY_OPERATOR_AND')), + 'OR' => JString::strtolower(JText::_('COM_FINDER_QUERY_OPERATOR_OR')), + 'NOT' => JString::strtolower(JText::_('COM_FINDER_QUERY_OPERATOR_NOT')) ); // If language debugging is enabled you need to ignore the debug strings in matching. @@ -992,7 +992,7 @@ protected function processString($input, $lang, $mode) if ($op === 'AND' && isset($terms[$i + 2])) { // Tokenize the current term. - $token = FinderIndexerHelper::tokenize($terms[$i], $lang, true); + $token = SearchIndexerHelper::tokenize($terms[$i], $lang, true); $token = $this->getTokenData($token); // Set the required flag. @@ -1006,7 +1006,7 @@ protected function processString($input, $lang, $mode) $this->operators[] = $terms[$i + 1]; // Tokenize the term after the next term (current plus two). - $other = FinderIndexerHelper::tokenize($terms[$i + 2], $lang, true); + $other = SearchIndexerHelper::tokenize($terms[$i + 2], $lang, true); $other = $this->getTokenData($other); // Set the required flag. @@ -1040,7 +1040,7 @@ protected function processString($input, $lang, $mode) elseif ($op === 'OR' && isset($terms[$i + 2])) { // Tokenize the current term. - $token = FinderIndexerHelper::tokenize($terms[$i], $lang, true); + $token = SearchIndexerHelper::tokenize($terms[$i], $lang, true); $token = $this->getTokenData($token); // Set the required flag. @@ -1061,7 +1061,7 @@ protected function processString($input, $lang, $mode) $this->operators[] = $terms[$i + 1]; // Tokenize the term after the next term (current plus two). - $other = FinderIndexerHelper::tokenize($terms[$i + 2], $lang, true); + $other = SearchIndexerHelper::tokenize($terms[$i + 2], $lang, true); $other = $this->getTokenData($other); // Set the required flag. @@ -1106,7 +1106,7 @@ protected function processString($input, $lang, $mode) $this->operators[] = $terms[$i]; // Tokenize the next term (current plus one). - $other = FinderIndexerHelper::tokenize($terms[$i + 1], $lang, true); + $other = SearchIndexerHelper::tokenize($terms[$i + 1], $lang, true); $other = $this->getTokenData($other); // Set the required flag. @@ -1144,7 +1144,7 @@ protected function processString($input, $lang, $mode) $this->operators[] = $terms[$i]; // Tokenize the next term (current plus one). - $other = FinderIndexerHelper::tokenize($terms[$i + 1], $lang, true); + $other = SearchIndexerHelper::tokenize($terms[$i + 1], $lang, true); $other = $this->getTokenData($other); // Set the required flag. @@ -1184,7 +1184,7 @@ protected function processString($input, $lang, $mode) for ($i = 0, $c = count($phrases); $i < $c; $i++) { // Tokenize the phrase. - $token = FinderIndexerHelper::tokenize($phrases[$i], $lang, true); + $token = SearchIndexerHelper::tokenize($phrases[$i], $lang, true); $token = $this->getTokenData($token); // Set the required flag. @@ -1211,7 +1211,7 @@ protected function processString($input, $lang, $mode) { // Tokenize the terms. $terms = implode(' ', $terms); - $tokens = FinderIndexerHelper::tokenize($terms, $lang, false); + $tokens = SearchIndexerHelper::tokenize($terms, $lang, false); // Make sure we are working with an array. $tokens = is_array($tokens) ? $tokens : array($tokens); @@ -1249,9 +1249,9 @@ protected function processString($input, $lang, $mode) * that term and we should try to find a similar term to use that we can * match so that we can suggest the alternative search query to the user. * - * @param FinderIndexerToken $token A FinderIndexerToken object. + * @param SearchIndexerToken $token A SearchIndexerToken object. * - * @return FinderIndexerToken A FinderIndexerToken object. + * @return SearchIndexerToken A SearchIndexerToken object. * * @since 2.5 * @throws Exception on database error. diff --git a/administrator/components/com_finder/helpers/indexer/result.php b/administrator/components/com_search/helpers/indexer/result.php similarity index 94% rename from administrator/components/com_finder/helpers/indexer/result.php rename to administrator/components/com_search/helpers/indexer/result.php index 78bcb6addde6d..fa55cc18bc168 100644 --- a/administrator/components/com_finder/helpers/indexer/result.php +++ b/administrator/components/com_search/helpers/indexer/result.php @@ -9,10 +9,10 @@ defined('_JEXEC') or die; -JLoader::register('FinderIndexer', __DIR__ . '/indexer.php'); +JLoader::register('SearchIndexer', __DIR__ . '/indexer.php'); /** - * Result class for the Finder indexer package. + * Result class for the Search indexer package. * * This class uses magic __get() and __set() methods to prevent properties * being added that might confuse the system. All properties not explicitly @@ -21,7 +21,7 @@ * * @since 2.5 */ -class FinderIndexerResult +class SearchIndexerResult { /** * An array of extra result properties. @@ -39,11 +39,11 @@ class FinderIndexerResult * @since 2.5 */ protected $instructions = array( - FinderIndexer::TITLE_CONTEXT => array('title', 'subtitle', 'id'), - FinderIndexer::TEXT_CONTEXT => array('summary', 'body'), - FinderIndexer::META_CONTEXT => array('meta', 'list_price', 'sale_price'), - FinderIndexer::PATH_CONTEXT => array('path', 'alias'), - FinderIndexer::MISC_CONTEXT => array('comments') + SearchIndexer::TITLE_CONTEXT => array('title', 'subtitle', 'id'), + SearchIndexer::TEXT_CONTEXT => array('summary', 'body'), + SearchIndexer::META_CONTEXT => array('meta', 'list_price', 'sale_price'), + SearchIndexer::PATH_CONTEXT => array('path', 'alias'), + SearchIndexer::MISC_CONTEXT => array('comments') ); /** diff --git a/administrator/components/com_finder/helpers/indexer/taxonomy.php b/administrator/components/com_search/helpers/indexer/taxonomy.php similarity index 99% rename from administrator/components/com_finder/helpers/indexer/taxonomy.php rename to administrator/components/com_search/helpers/indexer/taxonomy.php index 9a9c9a831a87e..37b75d7058760 100644 --- a/administrator/components/com_finder/helpers/indexer/taxonomy.php +++ b/administrator/components/com_search/helpers/indexer/taxonomy.php @@ -10,11 +10,11 @@ defined('_JEXEC') or die; /** - * Stemmer base class for the Finder indexer package. + * Stemmer base class for the Search indexer package. * * @since 2.5 */ -class FinderIndexerTaxonomy +class SearchIndexerTaxonomy { /** * An internal cache of taxonomy branch data. diff --git a/administrator/components/com_finder/helpers/indexer/token.php b/administrator/components/com_search/helpers/indexer/token.php similarity index 53% rename from administrator/components/com_finder/helpers/indexer/token.php rename to administrator/components/com_search/helpers/indexer/token.php index 2b1f3edadbfe9..2fc3fad17476e 100644 --- a/administrator/components/com_finder/helpers/indexer/token.php +++ b/administrator/components/com_search/helpers/indexer/token.php @@ -12,11 +12,11 @@ use Joomla\String\StringHelper; /** - * Token class for the Finder indexer package. + * Token class for the Search indexer package. * * @since 2.5 */ -class FinderIndexerToken +class SearchIndexerToken { /** * This is the term that will be referenced in the terms table and the @@ -100,48 +100,25 @@ 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); + // Populate the token instance. + $this->term = $term; + $this->stem = SearchIndexerHelper::stem($this->term, $lang); + $this->numeric = (is_numeric($this->term) || (bool) preg_match('#^[0-9,.\-\+]+$#', $this->term)); + $this->common = $this->numeric ? false : SearchIndexerHelper::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 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); - } + /* + * 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); } } diff --git a/administrator/components/com_finder/helpers/language.php b/administrator/components/com_search/helpers/lang.php similarity index 93% rename from administrator/components/com_finder/helpers/language.php rename to administrator/components/com_search/helpers/lang.php index 3cacfce8bfdfb..db797d5cb2e7a 100644 --- a/administrator/components/com_finder/helpers/language.php +++ b/administrator/components/com_search/helpers/lang.php @@ -1,7 +1,7 @@ load('com_finder', JPATH_SITE); + JFactory::getLanguage()->load('com_search', JPATH_SITE); } /** @@ -119,7 +119,7 @@ public static function loadPluginLanguage() ->select(array($db->qn('name'), $db->qn('element'))) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) - ->where($db->quoteName('folder') . ' = ' . $db->quote('finder')) + ->where($db->quoteName('folder') . ' = ' . $db->quote('search')) ->where($db->quoteName('enabled') . ' = 1'); $db->setQuery($query); $plugins = $db->loadObjectList(); diff --git a/administrator/components/com_search/helpers/search.php b/administrator/components/com_search/helpers/search.php index e12a75eb26091..e44b10fae39a9 100644 --- a/administrator/components/com_search/helpers/search.php +++ b/administrator/components/com_search/helpers/search.php @@ -29,7 +29,26 @@ class SearchHelper */ public static function addSubmenu($vName) { - // Not required. + JHtmlSidebar::addEntry( + JText::_('COM_SEARCH_SUBMENU_SEARCHES'), + 'index.php?option=com_search&view=searches', + $vName == 'searches' + ); + JHtmlSidebar::addEntry( + JText::_('COM_SEARCH_SUBMENU_INDEX'), + 'index.php?option=com_search&view=index', + $vName == 'index' + ); + JHtmlSidebar::addEntry( + JText::_('COM_SEARCH_SUBMENU_MAPS'), + 'index.php?option=com_search&view=maps', + $vName == 'maps' + ); + JHtmlSidebar::addEntry( + JText::_('COM_SEARCH_SUBMENU_FILTERS'), + 'index.php?option=com_search&view=filters', + $vName == 'filters' + ); } /** @@ -285,4 +304,33 @@ public static function _smartSubstr($text, $searchword) } } } + + /** + * Gets the finder system plugin extension id. + * + * @return int The finder system plugin extension id. + * + * @since 3.6.0 + */ + public static function getFinderPluginId() + { + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('extension_id')) + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('folder') . ' = ' . $db->quote('content')) + ->where($db->quoteName('element') . ' = ' . $db->quote('finder')); + $db->setQuery($query); + + try + { + $result = (int) $db->loadResult(); + } + catch (RuntimeException $e) + { + JError::raiseWarning(500, $e->getMessage()); + } + + return $result; + } } diff --git a/administrator/components/com_finder/models/fields/branches.php b/administrator/components/com_search/models/fields/branches.php similarity index 100% rename from administrator/components/com_finder/models/fields/branches.php rename to administrator/components/com_search/models/fields/branches.php diff --git a/administrator/components/com_finder/models/fields/contentmap.php b/administrator/components/com_search/models/fields/contentmap.php similarity index 92% rename from administrator/components/com_finder/models/fields/contentmap.php rename to administrator/components/com_search/models/fields/contentmap.php index f0e8a819155ad..2f040e6093cdf 100644 --- a/administrator/components/com_finder/models/fields/contentmap.php +++ b/administrator/components/com_search/models/fields/contentmap.php @@ -11,7 +11,7 @@ JFormHelper::loadFieldClass('groupedlist'); -JLoader::register('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php'); +JLoader::register('SearchHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/lang.php'); /** * Form Field class for the Joomla CMS. @@ -96,11 +96,11 @@ protected function getGroups() if (trim($name, '**') == 'Language') { - $text = FinderHelperLanguage::branchLanguageTitle($branch->text); + $text = SearchHelperLanguage::branchLanguageTitle($branch->text); } else { - $key = FinderHelperLanguage::branchSingular($branch->text); + $key = SearchHelperLanguage::branchSingular($branch->text); $text = $lang->hasKey($key) ? JText::_($key) : $branch->text; } diff --git a/administrator/components/com_finder/models/fields/contenttypes.php b/administrator/components/com_search/models/fields/contenttypes.php similarity index 88% rename from administrator/components/com_finder/models/fields/contenttypes.php rename to administrator/components/com_search/models/fields/contenttypes.php index a8c37a2ea9e11..9ca39029226ac 100644 --- a/administrator/components/com_finder/models/fields/contenttypes.php +++ b/administrator/components/com_search/models/fields/contenttypes.php @@ -11,10 +11,10 @@ use Joomla\Utilities\ArrayHelper; -JLoader::register('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php'); +JLoader::register('SearchHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_search/helpers/lang.php'); /** - * Content Types Filter field for the Finder package. + * Content Types Filter field for the Search package. * * @since 3.6.0 */ @@ -61,7 +61,7 @@ public function getOptions() // Translate. foreach ($contentTypes as $contentType) { - $key = FinderHelperLanguage::branchSingular($contentType->text); + $key = SearchHelperLanguage::branchSingular($contentType->text); $contentType->translatedText = $lang->hasKey($key) ? JText::_($key) : $contentType->text; } diff --git a/administrator/components/com_finder/models/fields/directories.php b/administrator/components/com_search/models/fields/directories.php similarity index 100% rename from administrator/components/com_finder/models/fields/directories.php rename to administrator/components/com_search/models/fields/directories.php diff --git a/administrator/components/com_finder/models/fields/searchfilter.php b/administrator/components/com_search/models/fields/searchfilter.php similarity index 100% rename from administrator/components/com_finder/models/fields/searchfilter.php rename to administrator/components/com_search/models/fields/searchfilter.php diff --git a/administrator/components/com_finder/models/filter.php b/administrator/components/com_search/models/filter.php similarity index 100% rename from administrator/components/com_finder/models/filter.php rename to administrator/components/com_search/models/filter.php diff --git a/administrator/components/com_finder/models/filters.php b/administrator/components/com_search/models/filters.php similarity index 100% rename from administrator/components/com_finder/models/filters.php rename to administrator/components/com_search/models/filters.php diff --git a/administrator/components/com_finder/models/forms/filter.xml b/administrator/components/com_search/models/forms/filter.xml similarity index 100% rename from administrator/components/com_finder/models/forms/filter.xml rename to administrator/components/com_search/models/forms/filter.xml diff --git a/administrator/components/com_finder/models/forms/filter_filters.xml b/administrator/components/com_search/models/forms/filter_filters.xml similarity index 100% rename from administrator/components/com_finder/models/forms/filter_filters.xml rename to administrator/components/com_search/models/forms/filter_filters.xml diff --git a/administrator/components/com_finder/models/forms/filter_index.xml b/administrator/components/com_search/models/forms/filter_index.xml similarity index 100% rename from administrator/components/com_finder/models/forms/filter_index.xml rename to administrator/components/com_search/models/forms/filter_index.xml diff --git a/administrator/components/com_finder/models/forms/filter_maps.xml b/administrator/components/com_search/models/forms/filter_maps.xml similarity index 100% rename from administrator/components/com_finder/models/forms/filter_maps.xml rename to administrator/components/com_search/models/forms/filter_maps.xml diff --git a/administrator/components/com_finder/models/index.php b/administrator/components/com_search/models/index.php similarity index 96% rename from administrator/components/com_finder/models/index.php rename to administrator/components/com_search/models/index.php index 8253a9dcb5b11..96a9ca61b22e1 100644 --- a/administrator/components/com_finder/models/index.php +++ b/administrator/components/com_search/models/index.php @@ -1,7 +1,7 @@ truncateTable('#__finder_links'); // Truncate the links terms tables. - for ($i = 0; $i <= 15; $i++) - { - // Get the mapping table suffix. - $suffix = dechex($i); - - $db->truncateTable('#__finder_links_terms' . $suffix); - } + $db->truncateTable('#__finder_links_terms'); // Truncate the terms table. $db->truncateTable('#__finder_terms'); @@ -384,7 +378,7 @@ protected function populateState($ordering = 'l.title', $direction = 'asc') $this->setState('filter.content_map', $this->getUserStateFromRequest($this->context . '.filter.content_map', 'filter_content_map', '', 'cmd')); // Load the parameters. - $params = JComponentHelper::getParams('com_finder'); + $params = JComponentHelper::getParams('com_search'); $this->setState('params', $params); // List state information. diff --git a/administrator/components/com_finder/models/indexer.php b/administrator/components/com_search/models/indexer.php similarity index 71% rename from administrator/components/com_finder/models/indexer.php rename to administrator/components/com_search/models/indexer.php index e84788b457f8b..a6f922320110d 100644 --- a/administrator/components/com_finder/models/indexer.php +++ b/administrator/components/com_search/models/indexer.php @@ -1,7 +1,7 @@ www.joomla.org 3.0.0 COM_SEARCH_XML_DESCRIPTION + COM_SEARCH controller.php router.php @@ -16,23 +17,42 @@ models views + + js + css + + + + sql/install.mysql.sql + sql/install.postgresql.sql + + + + + sql/uninstall.mysql.sql + sql/uninstall.postgresql.sql + + language/en-GB.com_search.ini - Search + access.xml config.xml controller.php search.php controllers helpers models + sql + tables views language/en-GB.com_search.ini language/en-GB.com_search.sys.ini + COM_SEARCH diff --git a/administrator/components/com_finder/sql/install.mysql.sql b/administrator/components/com_search/sql/install.mysql.sql similarity index 55% rename from administrator/components/com_finder/sql/install.mysql.sql rename to administrator/components/com_search/sql/install.mysql.sql index c8f060220e6ae..f8ed617bdc690 100644 --- a/administrator/components/com_finder/sql/install.mysql.sql +++ b/administrator/components/com_search/sql/install.mysql.sql @@ -54,205 +54,10 @@ CREATE TABLE IF NOT EXISTS `#__finder_links` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; -- --- Table structure for table `#__finder_links_terms0` +-- Table structure for table `#__finder_links_terms` -- -CREATE TABLE IF NOT EXISTS `#__finder_links_terms0` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_terms1` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms1` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_terms2` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms2` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_terms3` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms3` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_terms4` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms4` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_terms5` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms5` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_terms6` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms6` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_terms7` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms7` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_terms8` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms8` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_terms9` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms9` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_termsa` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_termsa` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_termsb` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_termsb` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_termsc` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_termsc` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_termsd` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_termsd` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_termse` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_termse` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- --- Table structure for table `#__finder_links_termsf` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_termsf` ( +CREATE TABLE IF NOT EXISTS `#__finder_links_terms` ( `link_id` int(10) unsigned NOT NULL, `term_id` int(10) unsigned NOT NULL, `weight` float unsigned NOT NULL, diff --git a/administrator/components/com_finder/sql/install.postgresql.sql b/administrator/components/com_search/sql/install.postgresql.sql similarity index 83% rename from administrator/components/com_finder/sql/install.postgresql.sql rename to administrator/components/com_search/sql/install.postgresql.sql index cd49af696bfb9..b57cb1d32b181 100644 --- a/administrator/components/com_finder/sql/install.postgresql.sql +++ b/administrator/components/com_search/sql/install.postgresql.sql @@ -54,194 +54,14 @@ CREATE INDEX "#__finder_links_idx_published_sale" on "#__finder_links" ("publish -- -- Table: #__finder_links_terms0 -- -CREATE TABLE "#__finder_links_terms0" ( +CREATE TABLE "#__finder_links_terms" ( "link_id" integer NOT NULL, "term_id" integer NOT NULL, "weight" numeric(8,2) NOT NULL, PRIMARY KEY ("link_id", "term_id") ); -CREATE INDEX "#__finder_links_terms0_idx_term_weight" on "#__finder_links_terms0" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms0_idx_link_term_weight" on "#__finder_links_terms0" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms1 --- -CREATE TABLE "#__finder_links_terms1" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms1_idx_term_weight" on "#__finder_links_terms1" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms1_idx_link_term_weight" on "#__finder_links_terms1" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms2 --- -CREATE TABLE "#__finder_links_terms2" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms2_idx_term_weight" on "#__finder_links_terms2" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms2_idx_link_term_weight" on "#__finder_links_terms2" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms3 --- -CREATE TABLE "#__finder_links_terms3" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms3_idx_term_weight" on "#__finder_links_terms3" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms3_idx_link_term_weight" on "#__finder_links_terms3" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms4 --- -CREATE TABLE "#__finder_links_terms4" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms4_idx_term_weight" on "#__finder_links_terms4" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms4_idx_link_term_weight" on "#__finder_links_terms4" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms5 --- -CREATE TABLE "#__finder_links_terms5" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms5_idx_term_weight" on "#__finder_links_terms5" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms5_idx_link_term_weight" on "#__finder_links_terms5" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms6 --- -CREATE TABLE "#__finder_links_terms6" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms6_idx_term_weight" on "#__finder_links_terms6" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms6_idx_link_term_weight" on "#__finder_links_terms6" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms7 --- -CREATE TABLE "#__finder_links_terms7" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms7_idx_term_weight" on "#__finder_links_terms7" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms7_idx_link_term_weight" on "#__finder_links_terms7" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms8 --- -CREATE TABLE "#__finder_links_terms8" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms8_idx_term_weight" on "#__finder_links_terms8" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms8_idx_link_term_weight" on "#__finder_links_terms8" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms9 --- -CREATE TABLE "#__finder_links_terms9" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms9_idx_term_weight" on "#__finder_links_terms9" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms9_idx_link_term_weight" on "#__finder_links_terms9" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_termsa --- -CREATE TABLE "#__finder_links_termsa" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_termsa_idx_term_weight" on "#__finder_links_termsa" ("term_id", "weight"); -CREATE INDEX "#__finder_links_termsa_idx_link_term_weight" on "#__finder_links_termsa" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_termsb --- -CREATE TABLE "#__finder_links_termsb" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_termsb_idx_term_weight" on "#__finder_links_termsb" ("term_id", "weight"); -CREATE INDEX "#__finder_links_termsb_idx_link_term_weight" on "#__finder_links_termsb" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_termsc --- -CREATE TABLE "#__finder_links_termsc" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_termsc_idx_term_weight" on "#__finder_links_termsc" ("term_id", "weight"); -CREATE INDEX "#__finder_links_termsc_idx_link_term_weight" on "#__finder_links_termsc" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_termsd --- -CREATE TABLE "#__finder_links_termsd" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_termsd_idx_term_weight" on "#__finder_links_termsd" ("term_id", "weight"); -CREATE INDEX "#__finder_links_termsd_idx_link_term_weight" on "#__finder_links_termsd" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_termse --- -CREATE TABLE "#__finder_links_termse" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_termse_idx_term_weight" on "#__finder_links_termse" ("term_id", "weight"); -CREATE INDEX "#__finder_links_termse_idx_link_term_weight" on "#__finder_links_termse" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_termsf --- -CREATE TABLE "#__finder_links_termsf" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_termsf_idx_term_weight" on "#__finder_links_termsf" ("term_id", "weight"); -CREATE INDEX "#__finder_links_termsf_idx_link_term_weight" on "#__finder_links_termsf" ("link_id", "term_id", "weight"); +CREATE INDEX "#__finder_links_terms_idx_term_weight" on "#__finder_links_terms" ("term_id", "weight"); +CREATE INDEX "#__finder_links_terms_idx_link_term_weight" on "#__finder_links_terms" ("link_id", "term_id", "weight"); -- -- Table: #__finder_taxonomy diff --git a/administrator/components/com_search/sql/uninstall.mysql.sql b/administrator/components/com_search/sql/uninstall.mysql.sql new file mode 100644 index 0000000000000..59d1b7a9b9491 --- /dev/null +++ b/administrator/components/com_search/sql/uninstall.mysql.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS `#__finder_filters`; +DROP TABLE IF EXISTS `#__finder_links`; +DROP TABLE IF EXISTS `#__finder_links_terms`; +DROP TABLE IF EXISTS `#__finder_taxonomy`; +DROP TABLE IF EXISTS `#__finder_taxonomy_map`; +DROP TABLE IF EXISTS `#__finder_terms`; +DROP TABLE IF EXISTS `#__finder_terms_common`; +DROP TABLE IF EXISTS `#__finder_tokens`; +DROP TABLE IF EXISTS `#__finder_tokens_aggregate`; +DROP TABLE IF EXISTS `#__finder_types`; diff --git a/administrator/components/com_search/sql/uninstall.postgresql.sql b/administrator/components/com_search/sql/uninstall.postgresql.sql new file mode 100644 index 0000000000000..6bc222650b261 --- /dev/null +++ b/administrator/components/com_search/sql/uninstall.postgresql.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS "#__finder_filters"; +DROP TABLE IF EXISTS "#__finder_links"; +DROP TABLE IF EXISTS "#__finder_links_terms"; +DROP TABLE IF EXISTS "#__finder_taxonomy"; +DROP TABLE IF EXISTS "#__finder_taxonomy_map"; +DROP TABLE IF EXISTS "#__finder_terms"; +DROP TABLE IF EXISTS "#__finder_terms_common"; +DROP TABLE IF EXISTS "#__finder_tokens"; +DROP TABLE IF EXISTS "#__finder_tokens_aggregate"; +DROP TABLE IF EXISTS "#__finder_types"; diff --git a/administrator/components/com_finder/tables/filter.php b/administrator/components/com_search/tables/filter.php similarity index 97% rename from administrator/components/com_finder/tables/filter.php rename to administrator/components/com_search/tables/filter.php index f6d7cf609f596..71306de666739 100644 --- a/administrator/components/com_finder/tables/filter.php +++ b/administrator/components/com_search/tables/filter.php @@ -1,7 +1,7 @@ load(array('alias' => $this->alias)) && ($table->filter_id != $this->filter_id || $this->filter_id == 0)) { diff --git a/administrator/components/com_finder/tables/link.php b/administrator/components/com_search/tables/link.php similarity index 82% rename from administrator/components/com_finder/tables/link.php rename to administrator/components/com_search/tables/link.php index 41bc829a3bbb0..e13365ffc3fbc 100644 --- a/administrator/components/com_finder/tables/link.php +++ b/administrator/components/com_search/tables/link.php @@ -1,7 +1,7 @@ escape($this->state->get('list.direction')); $lang = JFactory::getLanguage(); -JText::script('COM_FINDER_INDEX_CONFIRM_PURGE_PROMPT'); -JText::script('COM_FINDER_INDEX_CONFIRM_DELETE_PROMPT'); +JText::script('COM_SEARCH_INDEX_CONFIRM_PURGE_PROMPT'); +JText::script('COM_SEARCH_INDEX_CONFIRM_DELETE_PROMPT'); JFactory::getDocument()->addScriptDeclaration(' Joomla.submitbutton = function(pressbutton) { if (pressbutton == "index.purge") { - if (confirm(Joomla.JText._("COM_FINDER_INDEX_CONFIRM_PURGE_PROMPT"))) + if (confirm(Joomla.JText._("COM_SEARCH_INDEX_CONFIRM_PURGE_PROMPT"))) { Joomla.submitform(pressbutton); } @@ -36,7 +36,7 @@ } if (pressbutton == "index.delete") { - if (confirm(Joomla.JText._("COM_FINDER_INDEX_CONFIRM_DELETE_PROMPT"))) + if (confirm(Joomla.JText._("COM_SEARCH_INDEX_CONFIRM_DELETE_PROMPT"))) { Joomla.submitform(pressbutton); } @@ -50,7 +50,7 @@ }; '); ?> -
+ sidebar)) : ?>
sidebar; ?> @@ -60,6 +60,11 @@
$this)); ?> + items)) : ?> +
+ +
+ @@ -73,16 +78,16 @@ @@ -94,7 +99,7 @@ - authorise('core.manage', 'com_finder'); ?> + authorise('core.manage', 'com_search'); ?> items as $i => $item) : ?> @@ -119,7 +124,7 @@
- + - + - + - +
@@ -110,7 +115,7 @@ t_title); + $key = SearchHelperLanguage::branchSingular($item->t_title); echo $lang->hasKey($key) ? JText::_($key) : $item->t_title; ?> publish_start_date) or intval($item->publish_end_date) or intval($item->start_date) or intval($item->end_date)) : ?> - + @@ -130,6 +135,7 @@
+ diff --git a/administrator/components/com_finder/views/index/view.html.php b/administrator/components/com_search/views/index/view.html.php similarity index 71% rename from administrator/components/com_finder/views/index/view.html.php rename to administrator/components/com_search/views/index/view.html.php index 4db0cbb853124..a718d81e2b261 100644 --- a/administrator/components/com_finder/views/index/view.html.php +++ b/administrator/components/com_search/views/index/view.html.php @@ -1,7 +1,7 @@ items = $this->get('Items'); $this->total = $this->get('Total'); @@ -82,7 +82,7 @@ public function display($tpl = null) $this->filterForm = $this->get('FilterForm'); $this->activeFilters = $this->get('ActiveFilters'); - FinderHelper::addSubmenu('index'); + SearchHelper::addSubmenu('index'); // Check for errors. if (count($errors = $this->get('Errors'))) @@ -92,12 +92,12 @@ public function display($tpl = null) if (!$this->pluginState['plg_content_finder']->enabled) { - $link = JRoute::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . FinderHelper::getFinderPluginId()); - JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_FINDER_INDEX_PLUGIN_CONTENT_NOT_ENABLED', $link), 'warning'); + $link = JRoute::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . SearchHelper::getFinderPluginId()); + JFactory::getApplication()->enqueueMessage(JText::sprintf('COM_SEARCH_INDEX_PLUGIN_CONTENT_NOT_ENABLED', $link), 'warning'); } elseif ($this->get('TotalIndexed') === 0) { - JFactory::getApplication()->enqueueMessage(JText::_('COM_FINDER_INDEX_NO_DATA') . ' ' . JText::_('COM_FINDER_INDEX_TIP'), 'notice'); + JFactory::getApplication()->enqueueMessage(JText::_('COM_SEARCH_INDEX_NO_DATA') . ' ' . JText::_('COM_SEARCH_INDEX_TIP'), 'notice'); } JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html'); @@ -118,14 +118,14 @@ public function display($tpl = null) */ protected function addToolbar() { - $canDo = JHelperContent::getActions('com_finder'); + $canDo = JHelperContent::getActions('com_search'); - JToolbarHelper::title(JText::_('COM_FINDER_INDEX_TOOLBAR_TITLE'), 'zoom-in finder'); + JToolbarHelper::title(JText::_('COM_SEARCH_INDEX_TOOLBAR_TITLE'), 'zoom-in finder'); $toolbar = JToolbar::getInstance('toolbar'); $toolbar->appendButton( - 'Popup', 'archive', 'COM_FINDER_INDEX', 'index.php?option=com_finder&view=indexer&tmpl=component', 500, 210, 0, 0, - 'window.parent.location.reload()', 'COM_FINDER_HEADING_INDEXER' + 'Popup', 'archive', 'COM_SEARCH_INDEX', 'index.php?option=com_search&view=indexer&tmpl=component', 500, 210, 0, 0, + 'window.parent.location.reload()', 'COM_SEARCH_HEADING_INDEXER' ); if ($canDo->get('core.edit.state')) @@ -139,7 +139,7 @@ protected function addToolbar() JToolbarHelper::preferences('com_finder'); } - $toolbar->appendButton('Popup', 'bars', 'COM_FINDER_STATISTICS', 'index.php?option=com_finder&view=statistics&tmpl=component', 550, 350); + $toolbar->appendButton('Popup', 'bars', 'COM_SEARCH_STATISTICS', 'index.php?option=com_search&view=statistics&tmpl=component', 550, 350); if ($canDo->get('core.delete')) { @@ -148,9 +148,9 @@ protected function addToolbar() if ($canDo->get('core.edit.state')) { - JToolbarHelper::trash('index.purge', 'COM_FINDER_INDEX_TOOLBAR_PURGE', false); + JToolbarHelper::trash('index.purge', 'COM_SEARCH_INDEX_TOOLBAR_PURGE', false); } - JToolbarHelper::help('JHELP_COMPONENTS_FINDER_MANAGE_INDEXED_CONTENT'); + JToolbarHelper::help('JHELP_COMPONENTS_SEARCH_MANAGE_INDEXED_CONTENT'); } } diff --git a/administrator/components/com_finder/views/indexer/tmpl/default.php b/administrator/components/com_search/views/indexer/tmpl/default.php similarity index 66% rename from administrator/components/com_finder/views/indexer/tmpl/default.php rename to administrator/components/com_search/views/indexer/tmpl/default.php index f69c07bb19f1a..81d42c8546c1d 100644 --- a/administrator/components/com_finder/views/indexer/tmpl/default.php +++ b/administrator/components/com_search/views/indexer/tmpl/default.php @@ -1,7 +1,7 @@ addScriptDeclaration('var msg = "' . JText::_('COM_FINDER_INDEXER_MESSAGE_COMPLETE') . '";'); +JHtml::_('script', 'com_search/indexer.js', false, true); +JFactory::getDocument()->addScriptDeclaration('var msg = "' . JText::_('COM_SEARCH_INDEXER_MESSAGE_COMPLETE') . '";'); ?> -
+


-

+

-

+

- +
diff --git a/administrator/components/com_finder/views/indexer/view.html.php b/administrator/components/com_search/views/indexer/view.html.php similarity index 72% rename from administrator/components/com_finder/views/indexer/view.html.php rename to administrator/components/com_search/views/indexer/view.html.php index 3b787b9905400..ab95ce3eb4dd5 100644 --- a/administrator/components/com_finder/views/indexer/view.html.php +++ b/administrator/components/com_search/views/indexer/view.html.php @@ -1,7 +1,7 @@ enabled = $this->state->params->get('enabled'); $this->canDo = JHelperContent::getActions('com_search'); + SearchHelper::addSubmenu('searches'); + // Check for errors. if (count($errors = $this->get('Errors'))) { @@ -59,6 +68,8 @@ public function display($tpl = null) } $this->addToolbar(); + $this->sidebar = JHtmlSidebar::render(); + parent::display($tpl); } diff --git a/administrator/components/com_finder/views/statistics/tmpl/default.php b/administrator/components/com_search/views/statistics/tmpl/default.php similarity index 100% rename from administrator/components/com_finder/views/statistics/tmpl/default.php rename to administrator/components/com_search/views/statistics/tmpl/default.php diff --git a/administrator/components/com_finder/views/statistics/view.html.php b/administrator/components/com_search/views/statistics/view.html.php similarity index 100% rename from administrator/components/com_finder/views/statistics/view.html.php rename to administrator/components/com_search/views/statistics/view.html.php diff --git a/administrator/language/en-GB/en-GB.com_finder.ini b/administrator/language/en-GB/en-GB.com_finder.ini deleted file mode 100644 index 1f8c22a6f2d4e..0000000000000 --- a/administrator/language/en-GB/en-GB.com_finder.ini +++ /dev/null @@ -1,220 +0,0 @@ -; Joomla! Project -; Copyright (C) 2005 - 2016 Open Source Matters. All rights reserved. -; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php -; Note : All ini files need to be saved as UTF-8 - -COM_FINDER="Smart Search" -COM_FINDER_ALLOW_EMPTY_QUERY_DESC="Only if a filter is selected, allow an empty search string to initiate a search within the filter constraints." -COM_FINDER_ALLOW_EMPTY_QUERY_LABEL="Allow Empty Search" -COM_FINDER_AN_ERROR_HAS_OCCURRED="An Error Has Occurred" -COM_FINDER_CONFIG_ALLOW_EMPTY_QUERY_DESCRIPTION="Only if a filter is selected, allow an empty search string to initiate a search within the filter restraints." -COM_FINDER_CONFIG_ALLOW_EMPTY_QUERY_LABEL="Allow Empty Search" -COM_FINDER_CONFIG_BATCH_SIZE_DESCRIPTION="The batch size controls how many items are processed per batch. Large batch sizes require lots of memory whereas small batch sizes require less memory but execute more requests which tends to take longer." -COM_FINDER_CONFIG_BATCH_SIZE_LABEL="Indexer Batch Size" -COM_FINDER_CONFIG_DESCRIPTION_LENGTH_DESC="Description text for search results will be truncated to the specified character length." -COM_FINDER_CONFIG_DESCRIPTION_LENGTH_DESCRIPTION="Description text for search results will be truncated to the specified character length." -COM_FINDER_CONFIG_DESCRIPTION_LENGTH_LABEL="Description Length" -COM_FINDER_CONFIG_ENABLE_LOGGING_DESCRIPTION="Enable this option to create a log file in your site's logs folder during the index process. This file is useful for troubleshooting issues with the index process. It is recommended that logging be disabled unless necessary." -COM_FINDER_CONFIG_ENABLE_LOGGING_LABEL="Enable Logging" -COM_FINDER_CONFIG_EXPAND_ADVANCED_DESC="Toggle if the advanced search options should be expanded by default." -COM_FINDER_CONFIG_EXPAND_ADVANCED_DESCRIPTION="Toggle if the advanced search options should be expanded by default." -COM_FINDER_CONFIG_EXPAND_ADVANCED_LABEL="Expand Advanced Search" -COM_FINDER_CONFIG_FIELD_OPENSEARCH_DESCRIPTON_DESCRIPTION="Description displayed for this site as a search provider." -COM_FINDER_CONFIG_FIELD_OPENSEARCH_DESCRIPTON_LABEL="OpenSearch Description" -COM_FINDER_CONFIG_FIELD_OPENSEARCH_NAME_DESCRIPTION="Name displayed for this site as a search provider." -COM_FINDER_CONFIG_FIELD_OPENSEARCH_NAME_LABEL="OpenSearch Name" -COM_FINDER_CONFIG_GATHER_SEARCH_STATISTICS_DESCRIPTION="Record the search phrases submitted by visitors." -COM_FINDER_CONFIG_GATHER_SEARCH_STATISTICS_LABEL="Gather Search Statistics" -COM_FINDER_CONFIG_HILIGHT_CONTENT_SEARCH_TERMS_DESCRIPTION="Toggle if search terms should be highlighted in search results." -COM_FINDER_CONFIG_HILIGHT_CONTENT_SEARCH_TERMS_LABEL="Highlight Search Terms" -COM_FINDER_CONFIG_MEMORY_TABLE_LIMIT_DESCRIPTION="The memory table limit should not be changed unless you are getting errors indicating that the finder_tokens or finder_tokens_aggregate tables are full. The default is 30,000." -COM_FINDER_CONFIG_MEMORY_TABLE_LIMIT_LABEL="Memory Table Limit" -COM_FINDER_CONFIG_META_MULTIPLIER_DESCRIPTION="The multiplier is used to control how much influence matching text has on the overall relevance score of a search result. A multiplier is considered in relationship to the other multipliers. The meta data comes from a number of sources including the meta keywords and meta description, author names, etc." -COM_FINDER_CONFIG_META_MULTIPLIER_LABEL="Meta Data Weight Multiplier" -COM_FINDER_CONFIG_MISC_MULTIPLIER_DESCRIPTION="The multiplier is used to control how much influence matching text has on the overall relevance score of a search result. A multiplier is considered in relationship to the other multipliers. The miscellaneous text comes from a number of sources including comments and other associated data." -COM_FINDER_CONFIG_MISC_MULTIPLIER_LABEL="Miscellaneous Text Weight Multiplier" -COM_FINDER_CONFIG_PATH_MULTIPLIER_DESCRIPTION="The multiplier is used to control how much influence matching text has on the overall relevance score of a search result. A multiplier is considered in relationship to the other multipliers. The path text comes from the SEF URL of the content." -COM_FINDER_CONFIG_PATH_MULTIPLIER_LABEL="Path Text Weight Multiplier" -COM_FINDER_CONFIG_SHOW_ADVANCED_DESC="Toggle if users should be able to see advanced search options." -COM_FINDER_CONFIG_SHOW_ADVANCED_DESCRIPTION="Toggle if users should be able to see advanced search options." -COM_FINDER_CONFIG_SHOW_ADVANCED_LABEL="Advanced Search" -COM_FINDER_CONFIG_SHOW_ADVANCED_TIPS_DESCRIPTION="Toggle if users should be able to see advanced search tips." -COM_FINDER_CONFIG_SHOW_ADVANCED_TIPS_LABEL="Advanced Tips" -COM_FINDER_CONFIG_SHOW_AUTOSUGGEST_DESCRIPTION="Toggle if automatic search suggestions should be displayed." -COM_FINDER_CONFIG_SHOW_AUTOSUGGEST_LABEL="Search Suggestions" -COM_FINDER_CONFIG_SHOW_DATE_FILTERS_DESC="Show the start and end date filters in the advanced search." -COM_FINDER_CONFIG_SHOW_DATE_FILTERS_DESCRIPTION="Show the start and end date filters in the advanced search." -COM_FINDER_CONFIG_SHOW_DATE_FILTERS_LABEL="Date Filters" -COM_FINDER_CONFIG_SHOW_DESCRIPTION_DESC="Toggle if the description should be displayed with search results." -COM_FINDER_CONFIG_SHOW_DESCRIPTION_DESCRIPTION="Toggle if the description should be displayed with search results." -COM_FINDER_CONFIG_SHOW_DESCRIPTION_LABEL="Result Description" -COM_FINDER_CONFIG_SHOW_EXPLAINED_QUERY_DESC="Show or hide a detailed explanation of the search requested." -COM_FINDER_CONFIG_SHOW_EXPLAINED_QUERY_LABEL="Query Explanation" -COM_FINDER_CONFIG_SHOW_FEED_DESC="Show the syndication feed link." -COM_FINDER_CONFIG_SHOW_FEED_LABEL="Show Feed" -COM_FINDER_CONFIG_SHOW_FEED_TEXT_DESC="Show the associated text with the feed, otherwise just the title is shown in the feed." -COM_FINDER_CONFIG_SHOW_FEED_TEXT_LABEL="Show Feed Text" -COM_FINDER_CONFIG_SHOW_SUGGESTED_QUERY_DESC="Whether to suggest alternative search terms when a search produces no results." -COM_FINDER_CONFIG_SHOW_SUGGESTED_QUERY_LABEL="Did You Mean" -COM_FINDER_CONFIG_SHOW_URL_DESC="Show the associated URL that for the item." -COM_FINDER_CONFIG_SHOW_URL_DESCRIPTION="Show the associated URL for the item." -COM_FINDER_CONFIG_SHOW_URL_LABEL="Result URL" -COM_FINDER_CONFIG_SORT_DIRECTION_DESC="The direction in which to sort the search results." -COM_FINDER_CONFIG_SORT_DIRECTION_LABEL="Sort Direction" -COM_FINDER_CONFIG_SORT_OPTION_ASCENDING="Ascending" -COM_FINDER_CONFIG_SORT_OPTION_DESCENDING="Descending" -COM_FINDER_CONFIG_SORT_OPTION_LIST_PRICE="List price" -COM_FINDER_CONFIG_SORT_OPTION_RELEVANCE="Relevance" -COM_FINDER_CONFIG_SORT_OPTION_START_DATE="Date" -COM_FINDER_CONFIG_SORT_ORDER_DESC="The field on which to sort the search results." -COM_FINDER_CONFIG_SORT_ORDER_LABEL="Sort Field" -COM_FINDER_CONFIG_STEMMER_DESCRIPTION="The language stemmer to use. Choose snowball if a stemmer for your language is not available or you have multilingual content." -COM_FINDER_CONFIG_STEMMER_ENABLE_DESCRIPTION="Enable language stemming if available." -COM_FINDER_CONFIG_STEMMER_ENABLE_LABEL="Enable Stemmer" -COM_FINDER_CONFIG_STEMMER_FR="French Only" -COM_FINDER_CONFIG_STEMMER_LABEL="Stemmer" -COM_FINDER_CONFIG_STEMMER_PORTER_EN="English Only" -COM_FINDER_CONFIG_STEMMER_SNOWBALL="Snowball" -COM_FINDER_CONFIG_TEXT_MULTIPLIER_DESCRIPTION="The multiplier is used to control how much influence matching text has on the overall relevance score of a search result. A multiplier is considered in relationship to the other multipliers. The body text comes from the summary and/or body of the content." -COM_FINDER_CONFIG_TEXT_MULTIPLIER_LABEL="Body Text Weight Multiplier" -COM_FINDER_CONFIG_TITLE_MULTIPLIER_DESCRIPTION="The multiplier is used to control how much influence matching text has on the overall relevance score of a search result. A multiplier is considered in relationship to the other multipliers. The title text comes from the title of the content." -COM_FINDER_CONFIG_TITLE_MULTIPLIER_LABEL="Title Text Weight Multiplier" -COM_FINDER_CONFIGURATION="Smart Search: Options" -COM_FINDER_CREATE_FILTER="Create a filter." -COM_FINDER_EDIT_FILTER="Edit Filter" -COM_FINDER_FIELD_CREATED_BY_ALIAS_DESC="Displayed name of the filter creator." -COM_FINDER_FIELD_CREATED_BY_ALIAS_LABEL="Alias" -COM_FINDER_FIELD_CREATED_BY_DESC="Creator of the filter." -COM_FINDER_FIELD_CREATED_BY_LABEL="Created By" -COM_FINDER_FIELD_MODIFIED_DESCRIPTION="The date and time that the filter was last modified." -COM_FINDER_FIELDSET_INDEX_OPTIONS_DESCRIPTION="Indexing options" -COM_FINDER_FIELDSET_INDEX_OPTIONS_LABEL="Index" -COM_FINDER_FIELDSET_SEARCH_OPTIONS_DESCRIPTION="Search options" -COM_FINDER_FIELDSET_SEARCH_OPTIONS_LABEL="Search" -COM_FINDER_FILTER_BRANCH_LABEL="Search by %s" -COM_FINDER_FILTER_BY="Show %s:" -COM_FINDER_FILTER_CONTENT_MAP_DESC="Filter the indexed content by content map." -COM_FINDER_FILTER_CONTENT_MAP_LABEL="Select the Content Map" -COM_FINDER_FILTER_EDIT_TOOLBAR_TITLE="Smart Search: Edit Filter" -COM_FINDER_FILTER_END_DATE_DESCRIPTION="Format YYYY-MM-DD" -COM_FINDER_FILTER_END_DATE_LABEL="End Date" -COM_FINDER_FILTER_FIELDSET_PARAMS="Filter Timeline" -COM_FINDER_FILTER_HIDE_ALL="Collapse all" -COM_FINDER_FILTER_MAP_COUNT="Map Count" -COM_FINDER_FILTER_MAP_COUNT_DESCRIPTION="The number of maps included in the filter." -COM_FINDER_FILTER_NEW_TOOLBAR_TITLE="Smart Search: New Filter" -COM_FINDER_FILTER_SEARCH_DESCRIPTION="Filter the list by a title." -COM_FINDER_FILTER_SELECT_CONTENT_MAP="- Select Content Map -" -COM_FINDER_FILTER_SELECT_ALL_LABEL="Search All" -COM_FINDER_FILTER_START_DATE_DESCRIPTION="Format YYYY-MM-DD" -COM_FINDER_FILTER_START_DATE_LABEL="Start Date" -COM_FINDER_FILTER_TIMESTAMP="Created On" -COM_FINDER_FILTER_SHOW_ALL="Expand all" -COM_FINDER_FILTER_TITLE_DESCRIPTION="The title of the filter." -COM_FINDER_FILTER_WHEN_AFTER="After" -COM_FINDER_FILTER_WHEN_BEFORE="Before" -COM_FINDER_FILTER_WHEN_END_DATE_DESCRIPTION="When to search relative to the end date (before, after or exactly)" -COM_FINDER_FILTER_WHEN_END_DATE_LABEL="When (End Date)" -COM_FINDER_FILTER_WHEN_EXACTLY="Exactly" -COM_FINDER_FILTER_WHEN_START_DATE_DESCRIPTION="When to search relative to the start date (before, after or exactly)" -COM_FINDER_FILTER_WHEN_START_DATE_LABEL="When (Start Date)" -COM_FINDER_FILTERS="Filters" -COM_FINDER_FILTERS_TOOLBAR_TITLE="Smart Search: Search Filters" -COM_FINDER_HEADING_CHILDREN="Maps" -COM_FINDER_HEADING_CREATED_BY="Created By" -COM_FINDER_HEADING_CREATED_BY_ASC="Created By ascending" -COM_FINDER_HEADING_CREATED_BY_DESC="Created By descending" -COM_FINDER_HEADING_CREATED_ON="Created On" -COM_FINDER_HEADING_CREATED_ON_ASC="Created On ascending" -COM_FINDER_HEADING_CREATED_ON_DESC="Created On descending" -COM_FINDER_HEADING_INDEXER="Smart Search Indexer" -COM_FINDER_HEADING_MAP_COUNT="Map Count" -COM_FINDER_HEADING_MAP_COUNT_ASC="Map Count ascending" -COM_FINDER_HEADING_MAP_COUNT_DESC="Map Count descending" -COM_FINDER_HEADING_NODES="Items" -COM_FINDER_INDEX="Index" -COM_FINDER_INDEX_CONFIRM_DELETE_PROMPT="Are you sure you want to delete the selected item(s)?" -COM_FINDER_INDEX_CONFIRM_PURGE_PROMPT="Are you sure you want to delete ALL items from the index? This can take a long time on large sites." -COM_FINDER_INDEX_DATE_INFO="Published Start: %s
Published End: %s
Content Start: %s
Content End: %s" -COM_FINDER_INDEX_DATE_INFO_TITLE="Link Date Information" -COM_FINDER_INDEX_FILTER_BY_STATE="Any Published State" -COM_FINDER_INDEX_HEADING_DETAILS="Details" -COM_FINDER_INDEX_HEADING_INDEX_DATE="Last Updated" -COM_FINDER_INDEX_HEADING_INDEX_DATE_ASC="Last Updated ascending" -COM_FINDER_INDEX_HEADING_INDEX_DATE_DESC="Last Updated descending" -COM_FINDER_INDEX_HEADING_INDEX_TYPE="Type" -COM_FINDER_INDEX_HEADING_INDEX_TYPE_ASC="Type ascending" -COM_FINDER_INDEX_HEADING_INDEX_TYPE_DESC="Type descending" -COM_FINDER_INDEX_HEADING_LINK_URL="Raw URL" -COM_FINDER_INDEX_HEADING_LINK_URL_ASC="Raw URL ascending" -COM_FINDER_INDEX_HEADING_LINK_URL_DESC="Raw URL descending" -COM_FINDER_INDEX_NO_CONTENT="No content matches your search criteria." -COM_FINDER_INDEX_NO_DATA="No content has been indexed." -COM_FINDER_INDEX_PLUGIN_CONTENT_NOT_ENABLED="The Smart Search Content Plugin is disabled. Changes to content will not update the Smart Search index if you do not enable this plugin." -COM_FINDER_INDEX_PURGE_FAILED="Failed to delete selected items." -COM_FINDER_INDEX_PURGE_SUCCESS="All items have been successfully deleted." -COM_FINDER_INDEX_SEARCH_DESC="Search in title, url and last updated date." -COM_FINDER_INDEX_SEARCH_LABEL="Search Indexed Content" -COM_FINDER_INDEX_TIP="Start the indexer by pressing the Index button in the toolbar." -COM_FINDER_INDEX_TOOLBAR_PURGE="Clear Index" -COM_FINDER_INDEX_TOOLBAR_TITLE="Smart Search: Indexed Content" -COM_FINDER_INDEX_TYPE_FILTER="Any Type of Content" -COM_FINDER_INDEXER_HEADER_COMPLETE="Indexing Complete" -COM_FINDER_INDEXER_HEADER_ERROR="An Error Has Occurred" -COM_FINDER_INDEXER_HEADER_INIT="Starting Indexer" -COM_FINDER_INDEXER_HEADER_OPTIMIZE="Optimising Index" -COM_FINDER_INDEXER_HEADER_RUNNING="Indexer Running" -COM_FINDER_INDEXER_INVALID_DRIVER="The indexer does not support processing on the %s database driver." -COM_FINDER_INDEXER_INVALID_PARSER="Invalid parser type %s" -COM_FINDER_INDEXER_INVALID_STEMMER="Invalid stemmer type %s" -COM_FINDER_INDEXER_MESSAGE_COMPLETE="The indexing process is complete. It is now safe to close this window." -COM_FINDER_INDEXER_MESSAGE_INIT="The indexer is being initialised. Do not close this window." -COM_FINDER_INDEXER_MESSAGE_OPTIMIZE="The index tables are being optimised for the best possible performance. Do not close this window." -COM_FINDER_INDEXER_MESSAGE_RUNNING="Your content is being indexed. Do not close this window." -COM_FINDER_ITEM_X_ONLY="%s Only" -COM_FINDER_ITEMS="Content" -COM_FINDER_MAPS="Maps" -COM_FINDER_MAPS_CONFIRM_DELETE_PROMPT="Are you sure you want to delete the selected map(s)?" -COM_FINDER_MAPS_COUNT_PUBLISHED_ITEMS="Published Indexed Content" -COM_FINDER_MAPS_COUNT_UNPUBLISHED_ITEMS="Unpublished Indexed Content" -COM_FINDER_MAPS_MULTILANG="Note: Language filter system plugin has been enabled, so this branch will not be used." -COM_FINDER_MAPS_NO_CONTENT="No results to display. Either no content has been indexed or no content meets your filter criteria." -COM_FINDER_MAPS_SELECT_BRANCH="- Select Map Group -" -COM_FINDER_MAPS_SELECT_TYPE="- Select Type of Content -" -COM_FINDER_MAPS_TOOLBAR_TITLE="Smart Search: Content Maps" -COM_FINDER_MESSAGE_RETURNED="The following message was returned by the server:" -COM_FINDER_N_ITEMS_CHECKED_IN_0="No item successfully checked in." -COM_FINDER_N_ITEMS_CHECKED_IN_1="%d item successfully checked in." -COM_FINDER_N_ITEMS_CHECKED_IN_MORE="%d items successfully checked in." -COM_FINDER_N_ITEMS_DELETED="%d items successfully deleted." -COM_FINDER_N_ITEMS_DELETED_1="%d item successfully deleted." -COM_FINDER_N_ITEMS_PUBLISHED="%d items successfully published." -COM_FINDER_N_ITEMS_PUBLISHED_1="%d item successfully published." -COM_FINDER_N_ITEMS_TRASHED="%d items successfully trashed." -COM_FINDER_N_ITEMS_TRASHED_1="%d item successfully trashed." -COM_FINDER_N_ITEMS_UNPUBLISHED="%d items successfully unpublished." -COM_FINDER_N_ITEMS_UNPUBLISHED_1="%d item successfully unpublished." -COM_FINDER_NO_ERROR_RETURNED="No error was returned. Make sure error reporting is enabled." -COM_FINDER_NO_FILTERS="No filters have been created yet." -COM_FINDER_NO_RESULTS="No results match your search criteria." -COM_FINDER_NO_RESULTS_OR_FILTERS="No results match your search criteria or no filters have been created yet." -COM_FINDER_QUERY_FILTER_TODAY="Today" -COM_FINDER_QUERY_OPERATOR_AND="And" -COM_FINDER_QUERY_OPERATOR_NOT="Not" -COM_FINDER_QUERY_OPERATOR_OR="Or" -COM_FINDER_SEARCH_FILTER_SEARCH_DESC="Search in filter title." -COM_FINDER_SEARCH_FILTER_SEARCH_LABEL="Search Filters" -COM_FINDER_SEARCH_LABEL="Search %s:" -COM_FINDER_SEARCH_SEARCH_QUERY_DESC="Search in content map title." -COM_FINDER_SEARCH_SEARCH_QUERY_LABEL="Search Content Maps" -COM_FINDER_SELECT_SEARCH_FILTER="Select filter" -COM_FINDER_STATISTICS="Statistics" -COM_FINDER_STATISTICS_LINK_TYPE_COUNT="Count" -COM_FINDER_STATISTICS_LINK_TYPE_HEADING="Link Type" -COM_FINDER_STATISTICS_LINK_TYPE_TOTAL="Total" -COM_FINDER_STATISTICS_STATS_DESCRIPTION="The indexed content on this site includes %s terms across %s links with %s attributes in %s branches." -COM_FINDER_STATISTICS_TITLE="Smart Search Statistics" -COM_FINDER_SUBMENU_FILTERS="Search Filters" -COM_FINDER_SUBMENU_INDEX="Indexed Content" -COM_FINDER_SUBMENU_MAPS="Content Maps" -COM_FINDER_XML_DESCRIPTION="Smart Search." diff --git a/administrator/language/en-GB/en-GB.com_finder.sys.ini b/administrator/language/en-GB/en-GB.com_finder.sys.ini deleted file mode 100644 index cdf24135e6361..0000000000000 --- a/administrator/language/en-GB/en-GB.com_finder.sys.ini +++ /dev/null @@ -1,10 +0,0 @@ -; Joomla! Project -; Copyright (C) 2005 - 2016 Open Source Matters. All rights reserved. -; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php -; Note : All ini files need to be saved as UTF-8 - -COM_FINDER="Smart Search" -COM_FINDER_XML_DESCRIPTION="Smart Search" - -COM_FINDER_MENU_SEARCH_VIEW_DEFAULT_TEXT="The default search layout." -COM_FINDER_MENU_SEARCH_VIEW_DEFAULT_TITLE="Search" diff --git a/administrator/language/en-GB/en-GB.com_search.ini b/administrator/language/en-GB/en-GB.com_search.ini index e6e2fa125ed13..3acfdaf0efd4d 100644 --- a/administrator/language/en-GB/en-GB.com_search.ini +++ b/administrator/language/en-GB/en-GB.com_search.ini @@ -45,3 +45,219 @@ COM_SEARCH_SEARCH_IN_PHRASE="Search in phrases." COM_SEARCH_SHOW_SEARCH_RESULTS="Show Search Results" COM_SEARCH_XML_DESCRIPTION="Component for search functions." +COM_SEARCH_ALLOW_EMPTY_QUERY_DESC="Only if a filter is selected, allow an empty search string to initiate a search within the filter constraints." +COM_SEARCH_ALLOW_EMPTY_QUERY_LABEL="Allow Empty Search" +COM_SEARCH_AN_ERROR_HAS_OCCURRED="An Error Has Occurred" +COM_SEARCH_CONFIG_ALLOW_EMPTY_QUERY_DESCRIPTION="Only if a filter is selected, allow an empty search string to initiate a search within the filter restraints." +COM_SEARCH_CONFIG_ALLOW_EMPTY_QUERY_LABEL="Allow Empty Search" +COM_SEARCH_CONFIG_BATCH_SIZE_DESCRIPTION="The batch size controls how many items are processed per batch. Large batch sizes require lots of memory whereas small batch sizes require less memory but execute more requests which tends to take longer." +COM_SEARCH_CONFIG_BATCH_SIZE_LABEL="Indexer Batch Size" +COM_SEARCH_CONFIG_DESCRIPTION_LENGTH_DESC="Description text for search results will be truncated to the specified character length." +COM_SEARCH_CONFIG_DESCRIPTION_LENGTH_DESCRIPTION="Description text for search results will be truncated to the specified character length." +COM_SEARCH_CONFIG_DESCRIPTION_LENGTH_LABEL="Description Length" +COM_SEARCH_CONFIG_ENABLE_LOGGING_DESCRIPTION="Enable this option to create a log file in your site's logs folder during the index process. This file is useful for troubleshooting issues with the index process. It is recommended that logging be disabled unless necessary." +COM_SEARCH_CONFIG_ENABLE_LOGGING_LABEL="Enable Logging" +COM_SEARCH_CONFIG_EXPAND_ADVANCED_DESC="Toggle if the advanced search options should be expanded by default." +COM_SEARCH_CONFIG_EXPAND_ADVANCED_DESCRIPTION="Toggle if the advanced search options should be expanded by default." +COM_SEARCH_CONFIG_EXPAND_ADVANCED_LABEL="Expand Advanced Search" +COM_SEARCH_CONFIG_FIELD_OPENSEARCH_DESCRIPTON_DESCRIPTION="Description displayed for this site as a search provider." +COM_SEARCH_CONFIG_FIELD_OPENSEARCH_DESCRIPTON_LABEL="OpenSearch Description" +COM_SEARCH_CONFIG_FIELD_OPENSEARCH_NAME_DESCRIPTION="Name displayed for this site as a search provider." +COM_SEARCH_CONFIG_FIELD_OPENSEARCH_NAME_LABEL="OpenSearch Name" +COM_SEARCH_CONFIG_GATHER_SEARCH_STATISTICS_DESCRIPTION="Record the search phrases submitted by visitors." +COM_SEARCH_CONFIG_GATHER_SEARCH_STATISTICS_LABEL="Gather Search Statistics" +COM_SEARCH_CONFIG_HILIGHT_CONTENT_SEARCH_TERMS_DESCRIPTION="Toggle if search terms should be highlighted in search results." +COM_SEARCH_CONFIG_HILIGHT_CONTENT_SEARCH_TERMS_LABEL="Highlight Search Terms" +COM_SEARCH_CONFIG_MEMORY_TABLE_LIMIT_DESCRIPTION="The memory table limit should not be changed unless you are getting errors indicating that the finder_tokens or finder_tokens_aggregate tables are full. The default is 30,000." +COM_SEARCH_CONFIG_MEMORY_TABLE_LIMIT_LABEL="Memory Table Limit" +COM_SEARCH_CONFIG_META_MULTIPLIER_DESCRIPTION="The multiplier is used to control how much influence matching text has on the overall relevance score of a search result. A multiplier is considered in relationship to the other multipliers. The meta data comes from a number of sources including the meta keywords and meta description, author names, etc." +COM_SEARCH_CONFIG_META_MULTIPLIER_LABEL="Meta Data Weight Multiplier" +COM_SEARCH_CONFIG_MISC_MULTIPLIER_DESCRIPTION="The multiplier is used to control how much influence matching text has on the overall relevance score of a search result. A multiplier is considered in relationship to the other multipliers. The miscellaneous text comes from a number of sources including comments and other associated data." +COM_SEARCH_CONFIG_MISC_MULTIPLIER_LABEL="Miscellaneous Text Weight Multiplier" +COM_SEARCH_CONFIG_PATH_MULTIPLIER_DESCRIPTION="The multiplier is used to control how much influence matching text has on the overall relevance score of a search result. A multiplier is considered in relationship to the other multipliers. The path text comes from the SEF URL of the content." +COM_SEARCH_CONFIG_PATH_MULTIPLIER_LABEL="Path Text Weight Multiplier" +COM_SEARCH_CONFIG_SHOW_ADVANCED_DESC="Toggle if users should be able to see advanced search options." +COM_SEARCH_CONFIG_SHOW_ADVANCED_DESCRIPTION="Toggle if users should be able to see advanced search options." +COM_SEARCH_CONFIG_SHOW_ADVANCED_LABEL="Advanced Search" +COM_SEARCH_CONFIG_SHOW_ADVANCED_TIPS_DESCRIPTION="Toggle if users should be able to see advanced search tips." +COM_SEARCH_CONFIG_SHOW_ADVANCED_TIPS_LABEL="Advanced Tips" +COM_SEARCH_CONFIG_SHOW_AUTOSUGGEST_DESCRIPTION="Toggle if automatic search suggestions should be displayed." +COM_SEARCH_CONFIG_SHOW_AUTOSUGGEST_LABEL="Search Suggestions" +COM_SEARCH_CONFIG_SHOW_DATE_FILTERS_DESC="Show the start and end date filters in the advanced search." +COM_SEARCH_CONFIG_SHOW_DATE_FILTERS_DESCRIPTION="Show the start and end date filters in the advanced search." +COM_SEARCH_CONFIG_SHOW_DATE_FILTERS_LABEL="Date Filters" +COM_SEARCH_CONFIG_SHOW_DESCRIPTION_DESC="Toggle if the description should be displayed with search results." +COM_SEARCH_CONFIG_SHOW_DESCRIPTION_DESCRIPTION="Toggle if the description should be displayed with search results." +COM_SEARCH_CONFIG_SHOW_DESCRIPTION_LABEL="Result Description" +COM_SEARCH_CONFIG_SHOW_EXPLAINED_QUERY_DESC="Show or hide a detailed explanation of the search requested." +COM_SEARCH_CONFIG_SHOW_EXPLAINED_QUERY_LABEL="Query Explanation" +COM_SEARCH_CONFIG_SHOW_FEED_DESC="Show the syndication feed link." +COM_SEARCH_CONFIG_SHOW_FEED_LABEL="Show Feed" +COM_SEARCH_CONFIG_SHOW_FEED_TEXT_DESC="Show the associated text with the feed, otherwise just the title is shown in the feed." +COM_SEARCH_CONFIG_SHOW_FEED_TEXT_LABEL="Show Feed Text" +COM_SEARCH_CONFIG_SHOW_SUGGESTED_QUERY_DESC="Whether to suggest alternative search terms when a search produces no results." +COM_SEARCH_CONFIG_SHOW_SUGGESTED_QUERY_LABEL="Did You Mean" +COM_SEARCH_CONFIG_SHOW_URL_DESC="Show the associated URL that for the item." +COM_SEARCH_CONFIG_SHOW_URL_DESCRIPTION="Show the associated URL for the item." +COM_SEARCH_CONFIG_SHOW_URL_LABEL="Result URL" +COM_SEARCH_CONFIG_SORT_DIRECTION_DESC="The direction in which to sort the search results." +COM_SEARCH_CONFIG_SORT_DIRECTION_LABEL="Sort Direction" +COM_SEARCH_CONFIG_SORT_OPTION_ASCENDING="Ascending" +COM_SEARCH_CONFIG_SORT_OPTION_DESCENDING="Descending" +COM_SEARCH_CONFIG_SORT_OPTION_LIST_PRICE="List price" +COM_SEARCH_CONFIG_SORT_OPTION_RELEVANCE="Relevance" +COM_SEARCH_CONFIG_SORT_OPTION_START_DATE="Date" +COM_SEARCH_CONFIG_SORT_ORDER_DESC="The field on which to sort the search results." +COM_SEARCH_CONFIG_SORT_ORDER_LABEL="Sort Field" +COM_SEARCH_CONFIG_STEMMER_DESCRIPTION="The language stemmer to use. Choose snowball if a stemmer for your language is not available or you have multilingual content." +COM_SEARCH_CONFIG_STEMMER_ENABLE_DESCRIPTION="Enable language stemming if available." +COM_SEARCH_CONFIG_STEMMER_ENABLE_LABEL="Enable Stemmer" +COM_SEARCH_CONFIG_STEMMER_FR="French Only" +COM_SEARCH_CONFIG_STEMMER_LABEL="Stemmer" +COM_SEARCH_CONFIG_STEMMER_PORTER_EN="English Only" +COM_SEARCH_CONFIG_STEMMER_SNOWBALL="Snowball" +COM_SEARCH_CONFIG_TEXT_MULTIPLIER_DESCRIPTION="The multiplier is used to control how much influence matching text has on the overall relevance score of a search result. A multiplier is considered in relationship to the other multipliers. The body text comes from the summary and/or body of the content." +COM_SEARCH_CONFIG_TEXT_MULTIPLIER_LABEL="Body Text Weight Multiplier" +COM_SEARCH_CONFIG_TITLE_MULTIPLIER_DESCRIPTION="The multiplier is used to control how much influence matching text has on the overall relevance score of a search result. A multiplier is considered in relationship to the other multipliers. The title text comes from the title of the content." +COM_SEARCH_CONFIG_TITLE_MULTIPLIER_LABEL="Title Text Weight Multiplier" +COM_SEARCH_CONFIGURATION="Smart Search: Options" +COM_SEARCH_CREATE_FILTER="Create a filter." +COM_SEARCH_EDIT_FILTER="Edit Filter" +COM_SEARCH_FIELD_CREATED_BY_ALIAS_DESC="Displayed name of the filter creator." +COM_SEARCH_FIELD_CREATED_BY_ALIAS_LABEL="Alias" +COM_SEARCH_FIELD_CREATED_BY_DESC="Creator of the filter." +COM_SEARCH_FIELD_CREATED_BY_LABEL="Created By" +COM_SEARCH_FIELD_MODIFIED_DESCRIPTION="The date and time that the filter was last modified." +COM_SEARCH_FIELDSET_INDEX_OPTIONS_DESCRIPTION="Indexing options" +COM_SEARCH_FIELDSET_INDEX_OPTIONS_LABEL="Index" +COM_SEARCH_FIELDSET_SEARCH_OPTIONS_DESCRIPTION="Search options" +COM_SEARCH_FIELDSET_SEARCH_OPTIONS_LABEL="Search" +COM_SEARCH_FILTER_BRANCH_LABEL="Search by %s" +COM_SEARCH_FILTER_BY="Show %s:" +COM_SEARCH_FILTER_CONTENT_MAP_DESC="Filter the indexed content by content map." +COM_SEARCH_FILTER_CONTENT_MAP_LABEL="Select the Content Map" +COM_SEARCH_FILTER_EDIT_TOOLBAR_TITLE="Smart Search: Edit Filter" +COM_SEARCH_FILTER_END_DATE_DESCRIPTION="Format YYYY-MM-DD" +COM_SEARCH_FILTER_END_DATE_LABEL="End Date" +COM_SEARCH_FILTER_FIELDSET_PARAMS="Filter Timeline" +COM_SEARCH_FILTER_HIDE_ALL="Collapse all" +COM_SEARCH_FILTER_MAP_COUNT="Map Count" +COM_SEARCH_FILTER_MAP_COUNT_DESCRIPTION="The number of maps included in the filter." +COM_SEARCH_FILTER_NEW_TOOLBAR_TITLE="Smart Search: New Filter" +COM_SEARCH_FILTER_SEARCH_DESCRIPTION="Filter the list by a title." +COM_SEARCH_FILTER_SELECT_CONTENT_MAP="- Select Content Map -" +COM_SEARCH_FILTER_SELECT_ALL_LABEL="Search All" +COM_SEARCH_FILTER_START_DATE_DESCRIPTION="Format YYYY-MM-DD" +COM_SEARCH_FILTER_START_DATE_LABEL="Start Date" +COM_SEARCH_FILTER_TIMESTAMP="Created On" +COM_SEARCH_FILTER_SHOW_ALL="Expand all" +COM_SEARCH_FILTER_TITLE_DESCRIPTION="The title of the filter." +COM_SEARCH_FILTER_WHEN_AFTER="After" +COM_SEARCH_FILTER_WHEN_BEFORE="Before" +COM_SEARCH_FILTER_WHEN_END_DATE_DESCRIPTION="When to search relative to the end date (before, after or exactly)" +COM_SEARCH_FILTER_WHEN_END_DATE_LABEL="When (End Date)" +COM_SEARCH_FILTER_WHEN_EXACTLY="Exactly" +COM_SEARCH_FILTER_WHEN_START_DATE_DESCRIPTION="When to search relative to the start date (before, after or exactly)" +COM_SEARCH_FILTER_WHEN_START_DATE_LABEL="When (Start Date)" +COM_SEARCH_FILTERS="Filters" +COM_SEARCH_FILTERS_TOOLBAR_TITLE="Smart Search: Search Filters" +COM_SEARCH_HEADING_CHILDREN="Maps" +COM_SEARCH_HEADING_CREATED_BY="Created By" +COM_SEARCH_HEADING_CREATED_BY_ASC="Created By ascending" +COM_SEARCH_HEADING_CREATED_BY_DESC="Created By descending" +COM_SEARCH_HEADING_CREATED_ON="Created On" +COM_SEARCH_HEADING_CREATED_ON_ASC="Created On ascending" +COM_SEARCH_HEADING_CREATED_ON_DESC="Created On descending" +COM_SEARCH_HEADING_INDEXER="Smart Search Indexer" +COM_SEARCH_HEADING_MAP_COUNT="Map Count" +COM_SEARCH_HEADING_MAP_COUNT_ASC="Map Count ascending" +COM_SEARCH_HEADING_MAP_COUNT_DESC="Map Count descending" +COM_SEARCH_HEADING_NODES="Items" +COM_SEARCH_INDEX="Index" +COM_SEARCH_INDEX_CONFIRM_DELETE_PROMPT="Are you sure you want to delete the selected item(s)?" +COM_SEARCH_INDEX_CONFIRM_PURGE_PROMPT="Are you sure you want to delete ALL items from the index? This can take a long time on large sites." +COM_SEARCH_INDEX_DATE_INFO="Published Start: %s
Published End: %s
Content Start: %s
Content End: %s" +COM_SEARCH_INDEX_DATE_INFO_TITLE="Link Date Information" +COM_SEARCH_INDEX_FILTER_BY_STATE="Any Published State" +COM_SEARCH_INDEX_HEADING_DETAILS="Details" +COM_SEARCH_INDEX_HEADING_INDEX_DATE="Last Updated" +COM_SEARCH_INDEX_HEADING_INDEX_DATE_ASC="Last Updated ascending" +COM_SEARCH_INDEX_HEADING_INDEX_DATE_DESC="Last Updated descending" +COM_SEARCH_INDEX_HEADING_INDEX_TYPE="Type" +COM_SEARCH_INDEX_HEADING_INDEX_TYPE_ASC="Type ascending" +COM_SEARCH_INDEX_HEADING_INDEX_TYPE_DESC="Type descending" +COM_SEARCH_INDEX_HEADING_LINK_URL="Raw URL" +COM_SEARCH_INDEX_HEADING_LINK_URL_ASC="Raw URL ascending" +COM_SEARCH_INDEX_HEADING_LINK_URL_DESC="Raw URL descending" +COM_SEARCH_INDEX_NO_CONTENT="No content matches your search criteria." +COM_SEARCH_INDEX_NO_DATA="No content has been indexed." +COM_SEARCH_INDEX_PLUGIN_CONTENT_NOT_ENABLED="The Smart Search Content Plugin is disabled. Changes to content will not update the Smart Search index if you do not enable this plugin." +COM_SEARCH_INDEX_PURGE_FAILED="Failed to delete selected items." +COM_SEARCH_INDEX_PURGE_SUCCESS="All items have been successfully deleted." +COM_SEARCH_INDEX_SEARCH_DESC="Search in title, url and last updated date." +COM_SEARCH_INDEX_SEARCH_LABEL="Search Indexed Content" +COM_SEARCH_INDEX_TIP="Start the indexer by pressing the Index button in the toolbar." +COM_SEARCH_INDEX_TOOLBAR_PURGE="Clear Index" +COM_SEARCH_INDEX_TOOLBAR_TITLE="Smart Search: Indexed Content" +COM_SEARCH_INDEX_TYPE_FILTER="Any Type of Content" +COM_SEARCH_INDEXER_HEADER_COMPLETE="Indexing Complete" +COM_SEARCH_INDEXER_HEADER_ERROR="An Error Has Occurred" +COM_SEARCH_INDEXER_HEADER_INIT="Starting Indexer" +COM_SEARCH_INDEXER_HEADER_OPTIMIZE="Optimising Index" +COM_SEARCH_INDEXER_HEADER_RUNNING="Indexer Running" +COM_SEARCH_INDEXER_INVALID_DRIVER="The indexer does not support processing on the %s database driver." +COM_SEARCH_INDEXER_INVALID_PARSER="Invalid parser type %s" +COM_SEARCH_INDEXER_INVALID_STEMMER="Invalid stemmer type %s" +COM_SEARCH_INDEXER_MESSAGE_COMPLETE="The indexing process is complete. It is now safe to close this window." +COM_SEARCH_INDEXER_MESSAGE_INIT="The indexer is being initialised. Do not close this window." +COM_SEARCH_INDEXER_MESSAGE_OPTIMIZE="The index tables are being optimised for the best possible performance. Do not close this window." +COM_SEARCH_INDEXER_MESSAGE_RUNNING="Your content is being indexed. Do not close this window." +COM_SEARCH_ITEM_X_ONLY="%s Only" +COM_SEARCH_ITEMS="Content" +COM_SEARCH_MAPS="Maps" +COM_SEARCH_MAPS_CONFIRM_DELETE_PROMPT="Are you sure you want to delete the selected map(s)?" +COM_SEARCH_MAPS_COUNT_PUBLISHED_ITEMS="Published Indexed Content" +COM_SEARCH_MAPS_COUNT_UNPUBLISHED_ITEMS="Unpublished Indexed Content" +COM_SEARCH_MAPS_MULTILANG="Note: Language filter system plugin has been enabled, so this branch will not be used." +COM_SEARCH_MAPS_NO_CONTENT="No results to display. Either no content has been indexed or no content meets your filter criteria." +COM_SEARCH_MAPS_SELECT_BRANCH="- Select Map Group -" +COM_SEARCH_MAPS_SELECT_TYPE="- Select Type of Content -" +COM_SEARCH_MAPS_TOOLBAR_TITLE="Smart Search: Content Maps" +COM_SEARCH_MESSAGE_RETURNED="The following message was returned by the server:" +COM_SEARCH_N_ITEMS_CHECKED_IN_0="No item successfully checked in." +COM_SEARCH_N_ITEMS_CHECKED_IN_1="%d item successfully checked in." +COM_SEARCH_N_ITEMS_CHECKED_IN_MORE="%d items successfully checked in." +COM_SEARCH_N_ITEMS_DELETED="%d items successfully deleted." +COM_SEARCH_N_ITEMS_DELETED_1="%d item successfully deleted." +COM_SEARCH_N_ITEMS_PUBLISHED="%d items successfully published." +COM_SEARCH_N_ITEMS_PUBLISHED_1="%d item successfully published." +COM_SEARCH_N_ITEMS_TRASHED="%d items successfully trashed." +COM_SEARCH_N_ITEMS_TRASHED_1="%d item successfully trashed." +COM_SEARCH_N_ITEMS_UNPUBLISHED="%d items successfully unpublished." +COM_SEARCH_N_ITEMS_UNPUBLISHED_1="%d item successfully unpublished." +COM_SEARCH_NO_ERROR_RETURNED="No error was returned. Make sure error reporting is enabled." +COM_SEARCH_NO_FILTERS="No filters have been created yet." +COM_SEARCH_NO_RESULTS="No results match your search criteria." +COM_SEARCH_NO_RESULTS_OR_FILTERS="No results match your search criteria or no filters have been created yet." +COM_SEARCH_QUERY_FILTER_TODAY="Today" +COM_SEARCH_QUERY_OPERATOR_AND="And" +COM_SEARCH_QUERY_OPERATOR_NOT="Not" +COM_SEARCH_QUERY_OPERATOR_OR="Or" +COM_SEARCH_SEARCH_FILTER_SEARCH_DESC="Search in filter title." +COM_SEARCH_SEARCH_FILTER_SEARCH_LABEL="Search Filters" +COM_SEARCH_SEARCH_LABEL="Search %s:" +COM_SEARCH_SEARCH_SEARCH_QUERY_DESC="Search in content map title." +COM_SEARCH_SEARCH_SEARCH_QUERY_LABEL="Search Content Maps" +COM_SEARCH_SELECT_SEARCH_FILTER="Select filter" +COM_SEARCH_STATISTICS="Statistics" +COM_SEARCH_STATISTICS_LINK_TYPE_COUNT="Count" +COM_SEARCH_STATISTICS_LINK_TYPE_HEADING="Link Type" +COM_SEARCH_STATISTICS_LINK_TYPE_TOTAL="Total" +COM_SEARCH_STATISTICS_STATS_DESCRIPTION="The indexed content on this site includes %s terms across %s links with %s attributes in %s branches." +COM_SEARCH_STATISTICS_TITLE="Smart Search Statistics" +COM_SEARCH_SUBMENU_FILTERS="Search Filters" +COM_SEARCH_SUBMENU_INDEX="Indexed Content" +COM_SEARCH_SUBMENU_MAPS="Content Maps" +COM_SEARCH_SUBMENU_SEARCHES="Search Statistics" +COM_SEARCH_XML_DESCRIPTION="Smart Search." + diff --git a/administrator/language/en-GB/en-GB.search.php b/administrator/language/en-GB/en-GB.search.php new file mode 100644 index 0000000000000..94453f7a5705a --- /dev/null +++ b/administrator/language/en-GB/en-GB.search.php @@ -0,0 +1,415 @@ + 1) { + self::replace($word, 'e', ''); + + } else if (self::m(substr($word, 0, -1)) == 1) { + + if (!self::cvc(substr($word, 0, -1))) { + self::replace($word, 'e', ''); + } + } + } + + // Part b + if (self::m($word) > 1 AND self::doubleConsonant($word) AND substr($word, -1) == 'l') { + $word = substr($word, 0, -1); + } + + return $word; + } + + + /** + * Replaces the first string with the second, at the end of the string. If third + * arg is given, then the preceding string must match that m count at least. + * + * @param string $str String to check + * @param string $check Ending to check for + * @param string $repl Replacement string + * @param int $m Optional minimum number of m() to meet + * @return bool Whether the $check string was at the end + * of the $str string. True does not necessarily mean + * that it was replaced. + */ + private static function replace(&$str, $check, $repl, $m = null) + { + $len = 0 - strlen($check); + + if (substr($str, $len) == $check) { + $substr = substr($str, 0, $len); + if (is_null($m) OR self::m($substr) > $m) { + $str = $substr . $repl; + } + + return true; + } + + return false; + } + + + /** + * What, you mean it's not obvious from the name? + * + * m() measures the number of consonant sequences in $str. if c is + * a consonant sequence and v a vowel sequence, and <..> indicates arbitrary + * presence, + * + * gives 0 + * vc gives 1 + * vcvc gives 2 + * vcvcvc gives 3 + * + * @param string $str The string to return the m count for + * @return int The m count + */ + private static function m($str) + { + $c = self::$regex_consonant; + $v = self::$regex_vowel; + + $str = preg_replace("#^$c+#", '', $str); + $str = preg_replace("#$v+$#", '', $str); + + preg_match_all("#($v+$c+)#", $str, $matches); + + return count($matches[1]); + } + + + /** + * Returns true/false as to whether the given string contains two + * of the same consonant next to each other at the end of the string. + * + * @param string $str String to check + * @return bool Result + */ + private static function doubleConsonant($str) + { + $c = self::$regex_consonant; + + return preg_match("#$c{2}$#", $str, $matches) AND $matches[0]{0} == $matches[0]{1}; + } + + + /** + * Checks for ending CVC sequence where second C is not W, X or Y + * + * @param string $str String to check + * @return bool Result + */ + private static function cvc($str) + { + $c = self::$regex_consonant; + $v = self::$regex_vowel; + + return preg_match("#($c$v$c)$#", $str, $matches) + AND strlen($matches[1]) == 3 + AND $matches[1]{2} != 'w' + AND $matches[1]{2} != 'x' + AND $matches[1]{2} != 'y'; + } +} \ No newline at end of file diff --git a/components/com_finder/controller.php b/components/com_finder/controller.php deleted file mode 100644 index 2ceae7ab6c610..0000000000000 --- a/components/com_finder/controller.php +++ /dev/null @@ -1,57 +0,0 @@ -input; - $cachable = true; - - // Load plugin language files. - FinderHelperLanguage::loadPluginLanguage(); - - // Set the default view name and format from the Request. - $viewName = $input->get('view', 'search', 'word'); - $input->set('view', $viewName); - - // Don't cache view for search queries - if ($input->get('q', null, 'string') || $input->get('f', null, 'int') || $input->get('t', null, 'array')) - { - $cachable = false; - } - - $safeurlparams = array( - 'f' => 'INT', - 'lang' => 'CMD' - ); - - return parent::display($cachable, $safeurlparams); - } -} diff --git a/components/com_finder/finder.php b/components/com_finder/finder.php deleted file mode 100644 index eea5a49bcefa3..0000000000000 --- a/components/com_finder/finder.php +++ /dev/null @@ -1,16 +0,0 @@ -execute(JFactory::getApplication()->input->get('task')); -$controller->redirect(); diff --git a/components/com_finder/router.php b/components/com_finder/router.php deleted file mode 100644 index 2639a7ad58fe0..0000000000000 --- a/components/com_finder/router.php +++ /dev/null @@ -1,162 +0,0 @@ -menu->getItem($query['Itemid']); - - // Check if the view matches. - if ($item && @$item->query['view'] === @$query['view']) - { - unset($query['view']); - } - - // Check if the search query filter matches. - if ($item && @$item->query['f'] === @$query['f']) - { - unset($query['f']); - } - - // Check if the search query string matches. - if ($item && @$item->query['q'] === @$query['q']) - { - unset($query['q']); - } - - return $segments; - } - - /* - * Lastly, handle a route with no menu item id. Fortunately, we only need - * to deal with the view as the other route variables are supposed to stay - * in the query string. - */ - if (isset($query['view'])) - { - // Add the view to the segments. - $segments[] = $query['view']; - unset($query['view']); - } - - $total = count($segments); - - for ($i = 0; $i < $total; $i++) - { - $segments[$i] = str_replace(':', '-', $segments[$i]); - } - - return $segments; - } - - /** - * Parse the segments of a URL. - * - * @param array &$segments The segments of the URL to parse. - * - * @return array The URL attributes to be used by the application. - * - * @since 3.3 - */ - public function parse(&$segments) - { - $total = count($segments); - $vars = array(); - - for ($i = 0; $i < $total; $i++) - { - $segments[$i] = preg_replace('/-/', ':', $segments[$i], 1); - } - - // Check if the view segment is set and it equals search or advanced. - if (@$segments[0] === 'search' || @$segments[0] === 'advanced') - { - $vars['view'] = $segments[0]; - } - - return $vars; - } -} - -/** - * Finder router functions - * - * These functions are proxys for the new router interface - * for old SEF extensions. - * - * @param array &$query An array of URL arguments - * - * @return array The URL arguments to use to assemble the subsequent URL. - * - * @deprecated 4.0 Use Class based routers instead - */ -function FinderBuildRoute(&$query) -{ - $router = new FinderRouter; - - return $router->build($query); -} - -/** - * Finder router functions - * - * These functions are proxys for the new router interface - * for old SEF extensions. - * - * @param array $segments The segments of the URL to parse. - * - * @return array The URL attributes to be used by the application. - * - * @deprecated 4.0 Use Class based routers instead - */ -function FinderParseRoute($segments) -{ - $router = new FinderRouter; - - return $router->parse($segments); -} diff --git a/components/com_finder/views/search/metadata.xml b/components/com_finder/views/search/metadata.xml deleted file mode 100644 index 5c0525632b10a..0000000000000 --- a/components/com_finder/views/search/metadata.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/components/com_finder/views/search/view.html.php b/components/com_finder/views/search/view.html.php deleted file mode 100644 index 7a1f88eac12e9..0000000000000 --- a/components/com_finder/views/search/view.html.php +++ /dev/null @@ -1,253 +0,0 @@ -getParams(); - - // Get view data. - $state = $this->get('State'); - $query = $this->get('Query'); - JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderQuery') : null; - $results = $this->get('Results'); - JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderResults') : null; - $total = $this->get('Total'); - JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderTotal') : null; - $pagination = $this->get('Pagination'); - JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderPagination') : null; - - // Check for errors. - if (count($errors = $this->get('Errors'))) - { - throw new JViewGenericdataexception(implode("\n", $errors), 500); - } - - // Configure the pathway. - if (!empty($query->input)) - { - $app->getPathWay()->addItem($this->escape($query->input)); - } - - // Push out the view data. - $this->state = &$state; - $this->params = &$params; - $this->query = &$query; - $this->results = &$results; - $this->total = &$total; - $this->pagination = &$pagination; - - // Check for a double quote in the query string. - if (strpos($this->query->input, '"')) - { - // Get the application router. - $router =& $app::getRouter(); - - // Fix the q variable in the URL. - if ($router->getVar('q') !== $this->query->input) - { - $router->setVar('q', $this->query->input); - } - } - - // Log the search - JSearchHelper::logSearch($this->query->input, 'com_finder'); - - // Push out the query data. - JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html'); - $this->suggested = JHtml::_('query.suggested', $query); - $this->explained = JHtml::_('query.explained', $query); - - // Escape strings for HTML output - $this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx')); - - // Check for layout override only if this is not the active menu item - // If it is the active menu item, then the view and category id will match - $active = $app->getMenu()->getActive(); - if (isset($active->query['layout'])) - { - // We need to set the layout in case this is an alternative menu item (with an alternative layout) - $this->setLayout($active->query['layout']); - } - - $this->prepareDocument($query); - - JDEBUG ? JProfiler::getInstance('Application')->mark('beforeFinderLayout') : null; - - parent::display($tpl); - - JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderLayout') : null; - } - - /** - * Method to get hidden input fields for a get form so that control variables - * are not lost upon form submission - * - * @return string A string of hidden input form fields - * - * @since 2.5 - */ - protected function getFields() - { - $fields = null; - - // Get the URI. - $uri = JUri::getInstance(JRoute::_($this->query->toUri())); - $uri->delVar('q'); - $uri->delVar('o'); - $uri->delVar('t'); - $uri->delVar('d1'); - $uri->delVar('d2'); - $uri->delVar('w1'); - $uri->delVar('w2'); - $elements = $uri->getQuery(true); - - // Create hidden input elements for each part of the URI. - foreach ($elements as $n => $v) - { - if (is_scalar($v)) - { - $fields .= ''; - } - } - - return $fields; - } - - /** - * Method to get the layout file for a search result object. - * - * @param string $layout The layout file to check. [optional] - * - * @return string The layout file to use. - * - * @since 2.5 - */ - protected function getLayoutFile($layout = null) - { - // Create and sanitize the file name. - $file = $this->_layout . '_' . preg_replace('/[^A-Z0-9_\.-]/i', '', $layout); - - // Check if the file exists. - jimport('joomla.filesystem.path'); - $filetofind = $this->_createFileName('template', array('name' => $file)); - $exists = JPath::find($this->_path['template'], $filetofind); - - return ($exists ? $layout : 'result'); - } - - /** - * Prepares the document - * - * @param FinderIndexerQuery $query The search query - * - * @return void - * - * @since 2.5 - */ - protected function prepareDocument($query) - { - $app = JFactory::getApplication(); - $menus = $app->getMenu(); - $title = null; - - // Because the application sets a default page title, - // we need to get it from the menu item itself - $menu = $menus->getActive(); - - if ($menu) - { - $this->params->def('page_heading', $this->params->get('page_title', $menu->title)); - } - else - { - $this->params->def('page_heading', JText::_('COM_FINDER_DEFAULT_PAGE_TITLE')); - } - - $title = $this->params->get('page_title', ''); - - if (empty($title)) - { - $title = $app->get('sitename'); - } - elseif ($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 ($layout = $this->params->get('article_layout')) - { - $this->setLayout($layout); - } - - // Configure the document meta-description. - if (!empty($this->explained)) - { - $explained = $this->escape(html_entity_decode(strip_tags($this->explained), ENT_QUOTES, 'UTF-8')); - $this->document->setDescription($explained); - } - - // Configure the document meta-keywords. - if (!empty($query->highlight)) - { - $this->document->setMetadata('keywords', implode(', ', $query->highlight)); - } - - if ($this->params->get('robots')) - { - $this->document->setMetadata('robots', $this->params->get('robots')); - } - - // Add feed link to the document head. - if ($this->params->get('show_feed_link', 1) == 1) - { - // Add the RSS link. - $props = array('type' => 'application/rss+xml', 'title' => 'RSS 2.0'); - $route = JRoute::_($this->query->toUri() . '&format=feed&type=rss'); - $this->document->addHeadLink($route, 'alternate', 'rel', $props); - - // Add the ATOM link. - $props = array('type' => 'application/atom+xml', 'title' => 'Atom 1.0'); - $route = JRoute::_($this->query->toUri() . '&format=feed&type=atom'); - $this->document->addHeadLink($route, 'alternate', 'rel', $props); - } - } -} diff --git a/components/com_finder/views/search/view.opensearch.php b/components/com_finder/views/search/view.opensearch.php deleted file mode 100644 index ebadd2b5cf834..0000000000000 --- a/components/com_finder/views/search/view.opensearch.php +++ /dev/null @@ -1,53 +0,0 @@ -setShortName($params->get('opensearch_name', $app->get('sitename'))); - $doc->setDescription($params->get('opensearch_description', $app->get('MetaDesc'))); - - // Add the URL for the search - $searchUri = JUri::base() . 'index.php?option=com_finder&q={searchTerms}'; - - // Find the menu item for the search - $menu = $app->getMenu(); - $items = $menu->getItems('link', 'index.php?option=com_finder&view=search'); - - if (isset($items[0])) - { - $searchUri .= '&Itemid=' . $items[0]->id; - } - - $htmlSearch = new JOpenSearchUrl; - $htmlSearch->template = JRoute::_($searchUri); - $doc->addUrl($htmlSearch); - } -} diff --git a/components/com_search/controller.php b/components/com_search/controller.php index 313ffadbe239a..9117dd0e9fbe9 100644 --- a/components/com_search/controller.php +++ b/components/com_search/controller.php @@ -9,6 +9,8 @@ defined('_JEXEC') or die; +JLoader::register('SearchHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_search/helpers/lang.php'); + /** * Search Component Controller * @@ -26,12 +28,30 @@ class SearchController extends JControllerLegacy * * @since 1.5 */ - public function display($cachable = false, $urlparams = false) + public function display($cachable = false, $urlparams = array()) { - // Force it to be the search view - $this->input->set('view', 'search'); + $input = JFactory::getApplication()->input; + $cachable = true; + + // Load plugin language files. + SearchHelperLanguage::loadPluginLanguage(); + + // Set the default view name and format from the Request. + $viewName = $input->get('view', 'search', 'word'); + $input->set('view', $viewName); + + // Don't cache view for search queries + if ($input->get('q', null, 'string') || $input->get('f', null, 'int') || $input->get('t', null, 'array')) + { + $cachable = false; + } + + $safeurlparams = array( + 'f' => 'INT', + 'lang' => 'CMD' + ); - return parent::display($cachable, $urlparams); + return parent::display($cachable, $safeurlparams); } /** diff --git a/components/com_finder/controllers/suggestions.json.php b/components/com_search/controllers/suggestions.json.php similarity index 100% rename from components/com_finder/controllers/suggestions.json.php rename to components/com_search/controllers/suggestions.json.php diff --git a/components/com_finder/helpers/html/filter.php b/components/com_search/helpers/html/filter.php similarity index 100% rename from components/com_finder/helpers/html/filter.php rename to components/com_search/helpers/html/filter.php diff --git a/components/com_finder/helpers/html/query.php b/components/com_search/helpers/html/query.php similarity index 100% rename from components/com_finder/helpers/html/query.php rename to components/com_search/helpers/html/query.php diff --git a/components/com_finder/helpers/route.php b/components/com_search/helpers/route.php similarity index 100% rename from components/com_finder/helpers/route.php rename to components/com_search/helpers/route.php diff --git a/components/com_finder/models/search.php b/components/com_search/models/search_old.php similarity index 62% rename from components/com_finder/models/search.php rename to components/com_search/models/search_old.php index 4d1ad66d611d6..dab281fb09cf7 100644 --- a/components/com_finder/models/search.php +++ b/components/com_search/models/search_old.php @@ -9,7 +9,6 @@ defined('_JEXEC') or die; -use Joomla\String\StringHelper; use Joomla\Utilities\ArrayHelper; // Register dependent classes. @@ -365,7 +364,7 @@ protected function getResultsTotal() $start = 0; $items = array(); $sorted = array(); - $maps = array(); + $allIDs = array(); $excluded = $this->getExcludedLinkIds(); /* @@ -376,205 +375,164 @@ protected function getResultsTotal() */ foreach ($this->includedTerms as $token => $ids) { - // 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] = array_merge($maps[$suffix], $ids); + $allIDs = array_merge($allIDs, $ids); } - /* - * When the query contains search terms we need to find and process the - * result total iteratively using a do-while loop. - */ - do - { - // Create a container for the fetched results. - $results = array(); - $more = false; - - /* - * Iterate through the mapping groups and load the total from each - * mapping table. - */ - foreach ($maps as $suffix => $ids) - { - // Create a storage key for this set. - $setId = $this->getStoreId('getResultsTotal:' . serialize(array_values($ids)) . ':' . $start . ':' . $limit); + // Create a container for the fetched results. + $results = array(); + $more = false; - // Use the cached data if possible. - if ($this->retrieve($setId)) - { - $temp = $this->retrieve($setId); - } - // Load the data from the database. - else - { - // Adjust the query to join on the appropriate mapping table. - $query = clone($base); - $query->join('INNER', '#__finder_links_terms' . $suffix . ' AS m ON m.link_id = l.link_id') - ->where('m.term_id IN (' . implode(',', $ids) . ')'); - - // Load the results from the database. - $this->_db->setQuery($query, $start, $limit); - $temp = $this->_db->loadObjectList(); + // Create a storage key for this set. + $setId = $this->getStoreId('getResultsTotal:' . serialize(array_values($allIDs)) . ':' . $start . ':' . $limit); - // Set the more flag to true if any of the sets equal the limit. - $more = (count($temp) === $limit) ? true : false; - - // We loaded the data unkeyed but we need it to be keyed for later. - $junk = $temp; - $temp = array(); - - // Convert to an associative array. - for ($i = 0, $c = count($junk); $i < $c; $i++) - { - $temp[$junk[$i]->link_id] = $junk[$i]; - } + // Use the cached data if possible. + if ($this->retrieve($setId)) + { + $results = $this->retrieve($setId); + } + // Load the data from the database. + else + { + // Adjust the query to join on the appropriate mapping table. + $query = clone($base); + $query->join('INNER', '#__finder_links_terms AS m ON m.link_id = l.link_id') + ->where('m.term_id IN (' . implode(',', $allIDs) . ')'); - // Store this set in cache. - $this->store($setId, $temp); - } + // Load the results from the database. + $this->_db->setQuery($query, $start, $limit); + $temp = $this->_db->loadObjectList(); - // Merge the results. - $results = array_merge($results, $temp); - } + // We loaded the data unkeyed but we need it to be keyed for later. + $junk = $temp; + $temp = array(); - // Check if there are any excluded terms to deal with. - if (count($excluded)) + // Convert to an associative array. + for ($i = 0, $c = count($junk); $i < $c; $i++) { - // Remove any results that match excluded terms. - for ($i = 0, $c = count($results); $i < $c; $i++) - { - if (in_array($results[$i]->link_id, $excluded)) - { - unset($results[$i]); - } - } - - // Reset the array keys. - $results = array_values($results); + $temp[$junk[$i]->link_id] = $junk[$i]; } - // Iterate through the set to extract the unique items. + // Store this set in cache. + $this->store($setId, $temp); + $results = $temp; + } + + // Check if there are any excluded terms to deal with. + if (count($excluded)) + { + // Remove any results that match excluded terms. for ($i = 0, $c = count($results); $i < $c; $i++) { - if (!isset($sorted[$results[$i]->link_id])) + if (in_array($results[$i]->link_id, $excluded)) { - $sorted[$results[$i]->link_id] = $results[$i]->ordering; + unset($results[$i]); } } - /* - * If the query contains just optional search terms and we have - * enough items for the page, we can stop here. - */ - if (empty($this->requiredTerms)) + // Reset the array keys. + $results = array_values($results); + } + + // Iterate through the set to extract the unique items. + for ($i = 0, $c = count($results); $i < $c; $i++) + { + if (!isset($sorted[$results[$i]->link_id])) { - // If we need more items and they're available, make another pass. - if ($more && count($sorted) < $limit) - { - // Increment the batch starting point and continue. - $start += $limit; - continue; - } + $sorted[$results[$i]->link_id] = $results[$i]->ordering; + } + } - // Push the total into cache. - $this->store($store, min(count($sorted), $limit)); + $items = $results; - // Return the total. - return $this->retrieve($store); + /* + * If the query contains just optional search terms and we have + * enough items for the page, we can stop here. + */ + if (empty($this->requiredTerms)) + { + // If we need more items and they're available, make another pass. + if ($more && count($sorted) < $limit) + { + // Increment the batch starting point and continue. + $start += $limit; } - /* - * The query contains required search terms so we have to iterate - * over the items and remove any items that do not match all of the - * required search terms. This is one of the most expensive steps - * because a required token could theoretically eliminate all of - * current terms which means we would have to loop through all of - * the possibilities. - */ - foreach ($this->requiredTerms as $token => $required) - { - // Create a storage key for this set. - $setId = $this->getStoreId('getResultsTotal:required:' . serialize(array_values($required)) . ':' . $start . ':' . $limit); + // Push the total into cache. + $this->store($store, min(count($sorted), $limit)); - // Use the cached data if possible. - if ($this->retrieve($setId)) - { - $reqTemp = $this->retrieve($setId); - } - // Check if the token was matched. - elseif (empty($required)) - { - return null; - } - // Load the data from the database. - else - { - // Setup containers in case we have to make multiple passes. - $reqStart = 0; - $reqTemp = array(); + // Return the total. + return $this->retrieve($store); + } - do - { - // Get the map table suffix. - $suffix = StringHelper::substr(md5(StringHelper::substr($token, 0, 1)), 0, 1); + /* + * The query contains required search terms so we have to iterate + * over the items and remove any items that do not match all of the + * required search terms. This is one of the most expensive steps + * because a required token could theoretically eliminate all of + * current terms which means we would have to loop through all of + * the possibilities. + */ + foreach ($this->requiredTerms as $token => $required) + { + // Create a storage key for this set. + $setId = $this->getStoreId('getResultsTotal:required:' . serialize(array_values($required)) . ':' . $start . ':' . $limit); - // Adjust the query to join on the appropriate mapping table. - $query = clone($base); - $query->join('INNER', '#__finder_links_terms' . $suffix . ' AS m ON m.link_id = l.link_id') - ->where('m.term_id IN (' . implode(',', $required) . ')'); + // Use the cached data if possible. + if ($this->retrieve($setId)) + { + $reqTemp = $this->retrieve($setId); + } + // Check if the token was matched. + elseif (empty($required)) + { + return null; + } + // Load the data from the database. + else + { + // Setup containers in case we have to make multiple passes. + $reqStart = 0; + $reqTemp = array(); - // Load the results from the database. - $this->_db->setQuery($query, $reqStart, $limit); - $temp = $this->_db->loadObjectList('link_id'); + do + { + // Adjust the query to join on the appropriate mapping table. + $query = clone($base); + $query->join('INNER', '#__finder_links_terms AS m ON m.link_id = l.link_id') + ->where('m.term_id IN (' . implode(',', $required) . ')'); - // Set the required token more flag to true if the set equal the limit. - $reqMore = (count($temp) === $limit) ? true : false; + // Load the results from the database. + $this->_db->setQuery($query, $reqStart, $limit); + $temp = $this->_db->loadObjectList('link_id'); - // Merge the matching set for this token. - $reqTemp = $reqTemp + $temp; + // Set the required token more flag to true if the set equal the limit. + $reqMore = (count($temp) === $limit) ? true : false; - // Increment the term offset. - $reqStart += $limit; - } - while ($reqMore == true); + // Merge the matching set for this token. + $reqTemp = $reqTemp + $temp; - // Store this set in cache. - $this->store($setId, $reqTemp); + // Increment the term offset. + $reqStart += $limit; } + while ($reqMore == true); - // Remove any items that do not match the required term. - $sorted = array_intersect_key($sorted, $reqTemp); + // Store this set in cache. + $this->store($setId, $reqTemp); } - // If we need more items and they're available, make another pass. - if ($more && count($sorted) < $limit) - { - // Increment the batch starting point. - $start += $limit; - - // Merge the found items. - $items = $items + $sorted; + // Remove any items that do not match the required term. + $sorted = array_intersect_key($sorted, $reqTemp); + } - continue; - } - // Otherwise, end the loop. - { - // Merge the found items. - $items = $items + $sorted; + // If we need more items and they're available, make another pass. + if ($more && count($sorted) < $limit) + { + // Increment the batch starting point. + $start += $limit; - $more = false; - } - // End do-while loop. + // Merge the found items. + $items = $items + $sorted; } - while ($more === true); // Set the total. $total = count($items); @@ -642,261 +600,194 @@ protected function getResultsData() $start = 0; $limit = (int) $this->getState('match.limit'); $items = array(); + $results = array(); $sorted = array(); - $maps = array(); + $allIDs = array(); $excluded = $this->getExcludedLinkIds(); - /* - * Iterate through the included 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->includedTerms as $token => $ids) { - // Get the mapping table suffix. - $suffix = StringHelper::substr(md5(StringHelper::substr($token, 0, 1)), 0, 1); + $allIDs = array_merge($allIDs, $ids); + } - // Initialize the mapping group. - if (!array_key_exists($suffix, $maps)) - { - $maps[$suffix] = array(); - } + // Create a storage key for this set. + $setId = $this->getStoreId('getResultsData:' . serialize(array_values($allIDs)) . ':' . $start . ':' . $limit); - // Add the terms to the mapping group. - $maps[$suffix] = array_merge($maps[$suffix], $ids); + // Use the cached data if possible. + if ($this->retrieve($setId)) + { + $results = $this->retrieve($setId); } - - /* - * When the query contains search terms we need to find and process the - * results iteratively using a do-while loop. - */ - do + // Load the data from the database. + else { - // Create a container for the fetched results. - $results = array(); - $more = false; - - /* - * Iterate through the mapping groups and load the results from each - * mapping table. - */ - foreach ($maps as $suffix => $ids) - { - // Create a storage key for this set. - $setId = $this->getStoreId('getResultsData:' . serialize(array_values($ids)) . ':' . $start . ':' . $limit); - - // Use the cached data if possible. - if ($this->retrieve($setId)) - { - $temp = $this->retrieve($setId); - } - // Load the data from the database. - else - { - // Adjust the query to join on the appropriate mapping table. - $query = clone($base); - $query->join('INNER', $this->_db->quoteName('#__finder_links_terms' . $suffix) . ' AS m ON m.link_id = l.link_id') - ->where('m.term_id IN (' . implode(',', $ids) . ')'); - - // Load the results from the database. - $this->_db->setQuery($query, $start, $limit); - $temp = $this->_db->loadObjectList('link_id'); - - // Store this set in cache. - $this->store($setId, $temp); + // Adjust the query to join on the appropriate mapping table. + $query = clone($base); + $query->join('INNER', $this->_db->quoteName('#__finder_links_terms') . ' AS m ON m.link_id = l.link_id') + ->where('m.term_id IN (' . implode(',', $allIDs) . ')'); - // The data is keyed by link_id to ease caching, we don't need it till later. - $temp = array_values($temp); - } + // Load the results from the database. + $this->_db->setQuery($query, $start, $limit); + $results = $this->_db->loadObjectList('link_id'); - // Set the more flag to true if any of the sets equal the limit. - $more = (count($temp) === $limit) ? true : false; + // Store this set in cache. + $this->store($setId, $results); - // Merge the results. - $results = array_merge($results, $temp); - } + // The data is keyed by link_id to ease caching, we don't need it till later. + $results = array_values($results); + } - // Check if there are any excluded terms to deal with. - if (count($excluded)) + // Check if there are any excluded terms to deal with. + if (count($excluded)) + { + // Remove any results that match excluded terms. + for ($i = 0, $c = count($results); $i < $c; $i++) { - // Remove any results that match excluded terms. - for ($i = 0, $c = count($results); $i < $c; $i++) + if (in_array($results[$i]->link_id, $excluded)) { - if (in_array($results[$i]->link_id, $excluded)) - { - unset($results[$i]); - } + unset($results[$i]); } - - // Reset the array keys. - $results = array_values($results); } - /* - * If we are ordering by relevance we have to add up the relevance - * scores that are contained in the ordering field. - */ - if ($ordering === 'm.weight') + // Reset the array keys. + $results = array_values($results); + } + + /* + * If we are ordering by relevance we have to add up the relevance + * scores that are contained in the ordering field. + */ + if ($ordering === 'm.weight') + { + // Iterate through the set to extract the unique items. + for ($i = 0, $c = count($results); $i < $c; $i++) { - // Iterate through the set to extract the unique items. - for ($i = 0, $c = count($results); $i < $c; $i++) + // Add the total weights for all included search terms. + if (isset($sorted[$results[$i]->link_id])) { - // Add the total weights for all included search terms. - if (isset($sorted[$results[$i]->link_id])) - { - $sorted[$results[$i]->link_id] += (float) $results[$i]->ordering; - } - else - { - $sorted[$results[$i]->link_id] = (float) $results[$i]->ordering; - } + $sorted[$results[$i]->link_id] += (float) $results[$i]->ordering; } - } - /* - * If we are ordering by start date we have to add convert the - * dates to unix timestamps. - */ - elseif ($ordering === 'l.start_date') - { - // Iterate through the set to extract the unique items. - for ($i = 0, $c = count($results); $i < $c; $i++) + else { - if (!isset($sorted[$results[$i]->link_id])) - { - $sorted[$results[$i]->link_id] = strtotime($results[$i]->ordering); - } + $sorted[$results[$i]->link_id] = (float) $results[$i]->ordering; } } - /* - * If we are not ordering by relevance or date, we just have to add - * the unique items to the set. - */ - else + } + /* + * If we are ordering by start date we have to add convert the + * dates to unix timestamps. + */ + elseif ($ordering === 'l.start_date') + { + // Iterate through the set to extract the unique items. + for ($i = 0, $c = count($results); $i < $c; $i++) { - // Iterate through the set to extract the unique items. - for ($i = 0, $c = count($results); $i < $c; $i++) + if (!isset($sorted[$results[$i]->link_id])) { - if (!isset($sorted[$results[$i]->link_id])) - { - $sorted[$results[$i]->link_id] = $results[$i]->ordering; - } + $sorted[$results[$i]->link_id] = strtotime($results[$i]->ordering); } } - - // Sort the results. - natcasesort($items); - if ($direction === 'DESC') - { - $items = array_reverse($items, true); - } - - /* - * If the query contains just optional search terms and we have - * enough items for the page, we can stop here. - */ - if (empty($this->requiredTerms)) + } + /* + * If we are not ordering by relevance or date, we just have to add + * the unique items to the set. + */ + else + { + // Iterate through the set to extract the unique items. + for ($i = 0, $c = count($results); $i < $c; $i++) { - // If we need more items and they're available, make another pass. - if ($more && count($sorted) < ($this->getState('list.start') + $this->getState('list.limit'))) + if (!isset($sorted[$results[$i]->link_id])) { - // Increment the batch starting point and continue. - $start += $limit; - continue; + $sorted[$results[$i]->link_id] = $results[$i]->ordering; } - - // Push the results into cache. - $this->store($store, $sorted); - - // Return the requested set. - return array_slice($this->retrieve($store), (int) $this->getState('list.start'), (int) $this->getState('list.limit'), true); } + } - /* - * The query contains required search terms so we have to iterate - * over the items and remove any items that do not match all of the - * required search terms. This is one of the most expensive steps - * because a required token could theoretically eliminate all of - * current terms which means we would have to loop through all of - * the possibilities. - */ - foreach ($this->requiredTerms as $token => $required) - { - // Create a storage key for this set. - $setId = $this->getStoreId('getResultsData:required:' . serialize(array_values($required)) . ':' . $start . ':' . $limit); + $items = $sorted; - // Use the cached data if possible. - if ($this->retrieve($setId)) - { - $reqTemp = $this->retrieve($setId); - } - // Check if the token was matched. - elseif (empty($required)) - { - return null; - } - // Load the data from the database. - else - { - // Setup containers in case we have to make multiple passes. - $reqStart = 0; - $reqTemp = array(); + // Sort the results. + natcasesort($items); + if ($direction === 'DESC') + { + $items = array_reverse($items, true); + } - do - { - // Get the map table suffix. - $suffix = StringHelper::substr(md5(StringHelper::substr($token, 0, 1)), 0, 1); + /* + * If the query contains just optional search terms and we have + * enough items for the page, we can stop here. + */ + if (empty($this->requiredTerms)) + { + // Push the results into cache. + $this->store($store, $sorted); - // Adjust the query to join on the appropriate mapping table. - $query = clone($base); - $query->join('INNER', $this->_db->quoteName('#__finder_links_terms' . $suffix) . ' AS m ON m.link_id = l.link_id') - ->where('m.term_id IN (' . implode(',', $required) . ')'); + // Return the requested set. + return array_slice($this->retrieve($store), (int) $this->getState('list.start'), (int) $this->getState('list.limit'), true); + } - // Load the results from the database. - $this->_db->setQuery($query, $reqStart, $limit); - $temp = $this->_db->loadObjectList('link_id'); + /* + * The query contains required search terms so we have to iterate + * over the items and remove any items that do not match all of the + * required search terms. This is one of the most expensive steps + * because a required token could theoretically eliminate all of + * current terms which means we would have to loop through all of + * the possibilities. + */ + foreach ($this->requiredTerms as $token => $required) + { + // Create a storage key for this set. + $setId = $this->getStoreId('getResultsData:required:' . serialize(array_values($required)) . ':' . $start . ':' . $limit); - // Set the required token more flag to true if the set equal the limit. - $reqMore = (count($temp) === $limit) ? true : false; + // Use the cached data if possible. + if ($this->retrieve($setId)) + { + $reqTemp = $this->retrieve($setId); + } + // Check if the token was matched. + elseif (empty($required)) + { + return null; + } + // Load the data from the database. + else + { + // Setup containers in case we have to make multiple passes. + $reqStart = 0; + $reqTemp = array(); - // Merge the matching set for this token. - $reqTemp = $reqTemp + $temp; + // Adjust the query to join on the appropriate mapping table. + $query = clone($base); + $query->join('INNER', $this->_db->quoteName('#__finder_links_terms') . ' AS m ON m.link_id = l.link_id') + ->where('m.term_id IN (' . implode(',', $required) . ')'); - // Increment the term offset. - $reqStart += $limit; - } - while ($reqMore == true); + // Load the results from the database. + $this->_db->setQuery($query, $reqStart, $limit); + $temp = $this->_db->loadObjectList('link_id'); - // Store this set in cache. - $this->store($setId, $reqTemp); - } + // Merge the matching set for this token. + $reqTemp = $reqTemp + $temp; - // Remove any items that do not match the required term. - $sorted = array_intersect_key($sorted, $reqTemp); - } + // Increment the term offset. + $reqStart += $limit; - // If we need more items and they're available, make another pass. - if ($more && count($sorted) < ($this->getState('list.start') + $this->getState('list.limit'))) - { - // Increment the batch starting point. - $start += $limit; + // Store this set in cache. + $this->store($setId, $reqTemp); + } - // Merge the found items. - $items = array_merge($items, $sorted); + // Remove any items that do not match the required term. + $sorted = array_intersect_key($sorted, $reqTemp); + } - continue; - } - // Otherwise, end the loop. - else - { - // Set the found items. - $items = $sorted; + // If we need more items and they're available, make another pass. + if (count($sorted) < ($this->getState('list.start') + $this->getState('list.limit'))) + { + // Increment the batch starting point. + $start += $limit; - $more = false; - } - // End do-while loop. + // Merge the found items. + $items = array_merge($items, $sorted); } - while ($more === true); // Push the results into cache. $this->store($store, $items); @@ -932,7 +823,7 @@ protected function getExcludedLinkIds() // Initialize containers. $links = array(); - $maps = array(); + $allIDs = array(); /* * Iterate through the excluded search terms and group them by mapping @@ -942,17 +833,7 @@ protected function getExcludedLinkIds() */ 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; + $allIDs[] = (int) $id; } /* @@ -962,23 +843,20 @@ protected function getExcludedLinkIds() // 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')); + // Create the query to get the links ids. + $query->clear() + ->select('link_id') + ->from($db->quoteName('#__finder_links_terms')) + ->where($db->quoteName('term_id') . ' IN (' . implode(',', $allIDs) . ')') + ->group($db->quoteName('link_id')); - // Load the link ids from the database. - $db->setQuery($query); - $temp = $db->loadColumn(); + // Load the link ids from the database. + $db->setQuery($query); + $temp = $db->loadColumn(); - // Merge the link ids. - $links = array_merge($links, $temp); - } + // Merge the link ids. + $links = array_merge($links, $temp); // Sanitize the link ids. $links = array_unique($links); @@ -1126,7 +1004,7 @@ protected function populateState($ordering = null, $direction = null) * Also, we allow this parameter to be passed in either case (lower/upper). */ $order = $input->getWord('filter_order', $params->get('sort_order', 'relevance')); - $order = StringHelper::strtolower($order); + $order = JString::strtolower($order); switch ($order) { case 'date': @@ -1157,7 +1035,7 @@ protected function populateState($ordering = null, $direction = null) * Also, we allow this parameter to be passed in either case (lower/upper). */ $dirn = $input->getWord('filter_order_Dir', $params->get('sort_direction', 'desc')); - $dirn = StringHelper::strtolower($dirn); + $dirn = JString::strtolower($dirn); switch ($dirn) { case 'asc': diff --git a/components/com_finder/models/suggestions.php b/components/com_search/models/suggestions.php similarity index 100% rename from components/com_finder/models/suggestions.php rename to components/com_search/models/suggestions.php diff --git a/components/com_search/router.php b/components/com_search/router.php index 987d37a6012d6..54fba03913b1f 100644 --- a/components/com_search/router.php +++ b/components/com_search/router.php @@ -114,3 +114,112 @@ function searchParseRoute($segments) return $router->parse($segments); } + +class FinderRouter extends JComponentRouterBase +{ + /** + * Build the route for the com_finder component + * + * @param array &$query An array of URL arguments + * + * @return array The URL arguments to use to assemble the subsequent URL. + * + * @since 3.3 + */ + public function build(&$query) + { + $segments = array(); + + /* + * First, handle menu item routes first. When the menu system builds a + * route, it only provides the option and the menu item id. We don't have + * to do anything to these routes. + */ + if (count($query) === 2 && isset($query['Itemid']) && isset($query['option'])) + { + return $segments; + } + + /* + * Next, handle a route with a supplied menu item id. All system generated + * routes should fall into this group. We can assume that the menu item id + * is the best possible match for the query but we need to go through and + * see which variables we can eliminate from the route query string because + * they are present in the menu item route already. + */ + if (!empty($query['Itemid'])) + { + // Get the menu item. + $item = $this->menu->getItem($query['Itemid']); + + // Check if the view matches. + if ($item && @$item->query['view'] === @$query['view']) + { + unset($query['view']); + } + + // Check if the search query filter matches. + if ($item && @$item->query['f'] === @$query['f']) + { + unset($query['f']); + } + + // Check if the search query string matches. + if ($item && @$item->query['q'] === @$query['q']) + { + unset($query['q']); + } + + return $segments; + } + + /* + * Lastly, handle a route with no menu item id. Fortunately, we only need + * to deal with the view as the other route variables are supposed to stay + * in the query string. + */ + if (isset($query['view'])) + { + // Add the view to the segments. + $segments[] = $query['view']; + unset($query['view']); + } + + $total = count($segments); + + for ($i = 0; $i < $total; $i++) + { + $segments[$i] = str_replace(':', '-', $segments[$i]); + } + + return $segments; + } + + /** + * Parse the segments of a URL. + * + * @param array &$segments The segments of the URL to parse. + * + * @return array The URL attributes to be used by the application. + * + * @since 3.3 + */ + public function parse(&$segments) + { + $total = count($segments); + $vars = array(); + + for ($i = 0; $i < $total; $i++) + { + $segments[$i] = preg_replace('/-/', ':', $segments[$i], 1); + } + + // Check if the view segment is set and it equals search or advanced. + if (@$segments[0] === 'search' || @$segments[0] === 'advanced') + { + $vars['view'] = $segments[0]; + } + + return $vars; + } +} \ No newline at end of file diff --git a/components/com_finder/views/search/tmpl/default.php b/components/com_search/views/search/tmpl/finder.php similarity index 100% rename from components/com_finder/views/search/tmpl/default.php rename to components/com_search/views/search/tmpl/finder.php diff --git a/components/com_finder/views/search/tmpl/default.xml b/components/com_search/views/search/tmpl/finder.xml similarity index 100% rename from components/com_finder/views/search/tmpl/default.xml rename to components/com_search/views/search/tmpl/finder.xml diff --git a/components/com_finder/views/search/tmpl/default_form.php b/components/com_search/views/search/tmpl/finder_form.php similarity index 100% rename from components/com_finder/views/search/tmpl/default_form.php rename to components/com_search/views/search/tmpl/finder_form.php diff --git a/components/com_finder/views/search/tmpl/default_result.php b/components/com_search/views/search/tmpl/finder_result.php similarity index 100% rename from components/com_finder/views/search/tmpl/default_result.php rename to components/com_search/views/search/tmpl/finder_result.php diff --git a/components/com_finder/views/search/tmpl/default_results.php b/components/com_search/views/search/tmpl/finder_results.php similarity index 93% rename from components/com_finder/views/search/tmpl/default_results.php rename to components/com_search/views/search/tmpl/finder_results.php index b18122878a4d2..c1d3fe8414e0b 100644 --- a/components/com_finder/views/search/tmpl/default_results.php +++ b/components/com_search/views/search/tmpl/finder_results.php @@ -70,9 +70,9 @@
pagination->get('limitstart') + 1; - $total = (int) $this->pagination->get('total'); - $limit = (int) $this->pagination->get('limit') * $this->pagination->get('pages.current'); + $start = (int) $this->pagination->limitstart + 1; + $total = (int) $this->pagination->total; + $limit = (int) $this->pagination->limit * $this->pagination->pages . current; $limit = (int) ($limit > $total ? $total : $limit); echo JText::sprintf('COM_FINDER_SEARCH_RESULTS_OF', $start, $limit, $total); diff --git a/components/com_finder/views/search/view.feed.php b/components/com_search/views/search/view.feed.php similarity index 100% rename from components/com_finder/views/search/view.feed.php rename to components/com_search/views/search/view.feed.php diff --git a/components/com_search/views/search/view.html.php b/components/com_search/views/search/view.html.php index 1859fa8d636c1..1f90b8c6f26c1 100644 --- a/components/com_search/views/search/view.html.php +++ b/components/com_search/views/search/view.html.php @@ -295,7 +295,7 @@ public function display($tpl = null) { $this->setLayout($active->query['layout']); } - +var_dump($results); // Escape strings for HTML output $this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx')); $this->pagination = &$pagination; @@ -314,3 +314,259 @@ public function display($tpl = null) parent::display($tpl); } } + + + +/** + * @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; + +/** + * Search HTML view class for the Finder package. + * + * @since 2.5 + */ +class FinderViewSearch extends JViewLegacy +{ + protected $query; + + protected $params; + + protected $state; + + protected $user; + + /** + * Method to display the view. + * + * @param string $tpl A template file to load. [optional] + * + * @return mixed JError object on failure, void on success. + * + * @since 2.5 + */ + public function display($tpl = null) + { + $app = JFactory::getApplication(); + $params = $app->getParams(); + + // Get view data. + $state = $this->get('State'); + $query = $this->get('Query'); + JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderQuery') : null; + $results = $this->get('Results'); + JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderResults') : null; + $total = $this->get('Total'); + JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderTotal') : null; + $pagination = $this->get('Pagination'); + JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderPagination') : null; + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + JError::raiseError(500, implode("\n", $errors)); + return false; + } + + // Configure the pathway. + if (!empty($query->input)) + { + $app->getPathWay()->addItem($this->escape($query->input)); + } + + // Push out the view data. + $this->state = &$state; + $this->params = &$params; + $this->query = &$query; + $this->results = &$results; + $this->total = &$total; + $this->pagination = &$pagination; + + // Check for a double quote in the query string. + if (strpos($this->query->input, '"')) + { + // Get the application router. + $router =& $app::getRouter(); + + // Fix the q variable in the URL. + if ($router->getVar('q') !== $this->query->input) + { + $router->setVar('q', $this->query->input); + } + } + + // Log the search + JSearchHelper::logSearch($this->query->input, 'com_finder'); + + // Push out the query data. + JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html'); + $this->suggested = JHtml::_('query.suggested', $query); + $this->explained = JHtml::_('query.explained', $query); + + // Escape strings for HTML output + $this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx')); + + // Check for layout override only if this is not the active menu item + // If it is the active menu item, then the view and category id will match + $active = $app->getMenu()->getActive(); + if (isset($active->query['layout'])) + { + // We need to set the layout in case this is an alternative menu item (with an alternative layout) + $this->setLayout($active->query['layout']); + } + + $this->prepareDocument($query); + + JDEBUG ? JProfiler::getInstance('Application')->mark('beforeFinderLayout') : null; + + parent::display($tpl); + + JDEBUG ? JProfiler::getInstance('Application')->mark('afterFinderLayout') : null; + } + + /** + * Method to get hidden input fields for a get form so that control variables + * are not lost upon form submission + * + * @return string A string of hidden input form fields + * + * @since 2.5 + */ + protected function getFields() + { + $fields = null; + + // Get the URI. + $uri = JUri::getInstance(JRoute::_($this->query->toUri())); + $uri->delVar('q'); + $uri->delVar('o'); + $uri->delVar('t'); + $uri->delVar('d1'); + $uri->delVar('d2'); + $uri->delVar('w1'); + $uri->delVar('w2'); + $elements = $uri->getQuery(true); + + // Create hidden input elements for each part of the URI. + foreach ($elements as $n => $v) + { + if (is_scalar($v)) + { + $fields .= ''; + } + } + + return $fields; + } + + /** + * Method to get the layout file for a search result object. + * + * @param string $layout The layout file to check. [optional] + * + * @return string The layout file to use. + * + * @since 2.5 + */ + protected function getLayoutFile($layout = null) + { + // Create and sanitize the file name. + $file = $this->_layout . '_' . preg_replace('/[^A-Z0-9_\.-]/i', '', $layout); + + // Check if the file exists. + jimport('joomla.filesystem.path'); + $filetofind = $this->_createFileName('template', array('name' => $file)); + $exists = JPath::find($this->_path['template'], $filetofind); + + return ($exists ? $layout : 'result'); + } + + /** + * Prepares the document + * + * @param FinderIndexerQuery $query The search query + * + * @return void + * + * @since 2.5 + */ + protected function prepareDocument($query) + { + $app = JFactory::getApplication(); + $menus = $app->getMenu(); + $title = null; + + // Because the application sets a default page title, + // we need to get it from the menu item itself + $menu = $menus->getActive(); + + if ($menu) + { + $this->params->def('page_heading', $this->params->get('page_title', $menu->title)); + } + else + { + $this->params->def('page_heading', JText::_('COM_FINDER_DEFAULT_PAGE_TITLE')); + } + + $title = $this->params->get('page_title', ''); + + if (empty($title)) + { + $title = $app->get('sitename'); + } + elseif ($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 ($layout = $this->params->get('article_layout')) + { + $this->setLayout($layout); + } + + // Configure the document meta-description. + if (!empty($this->explained)) + { + $explained = $this->escape(html_entity_decode(strip_tags($this->explained), ENT_QUOTES, 'UTF-8')); + $this->document->setDescription($explained); + } + + // Configure the document meta-keywords. + if (!empty($query->highlight)) + { + $this->document->setMetadata('keywords', implode(', ', $query->highlight)); + } + + if ($this->params->get('robots')) + { + $this->document->setMetadata('robots', $this->params->get('robots')); + } + + // Add feed link to the document head. + if ($this->params->get('show_feed_link', 1) == 1) + { + // Add the RSS link. + $props = array('type' => 'application/rss+xml', 'title' => 'RSS 2.0'); + $route = JRoute::_($this->query->toUri() . '&format=feed&type=rss'); + $this->document->addHeadLink($route, 'alternate', 'rel', $props); + + // Add the ATOM link. + $props = array('type' => 'application/atom+xml', 'title' => 'Atom 1.0'); + $route = JRoute::_($this->query->toUri() . '&format=feed&type=atom'); + $this->document->addHeadLink($route, 'alternate', 'rel', $props); + } + } +} diff --git a/installation/sql/mysql/joomla.sql b/installation/sql/mysql/joomla.sql index 40c34fb020a36..73351e67c9470 100644 --- a/installation/sql/mysql/joomla.sql +++ b/installation/sql/mysql/joomla.sql @@ -752,235 +752,10 @@ CREATE TABLE IF NOT EXISTS `#__finder_links` ( -- -------------------------------------------------------- -- --- Table structure for table `#__finder_links_terms0` +-- Table structure for table `#__finder_links_terms` -- -CREATE TABLE IF NOT EXISTS `#__finder_links_terms0` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_terms1` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms1` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_terms2` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms2` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_terms3` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms3` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_terms4` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms4` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_terms5` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms5` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_terms6` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms6` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_terms7` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms7` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_terms8` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms8` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_terms9` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_terms9` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_termsa` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_termsa` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_termsb` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_termsb` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_termsc` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_termsc` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_termsd` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_termsd` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_termse` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_termse` ( - `link_id` int(10) unsigned NOT NULL, - `term_id` int(10) unsigned NOT NULL, - `weight` float unsigned NOT NULL, - PRIMARY KEY (`link_id`,`term_id`), - KEY `idx_term_weight` (`term_id`,`weight`), - KEY `idx_link_term_weight` (`link_id`,`term_id`,`weight`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_general_ci; - --- -------------------------------------------------------- - --- --- Table structure for table `#__finder_links_termsf` --- - -CREATE TABLE IF NOT EXISTS `#__finder_links_termsf` ( +CREATE TABLE IF NOT EXISTS `#__finder_links_terms` ( `link_id` int(10) unsigned NOT NULL, `term_id` int(10) unsigned NOT NULL, `weight` float unsigned NOT NULL, diff --git a/installation/sql/postgresql/joomla.sql b/installation/sql/postgresql/joomla.sql index 0f97df2f99b6b..f4f1db162c43a 100644 --- a/installation/sql/postgresql/joomla.sql +++ b/installation/sql/postgresql/joomla.sql @@ -752,196 +752,16 @@ CREATE INDEX "#__finder_links_idx_published_list" on "#__finder_links" ("publish CREATE INDEX "#__finder_links_idx_published_sale" on "#__finder_links" ("published", "state", "access", "publish_start_date", "publish_end_date", "sale_price"); -- --- Table: #__finder_links_terms0 +-- Table: #__finder_links_terms -- -CREATE TABLE "#__finder_links_terms0" ( +CREATE TABLE "#__finder_links_terms" ( "link_id" integer NOT NULL, "term_id" integer NOT NULL, "weight" numeric(8,2) NOT NULL, PRIMARY KEY ("link_id", "term_id") ); -CREATE INDEX "#__finder_links_terms0_idx_term_weight" on "#__finder_links_terms0" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms0_idx_link_term_weight" on "#__finder_links_terms0" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms1 --- -CREATE TABLE "#__finder_links_terms1" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms1_idx_term_weight" on "#__finder_links_terms1" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms1_idx_link_term_weight" on "#__finder_links_terms1" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms2 --- -CREATE TABLE "#__finder_links_terms2" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms2_idx_term_weight" on "#__finder_links_terms2" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms2_idx_link_term_weight" on "#__finder_links_terms2" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms3 --- -CREATE TABLE "#__finder_links_terms3" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms3_idx_term_weight" on "#__finder_links_terms3" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms3_idx_link_term_weight" on "#__finder_links_terms3" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms4 --- -CREATE TABLE "#__finder_links_terms4" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms4_idx_term_weight" on "#__finder_links_terms4" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms4_idx_link_term_weight" on "#__finder_links_terms4" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms5 --- -CREATE TABLE "#__finder_links_terms5" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms5_idx_term_weight" on "#__finder_links_terms5" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms5_idx_link_term_weight" on "#__finder_links_terms5" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms6 --- -CREATE TABLE "#__finder_links_terms6" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms6_idx_term_weight" on "#__finder_links_terms6" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms6_idx_link_term_weight" on "#__finder_links_terms6" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms7 --- -CREATE TABLE "#__finder_links_terms7" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms7_idx_term_weight" on "#__finder_links_terms7" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms7_idx_link_term_weight" on "#__finder_links_terms7" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms8 --- -CREATE TABLE "#__finder_links_terms8" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms8_idx_term_weight" on "#__finder_links_terms8" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms8_idx_link_term_weight" on "#__finder_links_terms8" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_terms9 --- -CREATE TABLE "#__finder_links_terms9" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_terms9_idx_term_weight" on "#__finder_links_terms9" ("term_id", "weight"); -CREATE INDEX "#__finder_links_terms9_idx_link_term_weight" on "#__finder_links_terms9" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_termsa --- -CREATE TABLE "#__finder_links_termsa" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_termsa_idx_term_weight" on "#__finder_links_termsa" ("term_id", "weight"); -CREATE INDEX "#__finder_links_termsa_idx_link_term_weight" on "#__finder_links_termsa" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_termsb --- -CREATE TABLE "#__finder_links_termsb" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_termsb_idx_term_weight" on "#__finder_links_termsb" ("term_id", "weight"); -CREATE INDEX "#__finder_links_termsb_idx_link_term_weight" on "#__finder_links_termsb" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_termsc --- -CREATE TABLE "#__finder_links_termsc" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_termsc_idx_term_weight" on "#__finder_links_termsc" ("term_id", "weight"); -CREATE INDEX "#__finder_links_termsc_idx_link_term_weight" on "#__finder_links_termsc" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_termsd --- -CREATE TABLE "#__finder_links_termsd" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_termsd_idx_term_weight" on "#__finder_links_termsd" ("term_id", "weight"); -CREATE INDEX "#__finder_links_termsd_idx_link_term_weight" on "#__finder_links_termsd" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_termse --- -CREATE TABLE "#__finder_links_termse" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_termse_idx_term_weight" on "#__finder_links_termse" ("term_id", "weight"); -CREATE INDEX "#__finder_links_termse_idx_link_term_weight" on "#__finder_links_termse" ("link_id", "term_id", "weight"); - --- --- Table: #__finder_links_termsf --- -CREATE TABLE "#__finder_links_termsf" ( - "link_id" integer NOT NULL, - "term_id" integer NOT NULL, - "weight" numeric(8,2) NOT NULL, - PRIMARY KEY ("link_id", "term_id") -); -CREATE INDEX "#__finder_links_termsf_idx_term_weight" on "#__finder_links_termsf" ("term_id", "weight"); -CREATE INDEX "#__finder_links_termsf_idx_link_term_weight" on "#__finder_links_termsf" ("link_id", "term_id", "weight"); +CREATE INDEX "#__finder_links_terms_idx_term_weight" on "#__finder_links_terms" ("term_id", "weight"); +CREATE INDEX "#__finder_links_terms_idx_link_term_weight" on "#__finder_links_terms" ("link_id", "term_id", "weight"); -- -- Table: #__finder_taxonomy diff --git a/language/en-GB/en-GB.search.php b/language/en-GB/en-GB.search.php new file mode 100644 index 0000000000000..94453f7a5705a --- /dev/null +++ b/language/en-GB/en-GB.search.php @@ -0,0 +1,415 @@ + 1) { + self::replace($word, 'e', ''); + + } else if (self::m(substr($word, 0, -1)) == 1) { + + if (!self::cvc(substr($word, 0, -1))) { + self::replace($word, 'e', ''); + } + } + } + + // Part b + if (self::m($word) > 1 AND self::doubleConsonant($word) AND substr($word, -1) == 'l') { + $word = substr($word, 0, -1); + } + + return $word; + } + + + /** + * Replaces the first string with the second, at the end of the string. If third + * arg is given, then the preceding string must match that m count at least. + * + * @param string $str String to check + * @param string $check Ending to check for + * @param string $repl Replacement string + * @param int $m Optional minimum number of m() to meet + * @return bool Whether the $check string was at the end + * of the $str string. True does not necessarily mean + * that it was replaced. + */ + private static function replace(&$str, $check, $repl, $m = null) + { + $len = 0 - strlen($check); + + if (substr($str, $len) == $check) { + $substr = substr($str, 0, $len); + if (is_null($m) OR self::m($substr) > $m) { + $str = $substr . $repl; + } + + return true; + } + + return false; + } + + + /** + * What, you mean it's not obvious from the name? + * + * m() measures the number of consonant sequences in $str. if c is + * a consonant sequence and v a vowel sequence, and <..> indicates arbitrary + * presence, + * + * gives 0 + * vc gives 1 + * vcvc gives 2 + * vcvcvc gives 3 + * + * @param string $str The string to return the m count for + * @return int The m count + */ + private static function m($str) + { + $c = self::$regex_consonant; + $v = self::$regex_vowel; + + $str = preg_replace("#^$c+#", '', $str); + $str = preg_replace("#$v+$#", '', $str); + + preg_match_all("#($v+$c+)#", $str, $matches); + + return count($matches[1]); + } + + + /** + * Returns true/false as to whether the given string contains two + * of the same consonant next to each other at the end of the string. + * + * @param string $str String to check + * @return bool Result + */ + private static function doubleConsonant($str) + { + $c = self::$regex_consonant; + + return preg_match("#$c{2}$#", $str, $matches) AND $matches[0]{0} == $matches[0]{1}; + } + + + /** + * Checks for ending CVC sequence where second C is not W, X or Y + * + * @param string $str String to check + * @return bool Result + */ + private static function cvc($str) + { + $c = self::$regex_consonant; + $v = self::$regex_vowel; + + return preg_match("#($c$v$c)$#", $str, $matches) + AND strlen($matches[1]) == 3 + AND $matches[1]{2} != 'w' + AND $matches[1]{2} != 'x' + AND $matches[1]{2} != 'y'; + } +} \ No newline at end of file diff --git a/media/com_finder/css/dates.css b/media/com_search/css/dates.css similarity index 100% rename from media/com_finder/css/dates.css rename to media/com_search/css/dates.css diff --git a/media/com_finder/css/finder.css b/media/com_search/css/finder.css similarity index 100% rename from media/com_finder/css/finder.css rename to media/com_search/css/finder.css diff --git a/media/com_finder/css/indexer.css b/media/com_search/css/indexer.css similarity index 100% rename from media/com_finder/css/indexer.css rename to media/com_search/css/indexer.css diff --git a/media/com_finder/js/autocompleter.js b/media/com_search/js/autocompleter.js similarity index 100% rename from media/com_finder/js/autocompleter.js rename to media/com_search/js/autocompleter.js diff --git a/media/com_finder/js/indexer.js b/media/com_search/js/indexer.js similarity index 74% rename from media/com_finder/js/indexer.js rename to media/com_search/js/indexer.js index ecceb07739159..e252ef8cbcfa6 100644 --- a/media/com_finder/js/indexer.js +++ b/media/com_search/js/indexer.js @@ -1,15 +1,15 @@ -var FinderIndexer = function(){ +var SearchIndexer = function(){ var totalItems= null; var batchSize= null; var offset= null; var progress= null; var optimized= false; - var path = 'index.php?option=com_finder&tmpl=component&format=json'; + var path = 'index.php?option=com_search&tmpl=component&format=json'; var initialize = function () { offset = 0; progress = 0; - path = path + '&' + jQuery('#finder-indexer-token').attr('name') + '=1'; + path = path + '&' + jQuery('#search-indexer-token').attr('name') + '=1'; getRequest('indexer.start'); }; @@ -47,15 +47,15 @@ var FinderIndexer = function(){ jQuery('#progress').remove(); try { if (json.error) { - jQuery('#finder-progress-header').text(json.header).addClass('finder-error'); - jQuery('#finder-progress-message').html(json.message).addClass('finder-error'); + jQuery('#search-progress-header').text(json.header).addClass('search-error'); + jQuery('#search-progress-message').html(json.message).addClass('search-error'); } } catch (ignore) { if (error === '') { error = Joomla.JText._('COM_FINDER_NO_ERROR_RETURNED'); } - jQuery('#finder-progress-header').text(Joomla.JText._('COM_FINDER_AN_ERROR_HAS_OCCURRED')).addClass('finder-error'); - jQuery('#finder-progress-message').html(error).addClass('finder-error'); + jQuery('#search-progress-header').text(Joomla.JText._('COM_FINDER_AN_ERROR_HAS_OCCURRED')).addClass('search-error'); + jQuery('#search-progress-message').html(error).addClass('search-error'); } } return true; @@ -70,14 +70,14 @@ var FinderIndexer = function(){ } var header = json ? json.header : Joomla.JText._('COM_FINDER_AN_ERROR_HAS_OCCURRED'); var message = json ? json.message : Joomla.JText._('COM_FINDER_MESSAGE_RETURNED') + '
' + json; - jQuery('#finder-progress-header').text(header).addClass('finder-error'); - jQuery('#finder-progress-message').html(message).addClass('finder-error'); + jQuery('#search-progress-header').text(header).addClass('search-error'); + jQuery('#search-progress-message').html(message).addClass('search-error'); }; var updateProgress = function (header, message) { progress = (offset / totalItems) * 100; - jQuery('#finder-progress-header').text(header); - jQuery('#finder-progress-message').html(message); + jQuery('#search-progress-header').text(header); + jQuery('#search-progress-message').html(message); if (progress < 100) { jQuery('#progress-bar').css('width', progress + '%').attr('aria-valuenow', progress); } @@ -95,7 +95,7 @@ var FinderIndexer = function(){ }; jQuery(function () { - Indexer = new FinderIndexer(); + Indexer = new SearchIndexer(); if (typeof window.parent.SqueezeBox == 'object') { jQuery(window.parent.SqueezeBox).on('close', function () { window.parent.location.reload(true); diff --git a/plugins/finder/categories/categories.php b/plugins/finder/categories/categories.php index a19ee808a6fd9..c695e092f49d0 100644 --- a/plugins/finder/categories/categories.php +++ b/plugins/finder/categories/categories.php @@ -1,7 +1,7 @@ id; } - elseif ($context == 'com_finder.index') + elseif ($context == 'com_search.index') { $id = $table->link_id; } @@ -231,9 +231,9 @@ public function onFinderChangeState($context, $pks, $value) } /** - * Method to index an item. The item must be a FinderIndexerResult object. + * Method to index an item. The item must be a SearchIndexerResult object. * - * @param FinderIndexerResult $item The item to index as an FinderIndexerResult object. + * @param SearchIndexerResult $item The item to index as an SearchIndexerResult object. * @param string $format The item format. Not used. * * @return void @@ -241,7 +241,7 @@ public function onFinderChangeState($context, $pks, $value) * @since 2.5 * @throws Exception on database error. */ - protected function index(FinderIndexerResult $item, $format = 'html') + protected function index(SearchIndexerResult $item, $format = 'html') { // Check if the extension is enabled. if (JComponentHelper::isEnabled($this->extension) == false) @@ -266,17 +266,17 @@ protected function index(FinderIndexerResult $item, $format = 'html') $item->metaauthor = $item->metadata->get('author'); // Handle the link to the metadata. - $item->addInstruction(FinderIndexer::META_CONTEXT, 'link'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'metakey'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'metadesc'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'metaauthor'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'author'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'link'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'metakey'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'metadesc'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'metaauthor'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'author'); // Deactivated Methods - // $item->addInstruction(FinderIndexer::META_CONTEXT, 'created_by_alias'); + // $item->addInstruction(SearchIndexer::META_CONTEXT, 'created_by_alias'); // Trigger the onContentPrepare event. - $item->summary = FinderIndexerHelper::prepareContent($item->summary, $item->params); + $item->summary = SearchIndexerHelper::prepareContent($item->summary, $item->params); // Build the necessary route and path information. $item->url = $this->getUrl($item->id, $item->extension, $this->layout); @@ -295,7 +295,7 @@ protected function index(FinderIndexerResult $item, $format = 'html') $item->route = ContentHelperRoute::getCategoryRoute($item->id, $item->language); } - $item->path = FinderIndexerHelper::getContentPath($item->route); + $item->path = SearchIndexerHelper::getContentPath($item->route); // Get the menu title if it exists. $title = $this->getItemMenuTitle($item->url); @@ -316,7 +316,7 @@ protected function index(FinderIndexerResult $item, $format = 'html') $item->addTaxonomy('Language', $item->language); // Get content extras. - FinderIndexerHelper::getContentExtras($item); + SearchIndexerHelper::getContentExtras($item); // Index the item. $this->indexer->index($item); diff --git a/plugins/finder/contacts/contacts.php b/plugins/finder/contacts/contacts.php index e11ab8e3fa4b1..68816d4d5ad73 100644 --- a/plugins/finder/contacts/contacts.php +++ b/plugins/finder/contacts/contacts.php @@ -1,7 +1,7 @@ id; } - elseif ($context == 'com_finder.index') + elseif ($context == 'com_search.index') { $id = $table->link_id; } @@ -238,9 +238,9 @@ public function onFinderChangeState($context, $pks, $value) } /** - * Method to index an item. The item must be a FinderIndexerResult object. + * Method to index an item. The item must be a SearchIndexerResult object. * - * @param FinderIndexerResult $item The item to index as an FinderIndexerResult object. + * @param SearchIndexerResult $item The item to index as an SearchIndexerResult object. * @param string $format The item format * * @return void @@ -248,7 +248,7 @@ public function onFinderChangeState($context, $pks, $value) * @since 2.5 * @throws Exception on database error. */ - protected function index(FinderIndexerResult $item, $format = 'html') + protected function index(SearchIndexerResult $item, $format = 'html') { // Check if the extension is enabled if (JComponentHelper::isEnabled($this->extension) == false) @@ -264,7 +264,7 @@ protected function index(FinderIndexerResult $item, $format = 'html') // Build the necessary route and path information. $item->url = $this->getUrl($item->id, $this->extension, $this->layout); $item->route = ContactHelperRoute::getContactRoute($item->slug, $item->catslug, $item->language); - $item->path = FinderIndexerHelper::getContentPath($item->route); + $item->path = SearchIndexerHelper::getContentPath($item->route); // Get the menu title if it exists. $title = $this->getItemMenuTitle($item->url); @@ -282,71 +282,71 @@ protected function index(FinderIndexerResult $item, $format = 'html') // Handle the contact position. if ($item->params->get('show_position', true)) { - $item->addInstruction(FinderIndexer::META_CONTEXT, 'position'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'position'); } // Handle the contact street address. if ($item->params->get('show_street_address', true)) { - $item->addInstruction(FinderIndexer::META_CONTEXT, 'address'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'address'); } // Handle the contact city. if ($item->params->get('show_suburb', true)) { - $item->addInstruction(FinderIndexer::META_CONTEXT, 'city'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'city'); } // Handle the contact region. if ($item->params->get('show_state', true)) { - $item->addInstruction(FinderIndexer::META_CONTEXT, 'region'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'region'); } // Handle the contact country. if ($item->params->get('show_country', true)) { - $item->addInstruction(FinderIndexer::META_CONTEXT, 'country'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'country'); } // Handle the contact zip code. if ($item->params->get('show_postcode', true)) { - $item->addInstruction(FinderIndexer::META_CONTEXT, 'zip'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'zip'); } // Handle the contact telephone number. if ($item->params->get('show_telephone', true)) { - $item->addInstruction(FinderIndexer::META_CONTEXT, 'telephone'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'telephone'); } // Handle the contact fax number. if ($item->params->get('show_fax', true)) { - $item->addInstruction(FinderIndexer::META_CONTEXT, 'fax'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'fax'); } // Handle the contact email address. if ($item->params->get('show_email', true)) { - $item->addInstruction(FinderIndexer::META_CONTEXT, 'email'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'email'); } // Handle the contact mobile number. if ($item->params->get('show_mobile', true)) { - $item->addInstruction(FinderIndexer::META_CONTEXT, 'mobile'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'mobile'); } // Handle the contact webpage. if ($item->params->get('show_webpage', true)) { - $item->addInstruction(FinderIndexer::META_CONTEXT, 'webpage'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'webpage'); } // Handle the contact user name. - $item->addInstruction(FinderIndexer::META_CONTEXT, 'user'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'user'); // Add the type taxonomy data. $item->addTaxonomy('Type', 'Contact'); @@ -370,7 +370,7 @@ protected function index(FinderIndexerResult $item, $format = 'html') } // Get content extras. - FinderIndexerHelper::getContentExtras($item); + SearchIndexerHelper::getContentExtras($item); // Index the item. $this->indexer->index($item); @@ -389,7 +389,7 @@ protected function setup() JLoader::register('ContactHelperRoute', JPATH_SITE . '/components/com_contact/helpers/route.php'); // This is a hack to get around the lack of a route helper. - FinderIndexerHelper::getContentPath('index.php?option=com_contact'); + SearchIndexerHelper::getContentPath('index.php?option=com_contact'); return true; } diff --git a/plugins/finder/content/content.php b/plugins/finder/content/content.php index 5b6dcfd041fe2..00362791528d0 100644 --- a/plugins/finder/content/content.php +++ b/plugins/finder/content/content.php @@ -1,7 +1,7 @@ id; } - elseif ($context == 'com_finder.index') + elseif ($context == 'com_search.index') { $id = $table->link_id; } @@ -231,9 +231,9 @@ public function onFinderChangeState($context, $pks, $value) } /** - * Method to index an item. The item must be a FinderIndexerResult object. + * Method to index an item. The item must be a SearchIndexerResult object. * - * @param FinderIndexerResult $item The item to index as an FinderIndexerResult object. + * @param SearchIndexerResult $item The item to index as an SearchIndexerResult object. * @param string $format The item format. Not used. * * @return void @@ -241,16 +241,16 @@ public function onFinderChangeState($context, $pks, $value) * @since 2.5 * @throws Exception on database error. */ - protected function index(FinderIndexerResult $item, $format = 'html') + protected function index(SearchIndexerResult $item, $format = 'html') { - $item->setLanguage(); - // Check if the extension is enabled. if (JComponentHelper::isEnabled($this->extension) == false) { return; } + $item->setLanguage(); + // Initialise the item parameters. $registry = new Registry($item->params); $item->params = JComponentHelper::getParams('com_content', true); @@ -259,32 +259,22 @@ protected function index(FinderIndexerResult $item, $format = 'html') $item->metadata = new Registry($item->metadata); // Trigger the onContentPrepare event. - $item->summary = FinderIndexerHelper::prepareContent($item->summary, $item->params); - $item->body = FinderIndexerHelper::prepareContent($item->body, $item->params); + $item->summary = SearchIndexerHelper::prepareContent($item->summary, $item->params); + $item->body = SearchIndexerHelper::prepareContent($item->body, $item->params); // Build the necessary route and path information. - $item->url = $this->getUrl($item->id, $this->extension, $this->layout); - $item->route = ContentHelperRoute::getArticleRoute($item->slug, $item->catid, $item->language); - $item->path = FinderIndexerHelper::getContentPath($item->route); - - // Get the menu title if it exists. - $title = $this->getItemMenuTitle($item->url); - - // Adjust the title if necessary. - if (!empty($title) && $this->params->get('use_menu_title', true)) - { - $item->title = $title; - } + $item->url = ContentHelperRoute::getArticleRoute($item->slug, $item->catid, $item->language); + $item->path = SearchIndexerHelper::getContentPath($item->route); // Add the meta author. $item->metaauthor = $item->metadata->get('author'); // Add the metadata processing instructions. - $item->addInstruction(FinderIndexer::META_CONTEXT, 'metakey'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'metadesc'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'metaauthor'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'author'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'created_by_alias'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'metakey'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'metadesc'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'metaauthor'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'author'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'created_by_alias'); // Translate the state. Articles should only be published if the category is published. $item->state = $this->translateState($item->state, $item->cat_state); @@ -305,7 +295,7 @@ protected function index(FinderIndexerResult $item, $format = 'html') $item->addTaxonomy('Language', $item->language); // Get content extras. - FinderIndexerHelper::getContentExtras($item); + SearchIndexerHelper::getContentExtras($item); // Index the item. $this->indexer->index($item); diff --git a/plugins/finder/newsfeeds/newsfeeds.php b/plugins/finder/newsfeeds/newsfeeds.php index 4f40e152a0332..92640c16cbefa 100644 --- a/plugins/finder/newsfeeds/newsfeeds.php +++ b/plugins/finder/newsfeeds/newsfeeds.php @@ -1,7 +1,7 @@ id; } - elseif ($context == 'com_finder.index') + elseif ($context == 'com_search.index') { $id = $table->link_id; } @@ -239,9 +239,9 @@ public function onFinderChangeState($context, $pks, $value) } /** - * Method to index an item. The item must be a FinderIndexerResult object. + * Method to index an item. The item must be a SearchIndexerResult object. * - * @param FinderIndexerResult $item The item to index as an FinderIndexerResult object. + * @param SearchIndexerResult $item The item to index as an SearchIndexerResult object. * @param string $format The item format. Not used. * * @return void @@ -249,7 +249,7 @@ public function onFinderChangeState($context, $pks, $value) * @since 2.5 * @throws Exception on database error. */ - protected function index(FinderIndexerResult $item, $format = 'html') + protected function index(SearchIndexerResult $item, $format = 'html') { // Check if the extension is enabled. if (JComponentHelper::isEnabled($this->extension) == false) @@ -267,7 +267,7 @@ protected function index(FinderIndexerResult $item, $format = 'html') // Build the necessary route and path information. $item->url = $this->getUrl($item->id, $this->extension, $this->layout); $item->route = NewsfeedsHelperRoute::getNewsfeedRoute($item->slug, $item->catslug, $item->language); - $item->path = FinderIndexerHelper::getContentPath($item->route); + $item->path = SearchIndexerHelper::getContentPath($item->route); /* * Add the metadata processing instructions based on the newsfeeds @@ -277,13 +277,13 @@ protected function index(FinderIndexerResult $item, $format = 'html') $item->metaauthor = $item->metadata->get('author'); // Handle the link to the metadata. - $item->addInstruction(FinderIndexer::META_CONTEXT, 'link'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'link'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'metakey'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'metadesc'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'metaauthor'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'author'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'created_by_alias'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'metakey'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'metadesc'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'metaauthor'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'author'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'created_by_alias'); // Add the type taxonomy data. $item->addTaxonomy('Type', 'News Feed'); @@ -295,7 +295,7 @@ protected function index(FinderIndexerResult $item, $format = 'html') $item->addTaxonomy('Language', $item->language); // Get content extras. - FinderIndexerHelper::getContentExtras($item); + SearchIndexerHelper::getContentExtras($item); // Index the item. $this->indexer->index($item); diff --git a/plugins/finder/tags/tags.php b/plugins/finder/tags/tags.php index ba1b1495593d7..8c55ee4b82985 100644 --- a/plugins/finder/tags/tags.php +++ b/plugins/finder/tags/tags.php @@ -1,7 +1,7 @@ id; } - elseif ($context == 'com_finder.index') + elseif ($context == 'com_search.index') { $id = $table->link_id; } @@ -193,9 +193,9 @@ public function onFinderChangeState($context, $pks, $value) } /** - * Method to index an item. The item must be a FinderIndexerResult object. + * Method to index an item. The item must be a SearchIndexerResult object. * - * @param FinderIndexerResult $item The item to index as an FinderIndexerResult object. + * @param SearchIndexerResult $item The item to index as an SearchIndexerResult object. * @param string $format The item format * * @return void @@ -203,7 +203,7 @@ public function onFinderChangeState($context, $pks, $value) * @since 3.1 * @throws Exception on database error. */ - protected function index(FinderIndexerResult $item, $format = 'html') + protected function index(SearchIndexerResult $item, $format = 'html') { // Check if the extension is enabled if (JComponentHelper::isEnabled($this->extension) == false) @@ -223,7 +223,7 @@ protected function index(FinderIndexerResult $item, $format = 'html') // Build the necessary route and path information. $item->url = $this->getUrl($item->id, $this->extension, $this->layout); $item->route = TagsHelperRoute::getTagRoute($item->slug); - $item->path = FinderIndexerHelper::getContentPath($item->route); + $item->path = SearchIndexerHelper::getContentPath($item->route); // Get the menu title if it exists. $title = $this->getItemMenuTitle($item->url); @@ -238,12 +238,12 @@ protected function index(FinderIndexerResult $item, $format = 'html') $item->metaauthor = $item->metadata->get('author'); // Handle the link to the metadata. - $item->addInstruction(FinderIndexer::META_CONTEXT, 'link'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'metakey'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'metadesc'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'metaauthor'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'author'); - $item->addInstruction(FinderIndexer::META_CONTEXT, 'created_by_alias'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'link'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'metakey'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'metadesc'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'metaauthor'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'author'); + $item->addInstruction(SearchIndexer::META_CONTEXT, 'created_by_alias'); // Add the type taxonomy data. $item->addTaxonomy('Type', 'Tag'); diff --git a/plugins/search/finder/finder.php b/plugins/search/finder/finder.php new file mode 100644 index 0000000000000..b5e95cbadaa59 --- /dev/null +++ b/plugins/search/finder/finder.php @@ -0,0 +1,735 @@ + 'PLG_SEARCH_FINDER_FINDER' + ); + + return $areas; + } + + /** + * Search finder + * The SQL must return the following fields that are used in a common display + * routine: href, title, section, created, text, browsernav. + * + * @param string $text Target search string. + * @param string $phrase Matching option (possible values: exact|any|all). Default is "any". + * @param string $ordering Ordering option (possible values: newest|oldest|popular|alpha|category). Default is "newest". + * @param mixed $areas An array if the search it to be restricted to areas or null to search all areas. + * + * @return array Search results. + * + * @since 1.6 + */ + public function onContentSearch($text, $phrase = '', $ordering = '', $areas = null) + { + // Get view data. + $this->_db = JFactory::getDbo(); + $this->state = new JObject; + $state = $this->populateState($text); + $results = $this->getResults(); + + return $results; + } + + /** + * Context string for the model type + * + * @var string + * @since 2.5 + */ + protected $context = 'com_finder.search'; + + /** + * The query object is an instance of SearchIndexerQuery which contains and + * models the entire search query including the text input; static and + * dynamic taxonomy filters; date filters; etc. + * + * @var SearchIndexerQuery + * @since 2.5 + */ + protected $query; + + /** + * An array of all excluded terms ids. + * + * @var array + * @since 2.5 + */ + protected $excludedTerms = array(); + + /** + * An array of all included terms ids. + * + * @var array + * @since 2.5 + */ + protected $includedTerms = array(); + + /** + * An array of all required terms ids. + * + * @var array + * @since 2.5 + */ + protected $requiredTerms = array(); + + /** + * Method to get the results of the query. + * + * @return array An array of SearchIndexerResult objects. + * + * @since 2.5 + * @throws Exception on database error. + */ + public function getResults() + { + // Check if the search query is valid. + if (empty($this->query->search)) + { + return null; + } + + // Check if we should return results. + if (empty($this->includedTerms) && (empty($this->query->filters) || !$this->query->empty)) + { + return null; + } + + // Get the row data. + $items = $this->getResultsData(); + + // Check the data. + if (empty($items)) + { + return null; + } + + // Create the query to get the search results. + $db = $this->_db; + $query = $db->getQuery(true) + ->select($db->quoteName('link_id') . ', ' . $db->quoteName('object')) + ->from($db->quoteName('#__finder_links')) + ->where($db->quoteName('link_id') . ' IN (' . implode(',', array_keys($items)) . ')'); + + // Load the results from the database. + $db->setQuery($query); + $rows = $db->loadObjectList('link_id'); + + // Set up our results container. + $results = $items; + + // Convert the rows to result objects. + foreach ($rows as $rk => $row) + { + // Build the result object. + $result = unserialize($row->object); + $result->weight = $results[$rk]; + $result->link_id = $rk; + + // Add the result back to the stack. + $results[$rk] = $result; + } + + // Switch to a non-associative array. + $results = array_values($results); + + // Return the results. + return $results; + } + + /** + * Method to build a database query to load the list data. + * + * @return JDatabaseQuery A database query. + * + * @since 2.5 + */ + protected function getListQuery() + { + // Set variables + $user = JFactory::getUser(); + $groups = implode(',', $user->getAuthorisedViewLevels()); + + // Create a new query object. + $db = JFactory::getDbo(); + $query = $db->getQuery(true) + ->select('l.link_id') + ->from($db->quoteName('#__finder_links') . ' AS l') + ->where('l.access IN (' . $groups . ')') + ->where('l.state = 1') + ->where('l.published = 1'); + + // Get the null date and the current date, minus seconds. + $nullDate = $db->quote($db->getNullDate()); + $nowDate = $db->quote(substr_replace(JFactory::getDate()->toSql(), '00', -2)); + + // Add the publish up and publish down filters. + $query->where('(l.publish_start_date = ' . $nullDate . ' OR l.publish_start_date <= ' . $nowDate . ')') + ->where('(l.publish_end_date = ' . $nullDate . ' OR l.publish_end_date >= ' . $nowDate . ')'); + + /* + * Add the taxonomy filters to the query. We have to join the taxonomy + * map table for each group so that we can use AND clauses across + * groups. Within each group there can be an array of values that will + * use OR clauses. + */ + if (!empty($this->query->filters)) + { + // Convert the associative array to a numerically indexed array. + $groups = array_values($this->query->filters); + + // Iterate through each taxonomy group and add the join and where. + for ($i = 0, $c = count($groups); $i < $c; $i++) + { + // We use the offset because each join needs a unique alias. + $query->join('INNER', $db->quoteName('#__finder_taxonomy_map') . ' AS t' . $i . ' ON t' . $i . '.link_id = l.link_id') + ->where('t' . $i . '.node_id IN (' . implode(',', $groups[$i]) . ')'); + } + } + + // Add the start date filter to the query. + if (!empty($this->query->date1)) + { + // Escape the date. + $date1 = $db->quote($this->query->date1); + + // Add the appropriate WHERE condition. + if ($this->query->when1 == 'before') + { + $query->where($db->quoteName('l.start_date') . ' <= ' . $date1); + } + elseif ($this->query->when1 == 'after') + { + $query->where($db->quoteName('l.start_date') . ' >= ' . $date1); + } + else + { + $query->where($db->quoteName('l.start_date') . ' = ' . $date1); + } + } + + // Add the end date filter to the query. + if (!empty($this->query->date2)) + { + // Escape the date. + $date2 = $db->quote($this->query->date2); + + // Add the appropriate WHERE condition. + if ($this->query->when2 == 'before') + { + $query->where($db->quoteName('l.start_date') . ' <= ' . $date2); + } + elseif ($this->query->when2 == 'after') + { + $query->where($db->quoteName('l.start_date') . ' >= ' . $date2); + } + else + { + $query->where($db->quoteName('l.start_date') . ' = ' . $date2); + } + } + // Filter by language + if ($this->state->get('filter.language')) + { + $query->where('l.language IN (' . $db->quote(JFactory::getLanguage()->getTag()) . ', ' . $db->quote('*') . ')'); + } + + // Return a copy of the query object. + return $query; + } + + /** + * Method to get the results for the search query. + * + * @return array An array of result data objects. + * + * @since 2.5 + * @throws Exception on database error. + */ + protected function getResultsData() + { + // Get the result ordering and direction. + $ordering = $this->state->get('list.ordering', 'l.start_date'); + $direction = $this->state->get('list.direction', 'DESC'); + + // Get the base query and add the ordering information. + $base = $this->getListQuery(); + $base->select($this->_db->escape($ordering) . ' AS ordering'); + $base->order($this->_db->escape($ordering) . ' ' . $this->_db->escape($direction)); + + /* + * If there are no optional or required search terms in the query, we + * can get the results in one relatively simple database query. + */ + if (empty($this->includedTerms)) + { + // Get the results from the database. + $this->_db->setQuery($base, (int) $this->state->get('list.start'), (int) $this->state->get('list.limit')); + return $this->_db->loadObjectList('link_id'); + } + + /* + * If there are optional or required search terms in the query, the + * process of getting the results is more complicated. + */ + $start = 0; + $limit = (int) $this->state->get('match.limit'); + $items = array(); + $results = array(); + $sorted = array(); + $allIDs = array(); + $excluded = $this->getExcludedLinkIds(); + + foreach ($this->includedTerms as $token => $ids) + { + $allIDs = array_merge($allIDs, $ids); + } + + // Adjust the query to join on the appropriate mapping table. + $query = clone($base); + $query->join('INNER', $this->_db->quoteName('#__finder_links_terms') . ' AS m ON m.link_id = l.link_id') + ->where('m.term_id IN (' . implode(',', $allIDs) . ')'); + + // Load the results from the database. + $this->_db->setQuery($query, $start, $limit); + $results = $this->_db->loadObjectList('link_id'); + + // Store this set in cache. + $this->store($setId, $results); + + // The data is keyed by link_id to ease caching, we don't need it till later. + $results = array_values($results); + + // Check if there are any excluded terms to deal with. + if (count($excluded)) + { + // Remove any results that match excluded terms. + for ($i = 0, $c = count($results); $i < $c; $i++) + { + if (in_array($results[$i]->link_id, $excluded)) + { + unset($results[$i]); + } + } + + // Reset the array keys. + $results = array_values($results); + } + + /* + * If we are ordering by relevance we have to add up the relevance + * scores that are contained in the ordering field. + */ + if ($ordering === 'm.weight') + { + // Iterate through the set to extract the unique items. + for ($i = 0, $c = count($results); $i < $c; $i++) + { + // Add the total weights for all included search terms. + if (isset($sorted[$results[$i]->link_id])) + { + $sorted[$results[$i]->link_id] += (float) $results[$i]->ordering; + } + else + { + $sorted[$results[$i]->link_id] = (float) $results[$i]->ordering; + } + } + } + /* + * If we are ordering by start date we have to add convert the + * dates to unix timestamps. + */ + elseif ($ordering === 'l.start_date') + { + // Iterate through the set to extract the unique items. + for ($i = 0, $c = count($results); $i < $c; $i++) + { + if (!isset($sorted[$results[$i]->link_id])) + { + $sorted[$results[$i]->link_id] = strtotime($results[$i]->ordering); + } + } + } + /* + * If we are not ordering by relevance or date, we just have to add + * the unique items to the set. + */ + else + { + // Iterate through the set to extract the unique items. + for ($i = 0, $c = count($results); $i < $c; $i++) + { + if (!isset($sorted[$results[$i]->link_id])) + { + $sorted[$results[$i]->link_id] = $results[$i]->ordering; + } + } + } + + $items = $sorted; + + // Sort the results. + natcasesort($items); + if ($direction === 'DESC') + { + $items = array_reverse($items, true); + } + + /* + * If the query contains just optional search terms and we have + * enough items for the page, we can stop here. + */ + if (empty($this->requiredTerms)) + { + return $sorted; + } + + /* + * The query contains required search terms so we have to iterate + * over the items and remove any items that do not match all of the + * required search terms. This is one of the most expensive steps + * because a required token could theoretically eliminate all of + * current terms which means we would have to loop through all of + * the possibilities. + */ + foreach ($this->requiredTerms as $token => $required) + { + // Check if the token was matched. + if (empty($required)) + { + return null; + } + // Load the data from the database. + else + { + // Setup containers in case we have to make multiple passes. + $reqStart = 0; + $reqTemp = array(); + + // Adjust the query to join on the appropriate mapping table. + $query = clone($base); + $query->join('INNER', $this->_db->quoteName('#__finder_links_terms') . ' AS m ON m.link_id = l.link_id') + ->where('m.term_id IN (' . implode(',', $required) . ')'); + + // Load the results from the database. + $this->_db->setQuery($query, $reqStart, $limit); + $temp = $this->_db->loadObjectList('link_id'); + + // Merge the matching set for this token. + $reqTemp = $reqTemp + $temp; + + // Increment the term offset. + $reqStart += $limit; + } + + // Remove any items that do not match the required term. + $sorted = array_intersect_key($sorted, $reqTemp); + } + + // If we need more items and they're available, make another pass. + if (count($sorted) < ($this->state->get('list.start') + $this->state->get('list.limit'))) + { + // Increment the batch starting point. + $start += $limit; + + // Merge the found items. + $items = array_merge($items, $sorted); + } + + // Return the requested set. + return $items; + } + + /** + * 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(); + $allIDs = 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) + { + $allIDs[] = (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); + + // Create the query to get the links ids. + $query->clear() + ->select('link_id') + ->from($db->quoteName('#__finder_links_terms')) + ->where($db->quoteName('term_id') . ' IN (' . implode(',', $allIDs) . ')') + ->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; + } + + /** + * Method to auto-populate the model state. Calling state->get in this method will result in recursion. + * + * @param string $ordering An optional ordering field. [optional] + * @param string $direction An optional direction. [optional] + * + * @return void + * + * @since 2.5 + */ + protected function populateState($search) + { + // Get the configuration options. + $app = JFactory::getApplication(); + $input = $app->input; + $params = JComponentHelper::getParams('com_search'); + $user = JFactory::getUser(); + $filter = JFilterInput::getInstance(); + + $this->state->set('filter.language', JLanguageMultilang::isEnabled()); + + // Setup the stemmer. + if ($params->get('stem', 1) && $params->get('stemmer', 'porter_en')) + { + SearchIndexerHelper::$stemmer = SearchIndexerStemmer::getInstance($params->get('stemmer', 'porter_en')); + } + + $request = $input->request; + $options = array(); + + // Get the empty query setting. + $options['empty'] = $params->get('allow_empty_query', 0); + + // Get the static taxonomy filters. + $options['filter'] = $request->getInt('f', $params->get('f', '')); + + // Get the dynamic taxonomy filters. + $options['filters'] = $request->get('t', $params->get('t', array()), '', 'array'); + + // Get the query string. + $options['input'] = $search; + + // Get the query language. + $options['language'] = $request->getCmd('l', $params->get('l', '')); + + // Get the start date and start date modifier filters. + $options['date1'] = $request->getString('d1', $params->get('d1', '')); + $options['when1'] = $request->getString('w1', $params->get('w1', '')); + + // Get the end date and end date modifier filters. + $options['date2'] = $request->getString('d2', $params->get('d2', '')); + $options['when2'] = $request->getString('w2', $params->get('w2', '')); + + // Load the query object. + $this->query = new SearchIndexerQuery($options); + + // Load the query token data. + $this->excludedTerms = $this->query->getExcludedTermIds(); + $this->includedTerms = $this->query->getIncludedTermIds(); + $this->requiredTerms = $this->query->getRequiredTermIds(); + + // Load the list state. + $this->state->set('list.start', $input->get('limitstart', 0, 'uint')); + $this->state->set('list.limit', $input->get('limit', $app->get('list_limit', 20), 'uint')); + + /* Load the sort ordering. + * Currently this is 'hard' coded via menu item parameter but may not satisfy a users need. + * More flexibility was way more user friendly. So we allow the user to pass a custom value + * from the pool of fields that are indexed like the 'title' field. + * Also, we allow this parameter to be passed in either case (lower/upper). + */ + $order = $input->getWord('filter_order', $params->get('sort_order', 'relevance')); + $order = JString::strtolower($order); + switch ($order) + { + case 'date': + $this->state->set('list.ordering', 'l.start_date'); + break; + + case 'price': + $this->state->set('list.ordering', 'l.list_price'); + break; + + case ($order == 'relevance' && !empty($this->includedTerms)): + $this->state->set('list.ordering', 'm.weight'); + break; + + // Custom field that is indexed and might be required for ordering + case 'title': + $this->state->set('list.ordering', 'l.title'); + break; + + default: + $this->state->set('list.ordering', 'l.link_id'); + break; + } + + /* Load the sort direction. + * Currently this is 'hard' coded via menu item parameter but may not satisfy a users need. + * More flexibility was way more user friendly. So we allow to be inverted. + * Also, we allow this parameter to be passed in either case (lower/upper). + */ + $dirn = $input->getWord('filter_order_Dir', $params->get('sort_direction', 'desc')); + $dirn = JString::strtolower($dirn); + switch ($dirn) + { + case 'asc': + $this->state->set('list.direction', 'ASC'); + break; + + default: + case 'desc': + $this->state->set('list.direction', 'DESC'); + break; + } + + // Set the match limit. + $this->state->set('match.limit', 1000); + + // Load the parameters. + $this->state->set('params', $params); + + // Load the user state. + $this->state->set('user.id', (int) $user->get('id')); + $this->state->set('user.groups', $user->getAuthorisedViewLevels()); + } + + /** + * Method to retrieve data from cache. + * + * @param string $id The cache store id. + * @param boolean $persistent Flag to enable the use of external cache. [optional] + * + * @return mixed The cached data if found, null otherwise. + * + * @since 2.5 + */ + /**protected function retrieve($id, $persistent = true) + { + $data = null; + + // Use the internal cache if possible. + if (isset($this->cache[$id])) + { + return $this->cache[$id]; + } + + // Use the external cache if data is persistent. + if ($persistent) + { + $data = JFactory::getCache($this->context, 'output')->get($id); + $data = $data ? unserialize($data) : null; + } + + // Store the data in internal cache. + if ($data) + { + $this->cache[$id] = $data; + } + + return $data; + }**/ + + /** + * Method to store data in cache. + * + * @param string $id The cache store id. + * @param mixed $data The data to cache. + * @param boolean $persistent Flag to enable the use of external cache. [optional] + * + * @return boolean True on success, false on failure. + * + * @since 2.5 + */ + protected function store($id, $data, $persistent = true) + { + // Store the data in internal cache. + $this->cache[$id] = $data; + + // Store the data in external cache if data is persistent. + if ($persistent) + { + return JFactory::getCache($this->context, 'output')->store(serialize($data), $id); + } + + return true; + } +} diff --git a/plugins/search/finder/finder.xml b/plugins/search/finder/finder.xml new file mode 100644 index 0000000000000..4b36261671f13 --- /dev/null +++ b/plugins/search/finder/finder.xml @@ -0,0 +1,20 @@ + + + plg_search_finder + Joomla! Project + November 2016 + Copyright (C) 2005 - 2016 Open Source Matters. All rights reserved. + GNU General Public License version 2 or later; see LICENSE.txt + admin@joomla.org + www.joomla.org + 4.0.0 + PLG_SEARCH_FINDER_XML_DESCRIPTION + + finder.php + + + en-GB.plg_search_finder.ini + en-GB.plg_search_finder.sys.ini + + +