Webylon 3.1 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • auth
  • Booking
  • cart
    • shipping
    • steppedcheckout
  • Catalog
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • AdvancedSearchForm
  • ContentControllerSearchExtension
  • EndsWithFilter
  • ExactMatchFilter
  • ExactMatchMultiFilter
  • FulltextFilter
  • FulltextSearchable
  • GreaterThanFilter
  • LessThanFilter
  • NegationFilter
  • PartialMatchFilter
  • SearchContext
  • SearchFilter
  • SearchForm
  • StartsWithFilter
  • StartsWithMultiFilter
  • SubstringFilter
  • WithinRangeFilter
  1 <?php
  2 /**
  3  * Standard basic search form which conducts a fulltext search on all {@link SiteTree}
  4  * objects. 
  5  *
  6  * If multilingual content is enabled through the {@link Translatable} extension,
  7  * only pages the currently set language on the holder for this searchform are found.
  8  * The language is set through a hidden field in the form, which is prepoluated
  9  * with {@link Translatable::get_current_locale()} when then form is constructed.
 10  * 
 11  * @see Use ModelController and SearchContext for a more generic search implementation based around DataObject
 12  * @package sapphire
 13  * @subpackage search
 14  */
 15 class SearchForm extends Form {
 16 
 17     private static $search_mode = 'morphy';
 18 
 19     /**
 20      * устанавливает режим поиска
 21      * 
 22      * @param string $val - режим
 23      *  * morphy - морфологический поиск (спец. символы не работают)
 24      *  * extended - поиск с выражениями: +слово -слово "как есть"
 25      *  * simple - поиск слов "как есть"
 26      */
 27     static function set_serch_mode($val) {
 28         self::$search_mode = $val;
 29     }
 30     
 31     /**
 32      * @var int $pageLength How many results are shown per page.
 33      * Relies on pagination being implemented in the search results template.
 34      */
 35     protected $pageLength = 10;
 36     
 37     /**
 38      * Classes to search
 39      */ 
 40     protected $classesToSearch = array(
 41         "SiteTree", "File"
 42     );
 43     
 44     /**
 45      * 
 46      * @param Controller $controller
 47      * @param string $name The name of the form (used in URL addressing)
 48      * @param FieldSet $fields Optional, defaults to a single field named "Search". Search logic needs to be customized
 49      *  if fields are added to the form.
 50      * @param FieldSet $actions Optional, defaults to a single field named "Go".
 51      */
 52     function __construct($controller, $name, $fields = null, $actions = null) {
 53         if(!$fields) {
 54             $fields = new FieldSet(
 55                 new TextField('Search', _t('SearchForm.SEARCH', 'Search')
 56             ));
 57         }
 58         
 59         if(singleton('SiteTree')->hasExtension('Translatable')) {
 60             $fields->push(new HiddenField('locale', 'locale', Translatable::get_current_locale()));
 61         }
 62         
 63         if(!$actions) {
 64             $actions = new FieldSet(
 65                 new FormAction("getResults", _t('SearchForm.GO', 'Go'))
 66             );
 67         }
 68         
 69         parent::__construct($controller, $name, $fields, $actions);
 70         
 71         $this->setFormMethod('get');
 72         
 73         $this->disableSecurityToken();
 74         $this->getValidator()->setJavascriptValidationHandler('none');
 75     }
 76     
 77     public function forTemplate() {
 78         return $this->renderWith(array(
 79             'SearchForm',
 80             'Form'
 81         ));
 82     }
 83 
 84     /**
 85      * Set the classes to search.
 86      * Currently you can only choose from "SiteTree" and "File", but a future version might improve this. 
 87      */
 88     function classesToSearch($classes) {
 89         $illegalClasses = array_diff($classes, array('SiteTree', 'File'));
 90         if($illegalClasses) {
 91             user_error("SearchForm::classesToSearch() passed illegal classes '" . implode("', '", $illegalClasses) . "'.  At this stage, only File and SiteTree are allowed", E_USER_WARNING);
 92         }
 93         $legalClasses = array_intersect($classes, array('SiteTree', 'File'));       
 94         $this->classesToSearch = $legalClasses;
 95     }
 96 
 97     /**
 98      * Return dataObjectSet of the results using $_REQUEST to get info from form.
 99      * Wraps around {@link searchEngine()}.
100      * 
101      * @param int $pageLength DEPRECATED 2.3 Use SearchForm->pageLength
102      * @param array $data Request data as an associative array. Should contain at least a key 'Search' with all searched keywords.
103      * @return DataObjectSet
104      */
105     public function getResults($pageLength = null, $data = null){
106         // legacy usage: $data was defaulting to $_REQUEST, parameter not passed in doc.silverstripe.org tutorials
107         if(!isset($data) || !is_array($data)) $data = $_REQUEST;
108         
109         // set language (if present)
110         if(singleton('SiteTree')->hasExtension('Translatable') && isset($data['locale'])) {
111             $origLocale = Translatable::get_current_locale();
112             Translatable::set_current_locale($data['locale']);
113         }
114 
115         if (self::$search_mode == 'morphy' && class_exists('SSMorphy')) {
116             // TODO 'слово-слово' (например Санкт-Петербург) -> ???, пока: 'слово слово'
117             $keywords = trim(preg_replace('/[^a-zA-Zа-яА-Я0-9\s]+/u', ' ', $data['Search']));
118             $keywords = SSMorphy::createSearchCriteria($keywords);
119         }
120         elseif (self::$search_mode == 'extended') {
121             // допускается +слово, -слово, "фраза как есть"
122             $keywords = trim(preg_replace('/[^a-zA-Zа-яА-Я0-9\s"+-]+/u', ' ', $data['Search']));
123             // 'слово+слово' -> 'слово +слово'
124             $keywords = preg_replace('/(\S)\+/u', '$1 +', $keywords);
125             // 'слово-слово' (например Санкт-Петербург) -> '"слово-слово"'
126             $keywords = preg_replace('/(\w+)-(\w+)/u', '"$1-$2"', $keywords);
127             // доводим кавычки до четного числа
128             if (substr_count($keywords, '"') % 2 > 0) {
129                 $keywords = $keywords . '"';
130             }
131             // любые окончания
132             $keywords = $this->addStarsToKeywords($keywords);
133         }
134         else {
135             // simple mode - режем все спецсимволы, для поиска в natural mode
136             $keywords = trim(preg_replace('/[^a-zA-Zа-яА-Я0-9\s]+/u', ' ', $data['Search']));
137         }
138 
139         if(!$pageLength) $pageLength = $this->pageLength;
140         $start = isset($_GET['start']) ? (int)$_GET['start'] : 0;
141 
142         if(strpos($keywords, '"') !== false || strpos($keywords, '+') !== false || strpos($keywords, '-') !== false || strpos($keywords, '*') !== false) {
143             $results = DB::getConn()->searchEngine($this->classesToSearch, $keywords, $start, $pageLength, "Relevance DESC", "", true);
144         } else {
145             $results = DB::getConn()->searchEngine($this->classesToSearch, $keywords, $start, $pageLength);
146         }
147         
148         // filter by permission
149         if($results) foreach($results as $result) {
150             if(!$result->canView()) {
151                 $results->remove($result);
152             }
153             else {
154                 // searchEngine() по-умолчанию вытаскивает только поля $ID, $Title, $Link и $Content
155                 // если $Link определен как метод зависящий от других полей (например от $LinkType в анонсах)
156                 // он будет определен неправильно - поэтому вытаскиваем объекты правильно
157                 $results->replace($result, DataObject::get_by_id($result->ClassName, $result->ID));
158             }
159         }
160         
161         // reset locale
162         if(singleton('SiteTree')->hasExtension('Translatable') && isset($data['locale'])) {
163             Translatable::set_current_locale($origLocale);
164         }
165 
166         return $results;
167     }
168 
169     /**
170      * Добавляет * в конец слов с учетом других значений boolean mode
171      * 
172      * @param string $keywords - строка для поиска
173      * 
174      * @return string
175      */
176     protected function addStarsToKeywords($keywords) {
177         if (!$keywords) return "";
178         $splitWords = preg_split("/\s+/" , $keywords);
179         while (list($i, $word) = each($splitWords)) {
180             if ($word[0] == '"') {
181                 // пропускаем до закрывающей кавычки
182                 while (list($i, $subword) = each($splitWords)) {
183                     $word .= ' ' . $subword;
184                     if (substr($subword,-1) == '"') break;
185                 }
186             } elseif ($word[0] == '(') {
187                 // пропускаем до закрывающей скобки
188                 while (list($i, $subword) = each($splitWords)) {
189                     $word .= ' ' . $subword;
190                     if (substr($subword,-1) == ')') break;
191                 }
192             } elseif ($word[0] != '+' && $word[0] != '-' && substr($word,-1) != '*') {
193                 $word .= '*';
194             }
195             $newWords[] = $word;
196         }
197         return implode(" ", $newWords);
198     }
199     
200     /**
201      * Get the search query for display in a "You searched for ..." sentence.
202      * 
203      * @param array $data
204      * @return string
205      */
206     public function getSearchQuery($data = null) {
207         // legacy usage: $data was defaulting to $_REQUEST, parameter not passed in doc.silverstripe.org tutorials
208         if(!isset($data)) $data = $_REQUEST;
209         
210         return Convert::raw2xml($data['Search']);
211     }
212     
213     /**
214      * Set the maximum number of records shown on each page.
215      * 
216      * @param int $length
217      */
218     public function setPageLength($length) {
219         $this->pageLength = $length;
220     }
221     
222     /**
223      * @return int
224      */
225     public function getPageLength() {
226         return $this->pageLength;
227     }
228 
229 }
230 
231 ?>
232 
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -
Webylon 3.1 API Docs API documentation generated by ApiGen 2.8.0