diff --git a/BibtexbrowserTest.php b/BibtexbrowserTest.php index 1d97897..9e5434d 100755 --- a/BibtexbrowserTest.php +++ b/BibtexbrowserTest.php @@ -78,7 +78,7 @@ class BibtexbrowserTest extends PHPUnit_Framework_TestCase { function createDB() { return $this->_createDB("@book{aKey,title={A Book},author={Martin Monperrus},publisher={Springer},year=2009}\n" - ."@book{aKey/withSlash,title={Slash Dangerous for web servers},author={Ap Ache},publisher={Springer},year=2010}\n" + ."@book{aKey/withSlash,title={Slash Dangerous for web servers},author={Ap Ache},editor={Martin Monperrus},publisher={Springer},year=2010}\n" ."@article{aKeyA,title={An Article},author={Foo Bar and Jane Doe},volume=5,journal=\"New Results\",year=2009,pages={1-2}}\n"); } @@ -187,6 +187,31 @@ class BibtexbrowserTest extends PHPUnit_Framework_TestCase { $this->assertTrue($entry->getTitle() == 'A Book'); } + function testMultiSearch_name_match() { + $btb = $this->createDB(); + $q=array(Q_NAME=>'Martin Monperrus'); + $results=$btb->multisearch($q); + $this->assertTrue(count($results) == 2); + } + + function testMultiSearch_author_name_match() { + $btb = $this->createDB(); + $q=array(Q_AUTHOR_NAME=>'Martin Monperrus'); + $results=$btb->multisearch($q); + $entry = $results[0]; + $this->assertTrue(count($results) == 1); + $this->assertTrue($entry->getTitle() == 'A Book'); + } + + function testMultiSearch_editor_name_match() { + $btb = $this->createDB(); + $q=array(Q_EDITOR_NAME=>'Martin Monperrus'); + $results=$btb->multisearch($q); + $entry = $results[0]; + $this->assertTrue(count($results) == 1); + $this->assertTrue($entry->getTitle() == 'Slash Dangerous for web servers'); + } + function test_config_value() { // default value $this->assertFalse(config_value('BIBTEXBROWSER_NO_DEFAULT')); diff --git a/bibtexbrowser.php b/bibtexbrowser.php index 762ef90..fc9e27a 100755 --- a/bibtexbrowser.php +++ b/bibtexbrowser.php @@ -243,6 +243,10 @@ define('Q_INNER_AUTHOR', '_author');// internally used for representing the auth define('Q_INNER_TYPE', 'x-bibtex-type');// used for representing the type of the bibtex entry internally @define('Q_INNER_KEYS_INDEX', '_keys-index');// used for storing indices in $_GET[Q_KEYS] array +define('Q_NAME', 'name');// used to allow for exact last name matches in multisearch +define('Q_AUTHOR_NAME', 'author_name');// used to allow for exact last name matches in multisearch +define('Q_EDITOR_NAME', 'editor_name');// used to allow for exact last name matches in multisearch + // for clean search engine links // we disable url rewriting // ... and hope that your php configuration will accept one of these @@ -1487,12 +1491,18 @@ class BibEntry { /** Returns the authors of this entry as an array (split by " and ") */ function getRawAuthors() { - return $this->split_authors(); + return $this->split_names(Q_AUTHOR); } - function split_authors() { - if (!array_key_exists(Q_AUTHOR, $this->raw_fields)) return array(); - $array = preg_split('/ and( |$)/ims', @$this->raw_fields[Q_AUTHOR]); + // Previously called split_authors. Made generic to allow call on editors as well. + function split_names($key) { + if (!array_key_exists($key, $this->raw_fields)) return array(); + + // Sometimes authors/editors are split by line breaks followed by whitespace in bib files. + // In this case we need to replace these with a normal space. + $raw = preg_replace( '/\s+/', ' ', @$this->raw_fields[$key]); + $array = preg_split('/ and( |$)/ims', $raw); + $res = array(); // we merge the remaining ones for ($i=0; $i < count($array)-1; $i++) { @@ -1689,6 +1699,12 @@ class BibEntry { return $editors; } + + /** Returns the editors of this entry as an array (split by " and ") */ + function getRawEditors() { + return $this->split_names(EDITOR); + } + /** Returns the editors of this entry as an arry */ function getFormattedEditors() { $editors = array(); @@ -4037,6 +4053,31 @@ class BibDataBase { break; } } + else if ($field==Q_NAME || $field==Q_AUTHOR_NAME || $field==Q_EDITOR_NAME) { + // Names require exact matching per name. Although a preg_match over the entire author field is possible, + // it's inconvenient and often results in unwanted matches if not done careful. Instead, use + // 'name'=>'(M. Monperrus|Monperrus, M.)' to exact match the name of an author or editor, use + // 'author_name' to match the name of an author, and use 'editor_name' to match the name of an editor. + $names = []; + if ($field==Q_NAME || $field==Q_AUTHOR_NAME) + $names = array_merge($bib->getRawAuthors(), $names); + if ($field==Q_NAME || $field==Q_EDITOR_NAME) + $names = array_merge($bib->getRawEditors(), $names); + + if (empty($names)) { + $entryisselected = false; + } else { + foreach ($names as $name) { + $entryisselected = preg_match('/^' . $fragment . '$/', trim($name)); + if ($entryisselected) { + break; + } + } + } + if (!$entryisselected) { + break; + } + } else if ($field==Q_KEYS) { if ( ! in_array( $bib->getKey(), $query[Q_KEYS] ) ) { $entryisselected = false;