mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
FEATURE Supporting search for special characters like umlauts in SearchForm. These characters are encoded to HTML entities by TinyMCE for SiteTree->Content, hence we need a special case in the search logic (incl. unit tests)
ENHANCEMENT Added MySQL FULLTEXT index for $Content property on SiteTree, Needs separate indexing to be searchable by SearchForm - $Content is the only field which has special characters encoded as HTML entities (through TinyMCE) git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@70328 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
4c4926d2b9
commit
2956cc482f
@ -88,6 +88,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
static $indexes = array(
|
static $indexes = array(
|
||||||
"SearchFields" => Array('type'=>'fulltext', 'value'=>'Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords'),
|
"SearchFields" => Array('type'=>'fulltext', 'value'=>'Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords'),
|
||||||
"TitleSearchFields" => Array('type'=>'fulltext', 'value'=>'Title'),
|
"TitleSearchFields" => Array('type'=>'fulltext', 'value'=>'Title'),
|
||||||
|
"ContentSearchFields" => Array('type'=>'fulltext', 'value'=>'Content'),
|
||||||
"URLSegment" => true,
|
"URLSegment" => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -150,14 +150,15 @@ class SearchForm extends Form {
|
|||||||
public function searchEngine($keywords, $pageLength = null, $sortBy = "Relevance DESC", $extraFilter = "", $booleanSearch = false, $alternativeFileFilter = "", $invertedMatch = false) {
|
public function searchEngine($keywords, $pageLength = null, $sortBy = "Relevance DESC", $extraFilter = "", $booleanSearch = false, $alternativeFileFilter = "", $invertedMatch = false) {
|
||||||
if(!$pageLength) $pageLength = $this->pageLength;
|
if(!$pageLength) $pageLength = $this->pageLength;
|
||||||
$fileFilter = '';
|
$fileFilter = '';
|
||||||
$keywords = addslashes($keywords);
|
|
||||||
|
$keywords = Convert::raw2sql($keywords);
|
||||||
|
$htmlEntityKeywords = htmlentities($keywords);
|
||||||
|
|
||||||
if($booleanSearch) $boolean = "IN BOOLEAN MODE";
|
if($booleanSearch) $boolean = "IN BOOLEAN MODE";
|
||||||
|
|
||||||
if($extraFilter) {
|
if($extraFilter) {
|
||||||
$extraFilter = " AND $extraFilter";
|
$extraFilter = " AND $extraFilter";
|
||||||
|
$fileFilter = ($alternativeFileFilter) ? " AND $alternativeFileFilter" : $extraFilter;
|
||||||
if($alternativeFileFilter) $fileFilter = " AND $alternativeFileFilter";
|
|
||||||
else $fileFilter = $extraFilter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->showInSearchTurnOn) $extraFilter .= " AND showInSearch <> 0";
|
if($this->showInSearchTurnOn) $extraFilter .= " AND showInSearch <> 0";
|
||||||
@ -167,12 +168,20 @@ class SearchForm extends Form {
|
|||||||
|
|
||||||
$notMatch = $invertedMatch ? "NOT " : "";
|
$notMatch = $invertedMatch ? "NOT " : "";
|
||||||
if($keywords) {
|
if($keywords) {
|
||||||
$matchContent = "MATCH (Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords) AGAINST ('$keywords' $boolean)";
|
$matchContent = "
|
||||||
|
MATCH (Title, MenuTitle, MetaTitle, MetaDescription, MetaKeywords) AGAINST ('$keywords' $boolean)
|
||||||
|
+ MATCH (Content) AGAINST ('$htmlEntityKeywords' $boolean)
|
||||||
|
";
|
||||||
$matchFile = "MATCH (Filename, Title, Content) AGAINST ('$keywords' $boolean) AND ClassName = 'File'";
|
$matchFile = "MATCH (Filename, Title, Content) AGAINST ('$keywords' $boolean) AND ClassName = 'File'";
|
||||||
|
|
||||||
// We make the relevance search by converting a boolean mode search into a normal one
|
// We make the relevance search by converting a boolean mode search into a normal one
|
||||||
$relevanceKeywords = str_replace(array('*','+','-'),'',$keywords);
|
$relevanceKeywords = str_replace(array('*','+','-'),'',$keywords);
|
||||||
$relevanceContent = "MATCH (Title) AGAINST ('$relevanceKeywords') + MATCH (Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords) AGAINST ('$relevanceKeywords')";
|
$htmlEntityRelevanceKeywords = str_replace(array('*','+','-'),'',$htmlEntityKeywords);
|
||||||
|
$relevanceContent = "
|
||||||
|
MATCH (Title) AGAINST ('$relevanceKeywords')
|
||||||
|
+ MATCH(Content) AGAINST ('$htmlEntityRelevanceKeywords')
|
||||||
|
+ MATCH (Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords) AGAINST ('$relevanceKeywords')
|
||||||
|
";
|
||||||
$relevanceFile = "MATCH (Filename, Title, Content) AGAINST ('$relevanceKeywords')";
|
$relevanceFile = "MATCH (Filename, Title, Content) AGAINST ('$relevanceKeywords')";
|
||||||
} else {
|
} else {
|
||||||
$relevanceContent = $relevanceFile = 1;
|
$relevanceContent = $relevanceFile = 1;
|
||||||
|
@ -18,7 +18,7 @@ class SearchFormTest extends FunctionalTest {
|
|||||||
$holderPage = $this->objFromFixture('SiteTree', 'searchformholder');
|
$holderPage = $this->objFromFixture('SiteTree', 'searchformholder');
|
||||||
$this->mockController = new ContentController($holderPage);
|
$this->mockController = new ContentController($holderPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPublishedPagesMatchedByTitle() {
|
function testPublishedPagesMatchedByTitle() {
|
||||||
$sf = new SearchForm($this->mockController, 'SearchForm');
|
$sf = new SearchForm($this->mockController, 'SearchForm');
|
||||||
|
|
||||||
@ -134,5 +134,26 @@ class SearchFormTest extends FunctionalTest {
|
|||||||
'Page with "Show in Search" disabled doesnt show'
|
'Page with "Show in Search" disabled doesnt show'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testSearchTitleAndContentWithSpecialCharacters() {
|
||||||
|
$sf = new SearchForm($this->mockController, 'SearchForm');
|
||||||
|
|
||||||
|
$pageWithSpecialChars = $this->objFromFixture('SiteTree', 'pageWithSpecialChars');
|
||||||
|
$pageWithSpecialChars->publish('Stage', 'Live');
|
||||||
|
|
||||||
|
$results = $sf->getResults(null, array('Search'=>'Brötchen'));
|
||||||
|
$this->assertContains(
|
||||||
|
$pageWithSpecialChars->ID,
|
||||||
|
$results->column('ID'),
|
||||||
|
'Published pages with umlauts in title are found'
|
||||||
|
);
|
||||||
|
|
||||||
|
$results = $sf->getResults(null, array('Search'=>'Bäcker'));
|
||||||
|
$this->assertContains(
|
||||||
|
$pageWithSpecialChars->ID,
|
||||||
|
$results->column('ID'),
|
||||||
|
'Published pages with htmlencoded umlauts in content are found'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
@ -30,4 +30,7 @@ SiteTree:
|
|||||||
Title: inheritRestrictedView
|
Title: inheritRestrictedView
|
||||||
dontShowInSearchPage:
|
dontShowInSearchPage:
|
||||||
Title: dontShowInSearchPage
|
Title: dontShowInSearchPage
|
||||||
ShowInSearch: 0
|
ShowInSearch: 0
|
||||||
|
pageWithSpecialChars:
|
||||||
|
Title: Brötchen
|
||||||
|
Content: Frisch vom Bäcker
|
Loading…
x
Reference in New Issue
Block a user