Source for file helper.php

Documentation is available at helper.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Administrator
  4.  * @subpackage  com_finder
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE
  8.  */
  9.  
  10. defined('_JEXEC'or die;
  11.  
  12. JLoader::register('FinderIndexerParser'__DIR__ . '/parser.php');
  13. JLoader::register('FinderIndexerStemmer'__DIR__ . '/stemmer.php');
  14. JLoader::register('FinderIndexerToken'__DIR__ . '/token.php');
  15.  
  16. /**
  17.  * Helper class for the Finder indexer package.
  18.  *
  19.  * @package     Joomla.Administrator
  20.  * @subpackage  com_finder
  21.  * @since       2.5
  22.  */
  23. {
  24.     /**
  25.      * The token stemmer object. The stemmer is set by whatever class
  26.      * wishes to use it but it must be an instance of FinderIndexerStemmer.
  27.      *
  28.      * @var        FinderIndexerStemmer 
  29.      * @since    2.5
  30.      */
  31.     public static $stemmer;
  32.  
  33.     /**
  34.      * Method to parse input into plain text.
  35.      *
  36.      * @param   string  $input   The raw input.
  37.      * @param   string  $format  The format of the input. [optional]
  38.      *
  39.      * @return  string  The parsed input.
  40.      *
  41.      * @since   2.5
  42.      * @throws  Exception on invalid parser.
  43.      */
  44.     public static function parse($input$format 'html')
  45.     {
  46.         // Get a parser for the specified format and parse the input.
  47.         return FinderIndexerParser::getInstance($format)->parse($input);
  48.     }
  49.  
  50.     /**
  51.      * Method to tokenize a text string.
  52.      *
  53.      * @param   string   $input   The input to tokenize.
  54.      * @param   string   $lang    The language of the input.
  55.      * @param   boolean  $phrase  Flag to indicate whether input could be a phrase. [optional]
  56.      *
  57.      * @return  array  An array of FinderIndexerToken objects.
  58.      *
  59.      * @since   2.5
  60.      */
  61.     public static function tokenize($input$lang$phrase false)
  62.     {
  63.         static $cache;
  64.         $store JString::strlen($input128 md5($input '::' $lang '::' $phrasenull;
  65.  
  66.         // Check if the string has been tokenized already.
  67.         if ($store && isset($cache[$store]))
  68.         {
  69.             return $cache[$store];
  70.         }
  71.  
  72.         $tokens array();
  73.         $quotes html_entity_decode('&#8216;&#8217;&#39;'ENT_QUOTES'UTF-8');
  74.  
  75.         // Get the simple language key.
  76.         $lang self::getPrimaryLanguage($lang);
  77.  
  78.         /*
  79.          * Parsing the string input into terms is a multi-step process.
  80.          *
  81.          * Regexes:
  82.          *  1. Remove everything except letters, numbers, quotes, apostrophe, plus, dash, period, and comma.
  83.          *  2. Remove plus, dash, period, and comma characters located before letter characters.
  84.          *  3. Remove plus, dash, period, and comma characters located after other characters.
  85.          *  4. Remove plus, period, and comma characters enclosed in alphabetical characters. Ungreedy.
  86.          *  5. Remove orphaned apostrophe, plus, dash, period, and comma characters.
  87.          *  6. Remove orphaned quote characters.
  88.          *  7. Replace the assorted single quotation marks with the ASCII standard single quotation.
  89.          *  8. Remove multiple space characters and replaces with a single space.
  90.          */
  91.         $input JString::strtolower($input);
  92.         $input preg_replace('#[^\pL\pM\pN\p{Pi}\p{Pf}\'+-.,]+#mui'' '$input);
  93.         $input preg_replace('#(^|\s)[+-.,]+([\pL\pM]+)#mui'' $1'$input);
  94.         $input preg_replace('#([\pL\pM\pN]+)[+-.,]+(\s|$)#mui''$1 '$input);
  95.         $input preg_replace('#([\pL\pM]+)[+.,]+([\pL\pM]+)#muiU''$1 $2'$input);
  96.         $input preg_replace('#(^|\s)[\'+-.,]+(\s|$)#mui'' '$input);
  97.         $input preg_replace('#(^|\s)[\p{Pi}\p{Pf}]+(\s|$)#mui'' '$input);
  98.         $input preg_replace('#[' $quotes ']+#mui''\''$input);
  99.         $input preg_replace('#\s+#mui'' '$input);
  100.         $input JString::trim($input);
  101.  
  102.         // Explode the normalized string to get the terms.
  103.         $terms explode(' '$input);
  104.  
  105.         /*
  106.          * If we have Unicode support and are dealing with Chinese text, Chinese
  107.          * has to be handled specially because there are not necessarily any spaces
  108.          * between the "words". So, we have to test if the words belong to the Chinese
  109.          * character set and if so, explode them into single glyphs or "words".
  110.          */
  111.         if ($lang === 'zh')
  112.         {
  113.             // Iterate through the terms and test if they contain Chinese.
  114.             for ($i 0$n count($terms)$i $n$i++)
  115.             {
  116.                 $charMatches array();
  117.                 $charCount preg_match_all('#[\p{Han}]#mui'$terms[$i]$charMatches);
  118.  
  119.                 // Split apart any groups of Chinese characters.
  120.                 for ($j 0$j $charCount$j++)
  121.                 {
  122.                     $tSplit JString::str_ireplace($charMatches[0][$j]''$terms[$i]false);
  123.                     if (!empty($tSplit))
  124.                     {
  125.                         $terms[$i$tSplit;
  126.                     }
  127.                     else
  128.                     {
  129.                         unset($terms[$i]);
  130.                     }
  131.  
  132.                     $terms[$charMatches[0][$j];
  133.                 }
  134.             }
  135.  
  136.             // Reset array keys.
  137.             $terms array_values($terms);
  138.         }
  139.  
  140.         /*
  141.          * If we have to handle the input as a phrase, that means we don't
  142.          * tokenize the individual terms and we do not create the two and three
  143.          * term combinations. The phrase must contain more than one word!
  144.          */
  145.         if ($phrase === true && count($terms1)
  146.         {
  147.             // Create tokens from the phrase.
  148.             $tokens[new FinderIndexerToken($terms$lang);
  149.         }
  150.         else
  151.         {
  152.             // Create tokens from the terms.
  153.             for ($i 0$n count($terms)$i $n$i++)
  154.             {
  155.                 $tokens[new FinderIndexerToken($terms[$i]$lang);
  156.             }
  157.  
  158.             // Create two and three word phrase tokens from the individual words.
  159.             for ($i 0$n count($tokens)$i $n$i++)
  160.             {
  161.                 // Setup the phrase positions.
  162.                 $i2 $i 1;
  163.                 $i3 $i 2;
  164.  
  165.                 // Create the two word phrase.
  166.                 if ($i2 $n && isset($tokens[$i2]))
  167.                 {
  168.                     // Tokenize the two word phrase.
  169.                     $token new FinderIndexerToken(array($tokens[$i]->term$tokens[$i2]->term)$lang$lang === 'zh' '' ' ');
  170.                     $token->derived true;
  171.  
  172.                     // Add the token to the stack.
  173.                     $tokens[$token;
  174.                 }
  175.  
  176.                 // Create the three word phrase.
  177.                 if ($i3 $n && isset($tokens[$i3]))
  178.                 {
  179.                     // Tokenize the three word phrase.
  180.                     $token new FinderIndexerToken(array($tokens[$i]->term$tokens[$i2]->term$tokens[$i3]->term)$lang$lang === 'zh' '' ' ');
  181.                     $token->derived true;
  182.  
  183.                     // Add the token to the stack.
  184.                     $tokens[$token;
  185.                 }
  186.             }
  187.         }
  188.  
  189.         if ($store)
  190.         {
  191.             $cache[$storecount($tokens$tokens array_shift($tokens);
  192.             return $cache[$store];
  193.         }
  194.         else
  195.         {
  196.             return count($tokens$tokens array_shift($tokens);
  197.         }
  198.     }
  199.  
  200.     /**
  201.      * Method to get the base word of a token. This method uses the public
  202.      * {@link FinderIndexerHelper::$stemmer} object if it is set. If no stemmer is set,
  203.      * the original token is returned.
  204.      *
  205.      * @param   string  $token  The token to stem.
  206.      * @param   string  $lang   The language of the token.
  207.      *
  208.      * @return  string  The root token.
  209.      *
  210.      * @since   2.5
  211.      */
  212.     public static function stem($token$lang)
  213.     {
  214.         // Trim apostrophes at either end of the token.
  215.         $token JString::trim($token'\'');
  216.  
  217.         // Trim everything after any apostrophe in the token.
  218.         if (($pos JString::strpos($token'\'')) !== false)
  219.         {
  220.             $token JString::substr($token0$pos);
  221.         }
  222.  
  223.         // Stem the token if we have a valid stemmer to use.
  224.         if (self::$stemmer instanceof FinderIndexerStemmer)
  225.         {
  226.             return self::$stemmer->stem($token$lang);
  227.         }
  228.         else
  229.         {
  230.             return $token;
  231.         }
  232.     }
  233.  
  234.     /**
  235.      * Method to add a content type to the database.
  236.      *
  237.      * @param   string  $title  The type of content. For example: PDF
  238.      * @param   string  $mime   The mime type of the content. For example: PDF [optional]
  239.      *
  240.      * @return  integer  The id of the content type.
  241.      *
  242.      * @since   2.5
  243.      * @throws  Exception on database error.
  244.      */
  245.     public static function addContentType($title$mime null)
  246.     {
  247.         static $types;
  248.  
  249.         $db JFactory::getDbo();
  250.         $query $db->getQuery(true);
  251.  
  252.         // Check if the types are loaded.
  253.         if (empty($types))
  254.         {
  255.             // Build the query to get the types.
  256.             $query->select('*')
  257.                 ->from($db->quoteName('#__finder_types'));
  258.  
  259.             // Get the types.
  260.             $db->setQuery($query);
  261.             $types $db->loadObjectList('title');
  262.         }
  263.  
  264.         // Check if the type already exists.
  265.         if (isset($types[$title]))
  266.         {
  267.             return (int) $types[$title]->id;
  268.         }
  269.  
  270.         // Add the type.
  271.         $query->clear()
  272.             ->insert($db->quoteName('#__finder_types'))
  273.             ->columns(array($db->quoteName('title')$db->quoteName('mime')))
  274.             ->values($db->quote($title', ' $db->quote($mime));
  275.         $db->setQuery($query);
  276.         $db->execute();
  277.  
  278.         // Return the new id.
  279.         return (int) $db->insertid();
  280.     }
  281.  
  282.     /**
  283.      * Method to check if a token is common in a language.
  284.      *
  285.      * @param   string  $token  The token to test.
  286.      * @param   string  $lang   The language to reference.
  287.      *
  288.      * @return  boolean  True if common, false otherwise.
  289.      *
  290.      * @since   2.5
  291.      */
  292.     public static function isCommon($token$lang)
  293.     {
  294.         static $data;
  295.  
  296.         // Load the common tokens for the language if necessary.
  297.         if (!isset($data[$lang]))
  298.         {
  299.             $data[$langself::getCommonWords($lang);
  300.         }
  301.  
  302.         // Check if the token is in the common array.
  303.         if (in_array($token$data[$lang]))
  304.         {
  305.             return true;
  306.         }
  307.         else
  308.         {
  309.             return false;
  310.         }
  311.     }
  312.  
  313.     /**
  314.      * Method to get an array of common terms for a language.
  315.      *
  316.      * @param   string  $lang  The language to use.
  317.      *
  318.      * @return  array  Array of common terms.
  319.      *
  320.      * @since   2.5
  321.      * @throws  Exception on database error.
  322.      */
  323.     public static function getCommonWords($lang)
  324.     {
  325.         $db JFactory::getDbo();
  326.  
  327.         // Create the query to load all the common terms for the language.
  328.         $query $db->getQuery(true)
  329.             ->select($db->quoteName('term'))
  330.             ->from($db->quoteName('#__finder_terms_common'))
  331.             ->where($db->quoteName('language'' = ' $db->quote($lang));
  332.  
  333.         // Load all of the common terms for the language.
  334.         $db->setQuery($query);
  335.         $results $db->loadColumn();
  336.  
  337.         return $results;
  338.     }
  339.  
  340.     /**
  341.      * Method to get the default language for the site.
  342.      *
  343.      * @return  string  The default language string.
  344.      *
  345.      * @since   2.5
  346.      */
  347.     public static function getDefaultLanguage()
  348.     {
  349.         static $lang;
  350.  
  351.         // We need to go to com_languages to get the site default language, it's the best we can guess.
  352.         if (empty($lang))
  353.         {
  354.             $lang JComponentHelper::getParams('com_languages')->get('site''en-GB');
  355.         }
  356.  
  357.         return $lang;
  358.     }
  359.  
  360.     /**
  361.      * Method to parse a language/locale key and return a simple language string.
  362.      *
  363.      * @param   string  $lang  The language/locale key. For example: en-GB
  364.      *
  365.      * @return  string  The simple language string. For example: en
  366.      *
  367.      * @since   2.5
  368.      */
  369.     public static function getPrimaryLanguage($lang)
  370.     {
  371.         static $data;
  372.  
  373.         // Only parse the identifier if necessary.
  374.         if (!isset($data[$lang]))
  375.         {
  376.             if (is_callable(array('Locale''getPrimaryLanguage')))
  377.             {
  378.                 // Get the language key using the Locale package.
  379.                 $data[$langLocale::getPrimaryLanguage($lang);
  380.             }
  381.             else
  382.             {
  383.                 // Get the language key using string position.
  384.                 $data[$langJString::substr($lang0JString::strpos($lang'-'));
  385.             }
  386.         }
  387.  
  388.         return $data[$lang];
  389.     }
  390.  
  391.     /**
  392.      * Method to get the path (SEF route) for a content item.
  393.      *
  394.      * @param   string  $url  The non-SEF route to the content item.
  395.      *
  396.      * @return  string  The path for the content item.
  397.      *
  398.      * @since   2.5
  399.      */
  400.     public static function getContentPath($url)
  401.     {
  402.         static $router;
  403.  
  404.         // Only get the router once.
  405.         if (!($router instanceof JRouter))
  406.         {
  407.             // Get and configure the site router.
  408.             $config JFactory::getConfig();
  409.             $router JRouter::getInstance('site');
  410.             $router->setMode($config->get('sef'1));
  411.         }
  412.  
  413.         // Build the relative route.
  414.         $uri $router->build($url);
  415.         $route $uri->toString(array('path''query''fragment'));
  416.         $route str_replace(JUri::base(true'/'''$route);
  417.  
  418.         return $route;
  419.     }
  420.  
  421.     /**
  422.      * Method to get extra data for a content before being indexed. This is how
  423.      * we add Comments, Tags, Labels, etc. that should be available to Finder.
  424.      *
  425.      * @param   FinderIndexerResult  &$item  The item to index as an FinderIndexerResult object.
  426.      *
  427.      * @return  boolean  True on success, false on failure.
  428.      *
  429.      * @since   2.5
  430.      * @throws  Exception on database error.
  431.      */
  432.     public static function getContentExtras(FinderIndexerResult &$item)
  433.     {
  434.         // Get the event dispatcher.
  435.         $dispatcher JEventDispatcher::getInstance();
  436.  
  437.         // Load the finder plugin group.
  438.         JPluginHelper::importPlugin('finder');
  439.  
  440.         try
  441.         {
  442.             // Trigger the event.
  443.             $results $dispatcher->trigger('onPrepareFinderContent'array(&$item));
  444.  
  445.             // Check the returned results. This is for plugins that don't throw
  446.             // exceptions when they encounter serious errors.
  447.             if (in_array(false$results))
  448.             {
  449.                 throw new Exception($dispatcher->getError()500);
  450.             }
  451.         }
  452.         catch (Exception $e)
  453.         {
  454.             // Handle a caught exception.
  455.             throw $e;
  456.         }
  457.  
  458.         return true;
  459.     }
  460.  
  461.     /**
  462.      * Method to process content text using the onContentPrepare event trigger.
  463.      *
  464.      * @param   string     $text    The content to process.
  465.      * @param   JRegistry  $params  The parameters object. [optional]
  466.      *
  467.      * @return  string  The processed content.
  468.      *
  469.      * @since   2.5
  470.      */
  471.     public static function prepareContent($text$params null)
  472.     {
  473.         static $loaded;
  474.  
  475.         // Get the dispatcher.
  476.         $dispatcher JEventDispatcher::getInstance();
  477.  
  478.         // Load the content plugins if necessary.
  479.         if (empty($loaded))
  480.         {
  481.             JPluginHelper::importPlugin('content');
  482.             $loaded true;
  483.         }
  484.  
  485.         // Instantiate the parameter object if necessary.
  486.         if (!($params instanceof JRegistry))
  487.         {
  488.             $registry new JRegistry;
  489.             $registry->loadString($params);
  490.             $params $registry;
  491.         }
  492.  
  493.         // Create a mock content object.
  494.         $content JTable::getInstance('Content');
  495.         $content->text $text;
  496.  
  497.         // Fire the onContentPrepare event.
  498.         $dispatcher->trigger('onContentPrepare'array('com_finder.indexer'&$content&$params0));
  499.  
  500.         return $content->text;
  501.     }
  502. }

Documentation generated on Tue, 19 Nov 2013 15:04:20 +0100 by phpDocumentor 1.4.3