2011-03-18 03:29:59 +01:00
< ? php
2016-06-16 06:57:19 +02:00
use SilverStripe\ORM\DB ;
use SilverStripe\ORM\SS_List ;
2011-03-18 03:29:59 +01:00
/**
* Standard basic search form which conducts a fulltext search on all { @ link SiteTree }
2016-01-06 00:42:07 +01:00
* objects .
2011-03-18 03:29:59 +01:00
*
* If multilingual content is enabled through the { @ link Translatable } extension ,
* only pages the currently set language on the holder for this searchform are found .
* The language is set through a hidden field in the form , which is prepoluated
* with { @ link Translatable :: get_current_locale ()} when then form is constructed .
2016-01-06 00:42:07 +01:00
*
2011-03-18 03:29:59 +01:00
* @ see Use ModelController and SearchContext for a more generic search implementation based around DataObject
* @ package cms
* @ subpackage search
*/
class SearchForm extends Form {
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
/**
* @ var int $pageLength How many results are shown per page .
* Relies on pagination being implemented in the search results template .
*/
protected $pageLength = 10 ;
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
/**
* Classes to search
2016-03-08 21:50:55 +01:00
*/
2011-03-18 03:29:59 +01:00
protected $classesToSearch = array (
" SiteTree " , " File "
);
2016-03-08 21:50:55 +01:00
2014-04-30 01:05:25 +02:00
private static $casting = array (
'SearchQuery' => 'Text'
);
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
/**
2016-01-06 00:42:07 +01:00
*
2011-03-18 03:29:59 +01:00
* @ param Controller $controller
* @ param string $name The name of the form ( used in URL addressing )
2011-10-26 07:35:51 +02:00
* @ param FieldList $fields Optional , defaults to a single field named " Search " . Search logic needs to be customized
2011-03-18 03:29:59 +01:00
* if fields are added to the form .
2011-10-26 07:35:51 +02:00
* @ param FieldList $actions Optional , defaults to a single field named " Go " .
2011-03-18 03:29:59 +01:00
*/
2012-09-19 12:07:46 +02:00
public function __construct ( $controller , $name , $fields = null , $actions = null ) {
2011-03-18 03:29:59 +01:00
if ( ! $fields ) {
2011-10-26 07:35:51 +02:00
$fields = new FieldList (
2011-03-18 03:29:59 +01:00
new TextField ( 'Search' , _t ( 'SearchForm.SEARCH' , 'Search' )
));
}
2016-03-08 21:50:55 +01:00
2011-03-22 09:30:10 +01:00
if ( class_exists ( 'Translatable' ) && singleton ( 'SiteTree' ) -> hasExtension ( 'Translatable' )) {
2013-05-11 09:29:47 +02:00
$fields -> push ( new HiddenField ( 'searchlocale' , 'searchlocale' , Translatable :: get_current_locale ()));
2011-03-18 03:29:59 +01:00
}
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
if ( ! $actions ) {
2011-10-26 07:35:51 +02:00
$actions = new FieldList (
2011-03-18 03:29:59 +01:00
new FormAction ( " getResults " , _t ( 'SearchForm.GO' , 'Go' ))
);
}
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
parent :: __construct ( $controller , $name , $fields , $actions );
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
$this -> setFormMethod ( 'get' );
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
$this -> disableSecurityToken ();
}
2016-03-08 21:50:55 +01:00
2014-10-03 06:08:47 +02:00
/**
* Return a rendered version of this form .
2016-01-06 00:42:07 +01:00
*
2014-10-03 06:08:47 +02:00
* This is returned when you access a form as $FormObject rather
* than <% with FormObject %>
*/
2011-03-18 03:29:59 +01:00
public function forTemplate () {
2014-10-03 06:08:47 +02:00
$return = $this -> renderWith ( array_merge (
( array ) $this -> getTemplate (),
array ( 'SearchForm' , 'Form' )
2011-03-18 03:29:59 +01:00
));
2014-10-03 06:08:47 +02:00
// Now that we're rendered, clear message
$this -> clearMessage ();
return $return ;
2011-03-18 03:29:59 +01:00
}
/**
* Set the classes to search .
2016-01-06 00:42:07 +01:00
* Currently you can only choose from " SiteTree " and " File " , but a future version might improve this .
2011-03-18 03:29:59 +01:00
*/
2012-09-19 12:07:46 +02:00
public function classesToSearch ( $classes ) {
2011-03-18 03:29:59 +01:00
$illegalClasses = array_diff ( $classes , array ( 'SiteTree' , 'File' ));
if ( $illegalClasses ) {
user_error ( " SearchForm::classesToSearch() passed illegal classes ' " . implode ( " ', ' " , $illegalClasses ) . " '. At this stage, only File and SiteTree are allowed " , E_USER_WARNING );
}
2016-03-08 21:50:55 +01:00
$legalClasses = array_intersect ( $classes , array ( 'SiteTree' , 'File' ));
2011-03-18 03:29:59 +01:00
$this -> classesToSearch = $legalClasses ;
}
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
/**
* Get the classes to search
*
* @ return array
*/
2012-09-19 12:07:46 +02:00
public function getClassesToSearch () {
2016-01-06 00:42:07 +01:00
return $this -> classesToSearch ;
2011-03-18 03:29:59 +01:00
}
/**
* Return dataObjectSet of the results using $_REQUEST to get info from form .
* Wraps around { @ link searchEngine ()} .
2016-01-06 00:42:07 +01:00
*
2011-03-18 03:29:59 +01:00
* @ param int $pageLength DEPRECATED 2.3 Use SearchForm -> pageLength
* @ param array $data Request data as an associative array . Should contain at least a key 'Search' with all searched keywords .
2011-10-26 08:10:19 +02:00
* @ return SS_List
2011-03-18 03:29:59 +01:00
*/
public function getResults ( $pageLength = null , $data = null ){
// legacy usage: $data was defaulting to $_REQUEST, parameter not passed in doc.silverstripe.org tutorials
if ( ! isset ( $data ) || ! is_array ( $data )) $data = $_REQUEST ;
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
// set language (if present)
2013-05-11 09:29:47 +02:00
if ( class_exists ( 'Translatable' )) {
if ( singleton ( 'SiteTree' ) -> hasExtension ( 'Translatable' ) && isset ( $data [ 'searchlocale' ])) {
if ( $data [ 'searchlocale' ] == " ALL " ) {
Translatable :: disable_locale_filter ();
} else {
$origLocale = Translatable :: get_current_locale ();
Translatable :: set_current_locale ( $data [ 'searchlocale' ]);
}
}
2011-03-18 03:29:59 +01:00
}
2013-05-11 09:29:47 +02:00
2011-03-18 03:29:59 +01:00
$keywords = $data [ 'Search' ];
$andProcessor = create_function ( '$matches' , '
return " + " . $matches [ 2 ] . " + " . $matches [ 4 ] . " " ;
' );
$notProcessor = create_function ( '$matches' , '
return " - " . $matches [ 3 ];
' );
$keywords = preg_replace_callback ( '/()("[^()"]+")( and )("[^"()]+")()/i' , $andProcessor , $keywords );
$keywords = preg_replace_callback ( '/(^| )([^() ]+)( and )([^ ()]+)( |$)/i' , $andProcessor , $keywords );
$keywords = preg_replace_callback ( '/(^| )(not )("[^"()]+")/i' , $notProcessor , $keywords );
$keywords = preg_replace_callback ( '/(^| )(not )([^() ]+)( |$)/i' , $notProcessor , $keywords );
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
$keywords = $this -> addStarsToKeywords ( $keywords );
if ( ! $pageLength ) $pageLength = $this -> pageLength ;
$start = isset ( $_GET [ 'start' ]) ? ( int ) $_GET [ 'start' ] : 0 ;
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
if ( strpos ( $keywords , '"' ) !== false || strpos ( $keywords , '+' ) !== false || strpos ( $keywords , '-' ) !== false || strpos ( $keywords , '*' ) !== false ) {
2013-06-21 00:45:33 +02:00
$results = DB :: get_conn () -> searchEngine ( $this -> classesToSearch , $keywords , $start , $pageLength , " \" Relevance \" DESC " , " " , true );
2011-03-18 03:29:59 +01:00
} else {
2013-06-21 00:45:33 +02:00
$results = DB :: get_conn () -> searchEngine ( $this -> classesToSearch , $keywords , $start , $pageLength );
2011-03-18 03:29:59 +01:00
}
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
// filter by permission
if ( $results ) foreach ( $results as $result ) {
if ( ! $result -> canView ()) $results -> remove ( $result );
}
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
// reset locale
2013-05-11 09:29:47 +02:00
if ( class_exists ( 'Translatable' )) {
if ( singleton ( 'SiteTree' ) -> hasExtension ( 'Translatable' ) && isset ( $data [ 'searchlocale' ])) {
if ( $data [ 'searchlocale' ] == " ALL " ) {
Translatable :: enable_locale_filter ();
} else {
Translatable :: set_current_locale ( $origLocale );
}
}
2011-03-18 03:29:59 +01:00
}
return $results ;
}
protected function addStarsToKeywords ( $keywords ) {
if ( ! trim ( $keywords )) return " " ;
// Add * to each keyword
$splitWords = preg_split ( " / +/ " , trim ( $keywords ));
while ( list ( $i , $word ) = each ( $splitWords )) {
if ( $word [ 0 ] == '"' ) {
while ( list ( $i , $subword ) = each ( $splitWords )) {
$word .= ' ' . $subword ;
if ( substr ( $subword , - 1 ) == '"' ) break ;
}
} else {
$word .= '*' ;
}
$newWords [] = $word ;
}
return implode ( " " , $newWords );
}
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
/**
* Get the search query for display in a " You searched for ... " sentence .
2016-01-06 00:42:07 +01:00
*
2011-03-18 03:29:59 +01:00
* @ param array $data
* @ return string
*/
public function getSearchQuery ( $data = null ) {
// legacy usage: $data was defaulting to $_REQUEST, parameter not passed in doc.silverstripe.org tutorials
if ( ! isset ( $data )) $data = $_REQUEST ;
2016-03-08 21:50:55 +01:00
2012-07-20 04:04:52 +02:00
// The form could be rendered without the search being done, so check for that.
2014-04-30 01:05:25 +02:00
if ( isset ( $data [ 'Search' ])) return $data [ 'Search' ];
2011-03-18 03:29:59 +01:00
}
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
/**
* Set the maximum number of records shown on each page .
2016-01-06 00:42:07 +01:00
*
2011-03-18 03:29:59 +01:00
* @ param int $length
*/
public function setPageLength ( $length ) {
$this -> pageLength = $length ;
}
2016-03-08 21:50:55 +01:00
2011-03-18 03:29:59 +01:00
/**
* @ return int
*/
public function getPageLength () {
return $this -> pageLength ;
}
}
2012-02-13 21:40:49 +01:00