Added the Porter Stemmer module to improve searches. This doesn't deal with some...
[yaffs-website] / web / modules / contrib / porterstemmer / porterstemmer.module
1 <?php
2
3 /**
4  * @file
5  * Contains porterstemmer.module.
6  */
7
8 use Drupal\Core\Routing\RouteMatchInterface;
9 use Drupal\porterstemmer\Porter2;
10
11 /**
12  * Regular expression defining a word boundary for Porter Stemmer.
13  *
14  * A word boundary is anything not a letter or an apostrophe.
15  */
16 define('PORTERSTEMMER_BOUNDARY', "[^a-zA-Z']+");
17
18 /**
19  * Implements hook_help().
20  */
21 function porterstemmer_help($route_name, RouteMatchInterface $route_match) {
22   switch ($route_name) {
23     // Main module help for the porterstemmer module.
24     case 'help.page.porterstemmer':
25       $output = '';
26       $output .= '<h3>' . t('About') . '</h3>';
27       $output .= '<p>' . t('Improves American English language searching by simplifying related words to their root (conjugations, plurals, ...).') . '</p>';
28       return $output;
29
30     default:
31   }
32 }
33
34 /**
35  * Implements hook_search_preprocess().
36  *
37  * Stems the words in $text, using the Porter 2 (English) stemming algorithm.
38  */
39 function porterstemmer_search_preprocess($text, $langcode = NULL) {
40   // If the language is not set, get it from the language manager.
41   if (!isset($langcode)) {
42     $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
43   }
44
45   if ($langcode == 'en') {
46     // Convert text to lower case, and replace special apostrophes with regular
47     // apostrophes.
48     $text = strtolower(str_replace('’', "'", $text));
49
50     // Split into words.
51     $words = preg_split('/(' . PORTERSTEMMER_BOUNDARY . '+)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
52
53     if (!count($words)) {
54       return $text;
55     }
56
57     $has_pecl_stem = _porterstemmer_pecl_loaded();
58
59     // Process each word, skipping delimiters.
60     $isword = !preg_match('/' . PORTERSTEMMER_BOUNDARY . '/', $words[0]);
61     foreach ($words as $k => $word) {
62       if ($isword) {
63         if ($has_pecl_stem) {
64           $words[$k] = stem_english($word);
65         }
66         else {
67           $words[$k] = Porter2::stem($word);
68         }
69       }
70       $isword = !$isword;
71     }
72
73     // Put it all back together (note that delimiters are in $words).
74     return implode('', $words);
75   }
76
77   return $text;
78 }
79
80 /**
81  * Checks to see if the PECL stem extension has been loaded.
82  *
83  * @return bool
84  *    TRUE if the stem_english() function from the PECL stem library can be
85  *    used, FALSE if not.
86  */
87 function _porterstemmer_pecl_loaded() {
88   static $has_pecl_stem = FALSE;
89   static $already_checked = FALSE;
90
91   if ($already_checked) {
92     return $has_pecl_stem;
93   }
94
95   $has_pecl_stem = extension_loaded('stem') && function_exists('stem_english');
96   $already_checked = TRUE;
97   return $has_pecl_stem;
98 }