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

Packages

  • 1c
    • exchange
      • catalog
  • auth
  • Booking
  • building
    • company
  • cart
    • shipping
    • steppedcheckout
  • Catalog
    • monument
  • 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             $this->template,
 80             'SearchForm',
 81             'Form'
 82         ));
 83     }
 84 
 85     /**
 86      * Set the classes to search.
 87      * Currently you can only choose from "SiteTree" and "File", but a future version might improve this. 
 88      */
 89     function classesToSearch($classes) {
 90         $illegalClasses = array_diff($classes, array('SiteTree', 'File'));
 91         if($illegalClasses) {
 92             user_error("SearchForm::classesToSearch() passed illegal classes '" . implode("', '", $illegalClasses) . "'.  At this stage, only File and SiteTree are allowed", E_USER_WARNING);
 93         }
 94         $legalClasses = array_intersect($classes, array('SiteTree', 'File'));       
 95         $this->classesToSearch = $legalClasses;
 96     }
 97 
 98     /**
 99      * Return dataObjectSet of the results using $_REQUEST to get info from form.
100      * Wraps around {@link searchEngine()}.
101      * 
102      * @param int $pageLength DEPRECATED 2.3 Use SearchForm->pageLength
103      * @param array $data Request data as an associative array. Should contain at least a key 'Search' with all searched keywords.
104      * @return DataObjectSet
105      */
106     public function getResults($pageLength = null, $data = null){
107         // legacy usage: $data was defaulting to $_REQUEST, parameter not passed in doc.silverstripe.org tutorials
108         if(!isset($data) || !is_array($data)) $data = $_REQUEST;
109         
110         // set language (if present)
111         if(singleton('SiteTree')->hasExtension('Translatable') && isset($data['locale'])) {
112             $origLocale = Translatable::get_current_locale();
113             Translatable::set_current_locale($data['locale']);
114         }
115 
116         if (self::$search_mode == 'morphy' && class_exists('SSMorphy')) {
117             // TODO 'слово-слово' (например Санкт-Петербург) -> ???, пока: 'слово слово'
118             $keywords = trim(preg_replace('/[^a-zA-Zа-яА-Я0-9\s]+/u', ' ', $data['Search']));
119             $keywords = SSMorphy::createSearchCriteria($keywords);
120         }
121         elseif (self::$search_mode == 'extended') {
122             // допускается +слово, -слово, "фраза как есть"
123             $keywords = trim(preg_replace('/[^a-zA-Zа-яА-Я0-9\s"+-]+/u', ' ', $data['Search']));
124             // 'слово+слово' -> 'слово +слово'
125             $keywords = preg_replace('/(\S)\+/u', '$1 +', $keywords);
126             // 'слово-слово' (например Санкт-Петербург) -> '"слово-слово"'
127             $keywords = preg_replace('/(\w+)-(\w+)/u', '"$1-$2"', $keywords);
128             // доводим кавычки до четного числа
129             if (substr_count($keywords, '"') % 2 > 0) {
130                 $keywords = $keywords . '"';
131             }
132             // любые окончания
133             $keywords = $this->addStarsToKeywords($keywords);
134         }
135         else {
136             // simple mode - режем все спецсимволы, для поиска в natural mode
137             $keywords = trim(preg_replace('/[^a-zA-Zа-яА-Я0-9\s]+/u', ' ', $data['Search']));
138         }
139 
140         if(!$pageLength) $pageLength = $this->pageLength;
141         $start = isset($_GET['start']) ? (int)$_GET['start'] : 0;
142 
143         if(strpos($keywords, '"') !== false || strpos($keywords, '+') !== false || strpos($keywords, '-') !== false || strpos($keywords, '*') !== false) {
144             $results = DB::getConn()->searchEngine($this->classesToSearch, $keywords, $start, $pageLength, "Relevance DESC", "", true);
145         } else {
146             $results = DB::getConn()->searchEngine($this->classesToSearch, $keywords, $start, $pageLength);
147         }
148         
149         // filter by permission
150         if($results) foreach($results as $result) {
151             if(!$result->canView()) {
152                 $results->remove($result);
153             }
154             else {
155                 // searchEngine() по-умолчанию вытаскивает только поля $ID, $Title, $Link и $Content
156                 // если $Link определен как метод зависящий от других полей (например от $LinkType в анонсах)
157                 // он будет определен неправильно - поэтому вытаскиваем объекты правильно
158                 $results->replace($result, DataObject::get_by_id($result->ClassName, $result->ID));
159             }
160         }
161         
162         // reset locale
163         if(singleton('SiteTree')->hasExtension('Translatable') && isset($data['locale'])) {
164             Translatable::set_current_locale($origLocale);
165         }
166 
167         return $results;
168     }
169 
170     /**
171      * Добавляет * в конец слов с учетом других значений boolean mode
172      * 
173      * @param string $keywords - строка для поиска
174      * 
175      * @return string
176      */
177     protected function addStarsToKeywords($keywords) {
178         if (!$keywords) return "";
179         $splitWords = preg_split("/\s+/" , $keywords);
180         while (list($i, $word) = each($splitWords)) {
181             if ($word[0] == '"') {
182                 // пропускаем до закрывающей кавычки
183                 while (list($i, $subword) = each($splitWords)) {
184                     $word .= ' ' . $subword;
185                     if (substr($subword,-1) == '"') break;
186                 }
187             } elseif ($word[0] == '(') {
188                 // пропускаем до закрывающей скобки
189                 while (list($i, $subword) = each($splitWords)) {
190                     $word .= ' ' . $subword;
191                     if (substr($subword,-1) == ')') break;
192                 }
193             } elseif ($word[0] != '+' && $word[0] != '-' && substr($word,-1) != '*') {
194                 $word .= '*';
195             }
196             $newWords[] = $word;
197         }
198         return implode(" ", $newWords);
199     }
200     
201     /**
202      * Get the search query for display in a "You searched for ..." sentence.
203      * 
204      * @param array $data
205      * @return string
206      */
207     public function getSearchQuery($data = null) {
208         // legacy usage: $data was defaulting to $_REQUEST, parameter not passed in doc.silverstripe.org tutorials
209         if(!isset($data)) $data = $_REQUEST;
210         
211         return Convert::raw2xml($data['Search']);
212     }
213     
214     /**
215      * Set the maximum number of records shown on each page.
216      * 
217      * @param int $length
218      */
219     public function setPageLength($length) {
220         $this->pageLength = $length;
221     }
222     
223     /**
224      * @return int
225      */
226     public function getPageLength() {
227         return $this->pageLength;
228     }
229 
230 }
231 
232 ?>
233 
[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.2 API Docs API documentation generated by ApiGen 2.8.0