From bf7b180dfaf6f43dc0ba3596fc89653ef9f37bfe Mon Sep 17 00:00:00 2001 From: Martin Monperrus Date: Sun, 28 Oct 2012 18:41:16 +0100 Subject: [PATCH] release of Oct 27 2012 --- bibtexbrowser.php | 140 +++++++++++++++++++++++++++++----------------- 1 file changed, 90 insertions(+), 50 deletions(-) diff --git a/bibtexbrowser.php b/bibtexbrowser.php index 333160b..ae6a88e 100644 --- a/bibtexbrowser.php +++ b/bibtexbrowser.php @@ -1,5 +1,5 @@ + URL: http://www.monperrus.net/martin/bibtexbrowser/ Feedback & Bug Reports: martin.monperrus@gmail.com @@ -16,13 +16,15 @@ License, or (at your option) any later version. // added on Wednesday, June 01 2011, bug found by Carlos Bras if (!defined('BIBTEXBROWSER')) { // this if block ends at the very end of this file, after all class and function declarations. -define('BIBTEXBROWSER','v20120703'); +define('BIBTEXBROWSER','v20121027'); // *************** CONFIGURATION // I recommend to put your changes in bibtexbrowser.local.php // it will help you to upgrade the script with a new version -@include(dirname(__FILE__).'/bibtexbrowser.local.php'); +// the changes that require existing bibtexbrowser symbols should be in bibtexbrowser.after.php (included at the end of this file) +@include(preg_replace('/\.php$/','.local.php',__FILE__)); + // there is no encoding transformation from the bibtex file to the html file // if your bibtex file contains 8 bits characters in utf-8 // change the following parameter @@ -54,6 +56,10 @@ define('BIBTEXBROWSER','v20120703'); // Wrapper to use when we are included by another script @define('BIBTEXBROWSER_EMBEDDED_WRAPPER', 'NoWrapper'); + +// Wrapper to use when we are included by another script +@define('BIBTEXBROWSER_MAIN', 'Dispatcher'); + // default order functions @define('ORDER_FUNCTION','compare_bib_entry_by_year_and_month'); // can be @define('ORDER_FUNCTION','compare_bib_entry_by_title'); @@ -82,7 +88,7 @@ define('BIBTEXBROWSER','v20120703'); @define('Q_AUTHOR_PAGE', 'author_page'); @define('Q_TAG', 'keywords'); @define('Q_TAG_PAGE', 'keywords_page'); -@define('Q_TYPE', 'type'); +@define('Q_TYPE', 'type');// used for queries @define('Q_TYPE_PAGE', 'type_page'); @define('Q_ALL', 'all'); @define('Q_ENTRY', 'entry'); @@ -113,6 +119,9 @@ define('BIBTEXBROWSER','v20120703'); // *************** END CONFIGURATION +define('Q_INNER_AUTHOR', '_author');// internally used for representing the author +define('Q_INNER_TYPE', 'x-bibtex-type');// used for representing the type of the bibtex entry internally + // for clean search engine links // we disable url rewriting // ... and hope that your php configuration will accept one of these @@ -218,7 +227,8 @@ function _zetDB($bibtex_filenames) { // we try to save a "compiled" in a txt file $compiledbib = 'bibtexbrowser_'.md5($bibtex_filenames).'.dat'; - $parse=false; + $parse=filemtime(__FILE__)>filemtime($compiledbib); + foreach(explode(MULTIPLE_BIB_SEPARATOR, $bibtex_filenames) as $bib) { // do we have a compiled version ? if (is_file($compiledbib) @@ -699,13 +709,18 @@ class BibDBBuilder { // we add a timestamp $this->currentEntry->setTimestamp(); + // we add a key if there is no key + if (!$this->currentEntry->hasField(Q_KEY)) { + $this->currentEntry->setField(Q_KEY,md5($this->currentEntry->getTitle().implode('',$this->currentEntry->getRawAuthors()))); + } + // we set the fulltext $this->currentEntry->text = $entrysource; // we format the author names in a special field // to enable search if ($this->currentEntry->hasField('author')) { - $this->currentEntry->setField('_author',$this->currentEntry->getFormattedAuthorsImproved()); + $this->currentEntry->setField(Q_INNER_AUTHOR,$this->currentEntry->getFormattedAuthorsImproved()); } // ignoring jabref comments @@ -716,7 +731,7 @@ class BibDBBuilder { // we add it to the string database else if ($this->currentEntry->getType()=='string') { foreach($this->currentEntry->fields as $k => $v) { - $k!='type' and $this->stringdb[$k]=$v; + $k!=Q_INNER_TYPE and $this->stringdb[$k]=$v; } } @@ -913,12 +928,12 @@ class BibEntry { /** Returns the type of this bib entry. */ function getType() { // strtolower is important to be case-insensitive - return strtolower($this->getField(Q_TYPE)); + return strtolower($this->getField(Q_INNER_TYPE)); } /** Sets the key of this bib entry. */ function setKey($value) { - $this->setField('key',$value); + $this->setField(Q_KEY,$value); } /** Sets a field of this bib entry. */ @@ -944,7 +959,7 @@ class BibEntry { // to support space e.g. "@article {" // as generated by ams.org // thanks to Jacob Kellner - $this->fields[Q_TYPE] =trim($value); + $this->fields[Q_INNER_TYPE] =trim($value); } function setIndex($index) { $this->index = $index; } @@ -957,7 +972,7 @@ class BibEntry { } // echo $this->filename; // echo $this->getKey(); - return BIBTEXBROWSER_URL.'?'.createQueryString(array('key'=>$this->getKey(), Q_FILE=>$this->filename)); + return BIBTEXBROWSER_URL.'?'.createQueryString(array(Q_KEY=>$this->getKey(), Q_FILE=>$this->filename)); } /** Tries to build a good absolute URL for this entry */ @@ -1011,7 +1026,7 @@ class BibEntry { /** Returns the key of this entry */ function getKey() { - return $this->getField('key'); + return $this->getField(Q_KEY); } /** Returns the title of this entry? */ @@ -1081,7 +1096,7 @@ class BibEntry { } - /** Returns the authors as a string depending on the configuration parameter COMMA_NAMES */ + /** Returns the authors as an array of strings (one string per author) */ function getFormattedAuthors() { $authors = array(); foreach ($this->getRawAuthors() as $author) { @@ -1130,7 +1145,7 @@ class BibEntry { * all author names except for the first one and appending ", et al." */ function getCompactedAuthors($author){ - $authors = $this->getAuthors(); + $authors = $this->getRawAuthors(); $etal = count($authors) > 1 ? ', et al.' : ''; return $this->formatAuthor($authors[0]) . $etal; } @@ -1225,7 +1240,7 @@ class BibEntry { return $this->text; } - /** Returns true if this bib entry contains the given phrase + /** Returns true if this bib entry contains the given phrase (PREG regexp) * in the given field. if $field is null, all fields are considered. * Note that this method is NOT case sensitive */ function hasPhrase($phrase, $field = null) { @@ -1484,13 +1499,18 @@ return array( // Books array( - 'query' => array(Q_TYPE=>'book'), + 'query' => array(Q_TYPE=>'book|proceedings'), 'title' => 'Books' ), + // Book chapters + array( + 'query' => array(Q_TYPE=>'incollection|inbook'), + 'title' => 'Book Chapters' + ), // Journal / Bookchapters array( - 'query' => array(Q_TYPE=>'article|incollection'), - 'title' => 'Refereed Articles and Book Chapters' + 'query' => array(Q_TYPE=>'article'), + 'title' => 'Refereed Articles' ), // conference papers array( @@ -1730,7 +1750,9 @@ function createQueryString($array_param) { } // then a simple transformation and implode foreach ($array_param as $key => $val) { - if($key == '_author') { $key = 'author'; } + // the inverse transformation should also be implemented into query2title + if($key == Q_INNER_AUTHOR) { $key = Q_AUTHOR; } + if($key == Q_INNER_TYPE) { $key = Q_TYPE; } $array_param[$key]=$key .'='. urlencode($val); } return implode("&",$array_param); @@ -1800,7 +1822,7 @@ class IndependentYearMenu { function poweredby() { $poweredby = "\n".'
'; $poweredby .= ''; - $poweredby .= 'Powered by bibtexbrowser'; + $poweredby .= 'Powered by bibtexbrowser'; $poweredby .= '
'."\n"; return $poweredby; } @@ -1920,14 +1942,14 @@ class MenuManager { foreach ($this->db->getTypes() as $type) { $types[$type] = $type; } - $types[''] = 'all types'; + $types['.*'] = 'all types'; // retreive or calculate page number to display if (isset($_GET[Q_TYPE_PAGE])) { $page = $_GET[Q_TYPE_PAGE]; } else $page = 1; - $this->displayMenu('Types', $types, $page, $this->type_size, Q_TYPE_PAGE, Q_TYPE); + $this->displayMenu('Types', $types, $page, $this->type_size, Q_TYPE_PAGE, Q_INNER_TYPE); } /** Displays and controls the authors menu in a table. */ @@ -2055,7 +2077,7 @@ else $page = 1; * the end index (exclusive). For each menu, the following form of * string is printed: * - * + * * Cheon, Yoonsik *
*/ @@ -2072,12 +2094,18 @@ else $page = 1; } } +if (!function_exists('query2title')) { /** transforms an array representing a query into a formatted string */ function query2title(&$query) { $headers = array(); foreach($query as $k=>$v) { - if($k == '_author') { $k = 'author'; } - if($k == 'type') { $v = substr($v,1,strlen($v)-2); } + if($k == Q_INNER_AUTHOR) { $k = 'author'; } + if($k == Q_INNER_TYPE) { + // we changed from x-bibtex-type to type + $k = 'type'; + // and we remove the regexp modifiers ^ $ + $v = preg_replace('/[$^]/','',$v); + } $headers[$k] = ucwords($k).': '.ucwords($v); } // special cases @@ -2085,7 +2113,7 @@ function query2title(&$query) { if (isset($headers[Q_AUTHOR])) $headers[Q_AUTHOR] = 'Publications of '.$_GET[Q_AUTHOR]; return join(' & ',$headers); } - +} /** displays the latest modified bibtex entries. usage: @@ -2297,11 +2325,12 @@ class AcademicDisplay { } /** transforms a query to HTML - * $ query is an array (e.g. array(Q_TYPE=>'book')) + * $ query is an array (e.g. array(Q_YEAR=>'2005')) * $title is a string, the title of the section */ function search2html($query, $title) { $entries = $this->db->multisearch($query); + uasort($entries, ORDER_FUNCTION); if (count($entries)>0) { echo "\n".'
'.$title.'
'."\n"; @@ -2768,6 +2797,7 @@ class BibDataBase { foreach ($this->bibdb as $bib) { $entryisselected = true; foreach ($query as $field => $fragment) { + $field = strtolower($field); if ($field==Q_SEARCH) { // we search in the whole bib entry if (!$bib->hasPhrase($fragment)) { @@ -2779,6 +2809,16 @@ class BibDataBase { $entryisselected = false; } } + else if ($field==Q_TYPE || $field==Q_INNER_TYPE) { + // types are always exact search + // remarks Ken + // type:"book" should only select book (and not inbook, book, bookchapter) + // this was before in Dispatch:type() + // moved here so that it is also used by AcademicDisplay:search2html() + if (!$bib->hasPhrase('^('.$fragment.')$', Q_INNER_TYPE)) { + $entryisselected = false; + } + } else { if (!$bib->hasPhrase($fragment, $field)) { $entryisselected = false; @@ -2898,10 +2938,12 @@ function bibtexbrowserDefaultCSS() { font-family: monospace; font-size: small; border: 1px solid #DDDDDD; - white-space:pre; background: none repeat scroll 0 0 #F5F5F5; padding:10px; + overflow:auto; + width:600px; + clear:both; } .bibentry-by { font-style: italic; } @@ -2941,7 +2983,7 @@ echo ' - + getRSS()!='') echo ''; ?> @@ -3203,7 +3245,7 @@ class RSSDisplay { http:// - bibtexbrowser v20120703 + bibtexbrowser v20121027 entries as $bibentry) { @@ -3239,7 +3281,8 @@ usage: // simulating ?bib=metrics.bib&year=2009 $_GET['bib']='metrics.bib'; $_GET['year']='2006'; - new Dispatcher(); + $x = new Dispatcher(); + $x->main(); */ class Dispatcher { @@ -3257,7 +3300,9 @@ class Dispatcher { */ var $wrapper = 'HTMLWrapper'; - function Dispatcher() { + function Dispatcher() {} + + function main() { // are we in test mode, or libray mode // then this file is just a library if (isset($_GET['test']) || isset($_GET['library'])) { @@ -3268,7 +3313,7 @@ class Dispatcher { } // first we set the database (load from disk or parse the bibtex file) - setDB(); + if (!isset($_GET[Q_DB])) { setDB(); } // is the publication list included in another page? // strtr is used for Windows where __FILE__ contains C:\toto and SCRIPT_FILENAME contains C:/toto (bug reported by Marco) @@ -3302,6 +3347,7 @@ class Dispatcher { //echo '
';print_r($selectedEntries);echo '
'; + if ($this->displayer=='') { $this->displayer = BIBTEXBROWSER_DEFAULT_DISPLAY; } @@ -3309,13 +3355,14 @@ class Dispatcher { // do we have a displayer? if ($this->displayer!='') { - + $options = array(); if (isset($_GET['dopt'])) { $options = json_decode($_GET['dopt'],true); } // required for PHP4 to have this intermediate variable + $x = new $this->displayer(); if (method_exists($x,'setEntries')) { @@ -3330,10 +3377,6 @@ class Dispatcher { $x->setQuery($this->query); } - if (method_exists($x,'setWrapper')) { - $x->setWrapper($this); - } - // should call method display() on $x new $this->wrapper($x); @@ -3397,17 +3440,12 @@ class Dispatcher { function author() { // Friday, October 29 2010 - // changed fomr 'author' to '_author' - // because '_author' is already formatted - // doing so we can search at the same time "Joe Dupont" an "Dupont, Joe" - $this->query['_author']=$_GET[Q_AUTHOR]; + // changed from 'author' to '_author' + // in order to search at the same time "Joe Dupont" an "Dupont, Joe" + $this->query[Q_INNER_AUTHOR]=$_GET[Q_AUTHOR]; } function type() { - // remarks KEN - // "book" selects inbook, book, bookchapter - // so we add the regexp modifiers - if (strlen($_GET[Q_TYPE])>0 && !preg_match('/^\^.*\$$/',$_GET[Q_TYPE])) { $_GET[Q_TYPE] = '^'.$_GET[Q_TYPE].'$'; } $this->query[Q_TYPE]= $_GET[Q_TYPE]; } @@ -3461,7 +3499,7 @@ class Dispatcher { function diagnosis() { header('Content-type: text/plain'); echo "php version: ".phpversion()."\n"; - echo "bibtexbrowser version: 20120703\n"; + echo "bibtexbrowser version: 20121027\n"; echo "dir: ".decoct(fileperms(dirname(__FILE__)))."\n"; echo "bibtex file: ".decoct(fileperms($_GET[Q_FILE]))."\n"; exit; @@ -3473,7 +3511,7 @@ class Dispatcher { - + You are browsing <?php echo $_GET[Q_FILE]; ?> with bibtexbrowser @@ -3491,6 +3529,8 @@ class Dispatcher { } // end if (!defined('BIBTEXBROWSER')) -new Dispatcher(); - +@include(preg_replace('/\.php$/','.after.php',__FILE__)); +$class = BIBTEXBROWSER_MAIN;// extension point +$main = new $class(); +$main->main(); ?> \ No newline at end of file